Skip to content

Commit 070ce4d

Browse files
colbymchenryclaude
andauthored
feat(cli): codegraph version command + complete CLI Reference (colbymchenry#864)
* feat(cli): codegraph version command + complete CLI Reference Add a `codegraph version` subcommand plus the `-v` and `-version` spellings (commander already wires up `--version`/`-V`), so the version is easy to reach however a user guesses at it. The `-v`/`-version` forms are intercepted before commander parses — its version short flag is the capital `-V`, and its parser rejects a multi-character single-dash flag. A trailing `-v` on a subcommand still means `--verbose`. Document the previously-missing commands in the README CLI Reference: `daemon`/`daemons`, `unlock`, `telemetry`, `version`, and `help`. Co-Authored-By: Claude Opus 4.8 <[email protected]> * docs(changelog): reference colbymchenry#864 on the version-command entry Co-Authored-By: Claude Opus 4.8 <[email protected]> --------- Co-authored-by: Claude Opus 4.8 <[email protected]>
1 parent ff288ac commit 070ce4d

4 files changed

Lines changed: 106 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1212
### New Features
1313

1414
- New `codegraph daemon` command (alias `daemons`) — an interactive manager for the background daemons. It shows what's running (your current project's daemon first, pre-selected), and you arrow-key to one and press enter to stop it, or pick "Stop all". Previously the only way to shut a daemon down was to hunt for its pid and `kill` it by hand. (#845)
15+
- Checking your installed version is now easy to reach however you guess at it: `codegraph version`, `codegraph -v`, and `codegraph -version` all print it, alongside the existing `codegraph --version`. (#864)
1516
- The CodeGraph MCP server now self-heals if its main thread ever locks up. A lightweight watchdog notices when the process has stopped responding and stops it so a fresh one starts on your next request — it can no longer sit pinned at 100% CPU with no way to recover. Tune the detection window with `CODEGRAPH_WATCHDOG_TIMEOUT_MS`, or turn it off entirely with `CODEGRAPH_NO_WATCHDOG=1`. (#850)
1617

1718
### Fixes

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ codegraph uninit [path] # Remove CodeGraph from a project (--force to
474474
codegraph index [path] # Full index (--force to re-index, --quiet for less output)
475475
codegraph sync [path] # Incremental update
476476
codegraph status [path] # Show statistics
477+
codegraph unlock [path] # Remove a stale lock file that's blocking indexing
477478
codegraph query <search> # Search symbols (--kind, --limit, --json)
478479
codegraph explore <query> # Relevant symbols' source + call paths in one shot (same output as the codegraph_explore MCP tool)
479480
codegraph node <symbol|file> # One symbol's source + callers, or read a file with line numbers (same output as codegraph_node)
@@ -483,7 +484,11 @@ codegraph callees <symbol> # Find what a function/method calls (--limit,
483484
codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
484485
codegraph affected [files...] # Find test files affected by changes (see below)
485486
codegraph serve --mcp # Start MCP server
487+
codegraph daemon # Manage background daemons — pick one to stop (alias: daemons)
488+
codegraph telemetry [on|off] # Show or change anonymous usage telemetry
486489
codegraph upgrade [version] # Update to the latest release (--check, --force)
490+
codegraph version # Print the installed version (also -v, --version)
491+
codegraph help [command] # Show help, optionally for one command
487492
```
488493

489494
### `codegraph affected`

__tests__/cli-version.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Tests for the `codegraph version` affordances.
3+
*
4+
* The version should be reachable however a user reaches for it — the bare
5+
* `version` subcommand, lowercase `-v`, single-dash `-version`, plus
6+
* commander's stock `--version` / `-V`. All of them print the exact
7+
* package.json version and nothing else.
8+
*
9+
* Exercised end-to-end against the built binary (same approach as
10+
* status-json.test.ts) so the spellings survive future CLI refactors.
11+
*/
12+
13+
import { describe, it, expect } from 'vitest';
14+
import { execFileSync } from 'child_process';
15+
import * as fs from 'fs';
16+
import * as os from 'os';
17+
import * as path from 'path';
18+
19+
const BIN = path.resolve(__dirname, '../dist/bin/codegraph.js');
20+
const PKG_VERSION = JSON.parse(
21+
fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf-8'),
22+
).version as string;
23+
24+
function run(args: string[]): string {
25+
return execFileSync(process.execPath, [BIN, ...args], {
26+
encoding: 'utf-8',
27+
// Skip the daemon and the wasm-flag re-exec so the command resolves in a
28+
// single fast process (no graph work happens for a version print anyway).
29+
env: { ...process.env, CODEGRAPH_NO_DAEMON: '1', CODEGRAPH_WASM_RELAUNCHED: '1' },
30+
stdio: ['ignore', 'pipe', 'pipe'],
31+
}).trim();
32+
}
33+
34+
describe('codegraph version affordances', () => {
35+
for (const spelling of ['version', '-v', '-version', '--version', '-V']) {
36+
it(`\`codegraph ${spelling}\` prints exactly the package version`, () => {
37+
expect(run([spelling])).toBe(PKG_VERSION);
38+
});
39+
}
40+
41+
it('lists the `version` subcommand in --help', () => {
42+
expect(run(['--help'])).toContain('version');
43+
});
44+
45+
it('`codegraph help` prints usage and the command list', () => {
46+
const out = run(['help']);
47+
expect(out).toContain('Usage: codegraph');
48+
expect(out).toContain('Commands:');
49+
});
50+
51+
it('a trailing `-v` is still the subcommand\'s --verbose, not the version intercept', () => {
52+
// A fresh temp dir outside any indexed project: `index -v` parses `-v` as
53+
// the index command's --verbose, then short-circuits at "not initialized"
54+
// and exits non-zero. The point is it must NOT print the bare version,
55+
// which would mean the top-level intercept swallowed a subcommand flag.
56+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-version-test-'));
57+
let combined = '';
58+
try {
59+
combined = execFileSync(process.execPath, [BIN, 'index', '-v', tempDir], {
60+
encoding: 'utf-8',
61+
env: { ...process.env, CODEGRAPH_NO_DAEMON: '1', CODEGRAPH_WASM_RELAUNCHED: '1' },
62+
stdio: ['ignore', 'pipe', 'pipe'],
63+
});
64+
} catch (err: unknown) {
65+
const e = err as { stdout?: string; stderr?: string };
66+
combined = `${e.stdout ?? ''}${e.stderr ?? ''}`;
67+
} finally {
68+
fs.rmSync(tempDir, { recursive: true, force: true });
69+
}
70+
expect(combined.trim()).not.toBe(PKG_VERSION);
71+
expect(combined).toContain('not initialized');
72+
});
73+
});

