feat(cli): add --skip-skills and --index-only flags to analyze command

The `installSkills()` call in `generateAIContextFiles()` runs
unconditionally, injecting 6 skill files into `.claude/skills/gitnexus/`
even when `--skip-agents-md` is passed. This is problematic for bulk
indexing operations on read-only mirrors or third-party repos.

Add two new flags:
- `--skip-skills`: suppress standard GitNexus skill file injection
- `--index-only`: pure index mode that suppresses all file injection
  (AGENTS.md, CLAUDE.md, and skills), writing only to `.gitnexus/`

This gives users three levels of control:
- `--skip-agents-md` — suppress only root context files
- `--skip-skills` — suppress only skill injection
- `--index-only` — suppress everything (pure indexing)

Discovery context: while bulk-indexing 176 repos with
`--skip-agents-md`, all 144 indexed repos were contaminated with
`.claude/skills/gitnexus/` files requiring manual cleanup.
This commit is contained in:
alex@plexifact.io 2026-04-08 13:52:43 -07:00
parent d69eadfb7f
commit 666f87f8c7
4 changed files with 31 additions and 7 deletions

View file

@ -28,6 +28,7 @@ interface RepoStats {
export interface AIContextOptions {
skipAgentsMd?: boolean;
noStats?: boolean;
skipSkills?: boolean;
}
const GITNEXUS_START_MARKER = '<!-- gitnexus:start -->';
@ -337,10 +338,14 @@ export async function generateAIContextFiles(
createdFiles.push('CLAUDE.md (skipped via --skip-agents-md)');
}
// Install skills to .claude/skills/gitnexus/
const installedSkills = await installSkills(repoPath);
if (installedSkills.length > 0) {
createdFiles.push(`.claude/skills/gitnexus/ (${installedSkills.length} skills)`);
// Install skills to .claude/skills/gitnexus/ (unless --skip-skills)
if (!options?.skipSkills) {
const installedSkills = await installSkills(repoPath);
if (installedSkills.length > 0) {
createdFiles.push(`.claude/skills/gitnexus/ (${installedSkills.length} skills)`);
}
} else {
createdFiles.push('.claude/skills/gitnexus/ (skipped via --skip-skills)');
}
return { files: createdFiles };

View file

@ -119,6 +119,10 @@ export interface AnalyzeOptions {
skipAgentsMd?: boolean;
/** Omit volatile symbol/relationship counts from AGENTS.md and CLAUDE.md. */
noStats?: boolean;
/** Skip installing standard GitNexus skill files to .claude/skills/gitnexus/. */
skipSkills?: boolean;
/** Pure index mode: skip all file injection (AGENTS.md, CLAUDE.md, skills). */
indexOnly?: boolean;
/** Index the folder even when no .git directory is present. */
skipGit?: boolean;
/**
@ -399,6 +403,9 @@ export const analyzeCommand = async (inputPath?: string, options?: AnalyzeOption
// ── Run shared analysis orchestrator ───────────────────────────────
try {
const skipAll = options?.indexOnly;
const skipAgentsMd = skipAll || options?.skipAgentsMd;
const skipSkills = skipAll || options?.skipSkills;
const result = await runFullAnalysis(
repoPath,
{
@ -410,7 +417,8 @@ export const analyzeCommand = async (inputPath?: string, options?: AnalyzeOption
embeddingsNodeLimit,
dropEmbeddings: options?.dropEmbeddings,
skipGit: options?.skipGit,
skipAgentsMd: options?.skipAgentsMd,
skipAgentsMd,
skipSkills,
noStats: options?.noStats,
registryName: options?.name,
// Registry-collision bypass — its own CLI flag, intentionally NOT
@ -497,7 +505,7 @@ export const analyzeCommand = async (inputPath?: string, options?: AnalyzeOption
processes: s.processes,
},
skillResult.skills,
{ skipAgentsMd: options?.skipAgentsMd, noStats: options?.noStats },
{ skipAgentsMd, skipSkills, noStats: options?.noStats },
);
}
} catch {

View file

@ -36,6 +36,11 @@ program
.option('--skills', 'Generate repo-specific skill files from detected communities')
.option('--skip-agents-md', 'Skip updating the gitnexus section in AGENTS.md and CLAUDE.md')
.option('--no-stats', 'Omit volatile file/symbol counts from AGENTS.md and CLAUDE.md')
.option(
'--skip-skills',
'Skip installing standard GitNexus skill files to .claude/skills/gitnexus/',
)
.option('--index-only', 'Pure index mode: skip all file injection (AGENTS.md, CLAUDE.md, skills)')
.option(
'--skip-git',
'Treat the provided path/cwd as the index root and skip parent git-root discovery',

View file

@ -81,6 +81,8 @@ export interface AnalyzeOptions {
skipAgentsMd?: boolean;
/** Omit volatile symbol/relationship counts from AGENTS.md and CLAUDE.md. */
noStats?: boolean;
/** Skip installing standard GitNexus skill files to .claude/skills/gitnexus/. */
skipSkills?: boolean;
/**
* User-provided alias for the registry `name` (#829). When set,
* forwarded to `registerRepo` so the indexed repo is stored under
@ -527,7 +529,11 @@ export async function runFullAnalysis(
processes: pipelineResult.processResult?.stats.totalProcesses,
},
undefined,
{ skipAgentsMd: options.skipAgentsMd, noStats: options.noStats },
{
skipAgentsMd: options.skipAgentsMd,
skipSkills: options.skipSkills,
noStats: options.noStats,
},
);
} catch {
// Best-effort — don't fail the entire analysis for context file issues