Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/cli/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createRequire } from "node:module";
import { Command } from "commander";
import { ClaudemuxError } from "../errors.js";
import { type AskCliOpts, askCli } from "./ask.js";
Expand All @@ -16,6 +17,8 @@ import { stateCli } from "./state.js";
import { turnCompleteCli } from "./turn-complete.js";
import { type WaitCliOpts, waitCli } from "./wait.js";

const packageJson = createRequire(import.meta.url)("../../package.json") as { version: string };

/**
* Build the `claudemux` commander entry. Exported separately from `bin/`
* so tests can drive it without spawning a subprocess.
Expand All @@ -26,7 +29,10 @@ import { type WaitCliOpts, waitCli } from "./wait.js";
*/
export function buildProgram(): Command {
const program = new Command();
program.name("claudemux").description("Drive long-lived Claude Code sessions from Node.");
program
.name("claudemux")
.description("Drive long-lived Claude Code sessions from Node.")
.version(packageJson.version);

// Every verb locates a session: namespace prefix + an explicit socket override
// (the latter for dev / debugging — most users share the default socket).
Expand Down
10 changes: 9 additions & 1 deletion test/cli/cli.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { spawn } from "node:child_process";
import { existsSync } from "node:fs";
import { existsSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
Expand All @@ -14,6 +14,7 @@ import { Harness, claudeBinDir } from "../harness/index.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const repoRoot = join(__dirname, "..", "..");
const binPath = join(repoRoot, "bin", "claudemux");
const packageVersion = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")).version;

// Real-claude boot is out of the hermetic gate (no `claude` in `npm test`/CI).
// The block below spawns the installed-but-logged-OUT claude binary; run it
Expand Down Expand Up @@ -80,6 +81,13 @@ describe("CLI — bin/claudemux exists and is runnable", () => {
}
});

it("--version prints the package version", async () => {
const r = await runCli(["--version"]);
expect(r.exit).toBe(0);
expect(r.stdout.trim()).toBe(packageVersion);
expect(r.stderr).toBe("");
});

it("--help output for every verb has ZERO references to 'tmux'", async () => {
const verbs = [
"spawn",
Expand Down
Loading