src/bin/codegraph.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@ const packageJson = JSON.parse(
120120
fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf-8')
121121
);
122122

123+
// Make the version trivial to reach. commander's `.version()` (below) wires up
124+
// `--version` and `-V`; intercept the spellings it can't — lowercase `-v` and
125+
// single-dash `-version` — before any parsing. (commander's version short flag
126+
// is the capital `-V`, and its parser rejects a multi-character single-dash
127+
// flag.) The bare `codegraph version` subcommand is registered further down so
128+
// the affordance also shows up in `codegraph --help`.
129+
const firstArg = process.argv[2];
130+
if (firstArg === '-v' || firstArg === '-version') {
131+
console.log(packageJson.version);
132+
return;
133+
}
134+
123135
// =============================================================================
124136
// ANSI Color Helpers (avoid chalk ESM issues)
125137
// =============================================================================
@@ -1978,6 +1990,21 @@ program
19781990
process.exit(code);
19791991
});
19801992

1993+
/**
1994+
* codegraph version
1995+
*
1996+
* The bare-noun form of `--version`. commander already provides `--version`
1997+
* and `-V`, and the `-v` / `-version` spellings are intercepted before parse
1998+
* (see top of main). This subcommand makes `codegraph version` work and lists
1999+
* the version affordance in `codegraph --help`.
2000+
*/
2001+
program
2002+
.command('version')
2003+
.description('Print the installed CodeGraph version (also: -v, --version)')
2004+
.action(() => {
2005+
console.log(packageJson.version);
2006+
});
2007+
19812008
// Parse and run
19822009
program.parse();
19832010

0 commit comments

Comments
 (0)