@chit-run/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chit.js +214 -21
- package/package.json +1 -1
package/dist/chit.js
CHANGED
|
@@ -9965,10 +9965,10 @@ var init_dist = __esm(() => {
|
|
|
9965
9965
|
// ../studio/src/server/audit.ts
|
|
9966
9966
|
import { existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
|
|
9967
9967
|
import { homedir as homedir5 } from "os";
|
|
9968
|
-
import { join as
|
|
9968
|
+
import { join as join8 } from "path";
|
|
9969
9969
|
function defaultAuditDir2() {
|
|
9970
|
-
const xdg = process.env.XDG_STATE_HOME ||
|
|
9971
|
-
return
|
|
9970
|
+
const xdg = process.env.XDG_STATE_HOME || join8(homedir5(), ".local", "state");
|
|
9971
|
+
return join8(xdg, "chit", "audit");
|
|
9972
9972
|
}
|
|
9973
9973
|
function blobRefs(e) {
|
|
9974
9974
|
switch (e.type) {
|
|
@@ -9987,8 +9987,8 @@ function blobRefs(e) {
|
|
|
9987
9987
|
function readAuditRun(auditDir, runId, includeBlobs) {
|
|
9988
9988
|
if (!SAFE_RUN_ID2.test(runId))
|
|
9989
9989
|
return { kind: "invalid-id" };
|
|
9990
|
-
const runDir =
|
|
9991
|
-
const eventsPath =
|
|
9990
|
+
const runDir = join8(auditDir, "runs", runId);
|
|
9991
|
+
const eventsPath = join8(runDir, "events.jsonl");
|
|
9992
9992
|
if (!existsSync8(eventsPath))
|
|
9993
9993
|
return { kind: "not-found" };
|
|
9994
9994
|
let events2;
|
|
@@ -10001,13 +10001,13 @@ function readAuditRun(auditDir, runId, includeBlobs) {
|
|
|
10001
10001
|
}
|
|
10002
10002
|
if (!includeBlobs)
|
|
10003
10003
|
return { kind: "ok", events: events2 };
|
|
10004
|
-
const blobsDir =
|
|
10004
|
+
const blobsDir = join8(runDir, "blobs");
|
|
10005
10005
|
const blobs = {};
|
|
10006
10006
|
for (const e of events2) {
|
|
10007
10007
|
for (const ref of blobRefs(e)) {
|
|
10008
10008
|
if (!SHA256_HEX2.test(ref) || ref in blobs)
|
|
10009
10009
|
continue;
|
|
10010
|
-
const blobPath =
|
|
10010
|
+
const blobPath = join8(blobsDir, ref);
|
|
10011
10011
|
if (existsSync8(blobPath))
|
|
10012
10012
|
blobs[ref] = readFileSync9(blobPath, "utf-8");
|
|
10013
10013
|
}
|
|
@@ -10094,7 +10094,7 @@ var init_paths = __esm(() => {
|
|
|
10094
10094
|
|
|
10095
10095
|
// ../studio/src/server/discovery.ts
|
|
10096
10096
|
import { readdirSync as readdirSync3, readFileSync as readFileSync10 } from "fs";
|
|
10097
|
-
import { basename, join as
|
|
10097
|
+
import { basename, join as join9, relative } from "path";
|
|
10098
10098
|
function safeParseChit(absolutePath) {
|
|
10099
10099
|
try {
|
|
10100
10100
|
const raw2 = JSON.parse(readFileSync10(absolutePath, "utf-8"));
|
|
@@ -10124,7 +10124,7 @@ function discover(opts) {
|
|
|
10124
10124
|
continue;
|
|
10125
10125
|
if (!entry.name.endsWith(".json"))
|
|
10126
10126
|
continue;
|
|
10127
|
-
const absolutePath =
|
|
10127
|
+
const absolutePath = join9(opts.cwd, entry.name);
|
|
10128
10128
|
if (!safeParseChit(absolutePath))
|
|
10129
10129
|
continue;
|
|
10130
10130
|
candidates.push({
|
|
@@ -10150,7 +10150,7 @@ var init_discovery = __esm(() => {
|
|
|
10150
10150
|
|
|
10151
10151
|
// ../studio/src/server/docs.ts
|
|
10152
10152
|
import { createHash as createHash5 } from "crypto";
|
|
10153
|
-
import { readFileSync as readFileSync11, writeFileSync as
|
|
10153
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
10154
10154
|
import { basename as basename2, relative as relative2 } from "path";
|
|
10155
10155
|
function canonicalize(draft) {
|
|
10156
10156
|
return JSON.stringify(draft, null, "\t");
|
|
@@ -10293,7 +10293,7 @@ class DocStore {
|
|
|
10293
10293
|
const manifest = parseManifest(draft);
|
|
10294
10294
|
const graphModel = buildGraphModel(manifest, this.registry, surface);
|
|
10295
10295
|
const canonicalRaw = canonicalize(draft);
|
|
10296
|
-
|
|
10296
|
+
writeFileSync6(entry.absolutePath, canonicalRaw, "utf-8");
|
|
10297
10297
|
const newHash = hashRaw(canonicalRaw);
|
|
10298
10298
|
return {
|
|
10299
10299
|
kind: "saved",
|
|
@@ -10363,9 +10363,9 @@ var init_docs = __esm(() => {
|
|
|
10363
10363
|
|
|
10364
10364
|
// ../studio/src/server/loops.ts
|
|
10365
10365
|
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs";
|
|
10366
|
-
import { join as
|
|
10366
|
+
import { join as join10 } from "path";
|
|
10367
10367
|
function loopsDir2(cwd) {
|
|
10368
|
-
return
|
|
10368
|
+
return join10(cwd, ".chit", "loops");
|
|
10369
10369
|
}
|
|
10370
10370
|
function summarize(loopId, records) {
|
|
10371
10371
|
const header = records[0];
|
|
@@ -10402,7 +10402,7 @@ function listLoops(cwd) {
|
|
|
10402
10402
|
function readLoop2(cwd, loopId) {
|
|
10403
10403
|
if (!SAFE_LOOP_ID2.test(loopId))
|
|
10404
10404
|
return { kind: "invalid-id" };
|
|
10405
|
-
const path =
|
|
10405
|
+
const path = join10(loopsDir2(cwd), `${loopId}.jsonl`);
|
|
10406
10406
|
if (!existsSync10(path))
|
|
10407
10407
|
return { kind: "not-found" };
|
|
10408
10408
|
try {
|
|
@@ -10456,7 +10456,7 @@ __export(exports_server, {
|
|
|
10456
10456
|
PathError: () => PathError
|
|
10457
10457
|
});
|
|
10458
10458
|
import { existsSync as existsSync11 } from "fs";
|
|
10459
|
-
import { join as
|
|
10459
|
+
import { join as join11 } from "path";
|
|
10460
10460
|
async function startStudio(opts) {
|
|
10461
10461
|
const hostname3 = opts.hostname ?? "127.0.0.1";
|
|
10462
10462
|
const requestedPort = opts.port ?? 0;
|
|
@@ -10508,7 +10508,7 @@ function buildApp(opts) {
|
|
|
10508
10508
|
const asset = c.req.param("asset");
|
|
10509
10509
|
if (!CLIENT_ASSETS.has(asset))
|
|
10510
10510
|
return c.text("not found", 404);
|
|
10511
|
-
const path =
|
|
10511
|
+
const path = join11(opts.clientDistDir, asset);
|
|
10512
10512
|
if (!existsSync11(path)) {
|
|
10513
10513
|
return c.text(`client bundle missing at ${path}. Run: bun run studio:build`, 503);
|
|
10514
10514
|
}
|
|
@@ -10684,7 +10684,7 @@ var init_server = __esm(() => {
|
|
|
10684
10684
|
init_loops();
|
|
10685
10685
|
init_token();
|
|
10686
10686
|
init_paths();
|
|
10687
|
-
CLIENT_DIST =
|
|
10687
|
+
CLIENT_DIST = join11(import.meta.dir, "..", "..", "dist", "client");
|
|
10688
10688
|
CLIENT_ASSETS = new Set(["index.js", "index.css"]);
|
|
10689
10689
|
});
|
|
10690
10690
|
|
|
@@ -10692,7 +10692,7 @@ var init_server = __esm(() => {
|
|
|
10692
10692
|
init_src();
|
|
10693
10693
|
import { readFileSync as readFileSync13 } from "fs";
|
|
10694
10694
|
import { homedir as homedir6 } from "os";
|
|
10695
|
-
import { basename as basename3, dirname as dirname2, join as
|
|
10695
|
+
import { basename as basename3, dirname as dirname2, join as join12 } from "path";
|
|
10696
10696
|
|
|
10697
10697
|
// src/adapters/sanitize.ts
|
|
10698
10698
|
var SENSITIVE_KEY = /key|token|secret|password|auth/i;
|
|
@@ -36680,10 +36680,200 @@ ${AUDIT_HELP}`);
|
|
|
36680
36680
|
});
|
|
36681
36681
|
}
|
|
36682
36682
|
|
|
36683
|
+
// src/cli/doctor.ts
|
|
36684
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
36685
|
+
import { mkdirSync as mkdirSync5, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
36686
|
+
import { join as join7 } from "path";
|
|
36687
|
+
var defaultIO3 = {
|
|
36688
|
+
out: (s) => process.stdout.write(s),
|
|
36689
|
+
err: (s) => process.stderr.write(s)
|
|
36690
|
+
};
|
|
36691
|
+
var PROBE_TIMEOUT_MS = 5000;
|
|
36692
|
+
function makeDefaultProbe(timeoutMs) {
|
|
36693
|
+
return (cmd, cwd) => {
|
|
36694
|
+
try {
|
|
36695
|
+
const r = Bun.spawnSync(cmd, {
|
|
36696
|
+
cwd,
|
|
36697
|
+
stdout: "pipe",
|
|
36698
|
+
stderr: "pipe",
|
|
36699
|
+
stdin: "ignore",
|
|
36700
|
+
timeout: timeoutMs
|
|
36701
|
+
});
|
|
36702
|
+
const output = `${r.stdout?.toString() ?? ""}${r.stderr?.toString() ?? ""}`.trim();
|
|
36703
|
+
return { ok: r.exitCode === 0, output };
|
|
36704
|
+
} catch {
|
|
36705
|
+
return { ok: false, output: "" };
|
|
36706
|
+
}
|
|
36707
|
+
};
|
|
36708
|
+
}
|
|
36709
|
+
var defaultProbe = makeDefaultProbe(PROBE_TIMEOUT_MS);
|
|
36710
|
+
function defaultDeps() {
|
|
36711
|
+
return {
|
|
36712
|
+
probe: defaultProbe,
|
|
36713
|
+
cwd: process.cwd(),
|
|
36714
|
+
auditDir: defaultAuditDir(),
|
|
36715
|
+
loadReg: () => loadRegistry(),
|
|
36716
|
+
bunVersion: process.versions.bun
|
|
36717
|
+
};
|
|
36718
|
+
}
|
|
36719
|
+
function checkBun(deps) {
|
|
36720
|
+
if (deps.bunVersion) {
|
|
36721
|
+
return { name: "bun", status: "pass", detail: `Bun ${deps.bunVersion}` };
|
|
36722
|
+
}
|
|
36723
|
+
return {
|
|
36724
|
+
name: "bun",
|
|
36725
|
+
status: "fail",
|
|
36726
|
+
detail: "not running under Bun",
|
|
36727
|
+
hint: "chit is Bun-native; install Bun from https://bun.sh and run chit under bun"
|
|
36728
|
+
};
|
|
36729
|
+
}
|
|
36730
|
+
function checkChitOnPath(deps) {
|
|
36731
|
+
if (deps.probe(["which", "chit"]).ok) {
|
|
36732
|
+
return { name: "chit", status: "pass", detail: "on PATH" };
|
|
36733
|
+
}
|
|
36734
|
+
return {
|
|
36735
|
+
name: "chit",
|
|
36736
|
+
status: "warn",
|
|
36737
|
+
detail: "not on PATH (running locally or via bunx)",
|
|
36738
|
+
hint: "install globally so `chit mcp` resolves: bun install -g @chit-run/cli"
|
|
36739
|
+
};
|
|
36740
|
+
}
|
|
36741
|
+
function checkGitRepo(deps) {
|
|
36742
|
+
if (deps.probe(["git", "rev-parse", "--is-inside-work-tree"], deps.cwd).ok) {
|
|
36743
|
+
return { name: "git repo", status: "pass", detail: `cwd is a git repo (${deps.cwd})` };
|
|
36744
|
+
}
|
|
36745
|
+
return {
|
|
36746
|
+
name: "git repo",
|
|
36747
|
+
status: "warn",
|
|
36748
|
+
detail: `cwd is not a git repo (${deps.cwd})`,
|
|
36749
|
+
hint: "converge and worktree-based flows expect a git repo; cd into one or git init"
|
|
36750
|
+
};
|
|
36751
|
+
}
|
|
36752
|
+
function checkAuditDir(deps) {
|
|
36753
|
+
try {
|
|
36754
|
+
mkdirSync5(deps.auditDir, { recursive: true });
|
|
36755
|
+
const probeFile = join7(deps.auditDir, `.doctor-${randomUUID3()}`);
|
|
36756
|
+
writeFileSync5(probeFile, "ok");
|
|
36757
|
+
rmSync5(probeFile);
|
|
36758
|
+
return { name: "audit dir", status: "pass", detail: `writable (${deps.auditDir})` };
|
|
36759
|
+
} catch (e) {
|
|
36760
|
+
return {
|
|
36761
|
+
name: "audit dir",
|
|
36762
|
+
status: "fail",
|
|
36763
|
+
detail: `not writable (${deps.auditDir}): ${e.message}`,
|
|
36764
|
+
hint: "audited runs need this dir; fix its permissions or set XDG_STATE_HOME"
|
|
36765
|
+
};
|
|
36766
|
+
}
|
|
36767
|
+
}
|
|
36768
|
+
function checkRegistry(deps) {
|
|
36769
|
+
let registry3;
|
|
36770
|
+
try {
|
|
36771
|
+
registry3 = deps.loadReg();
|
|
36772
|
+
} catch (e) {
|
|
36773
|
+
if (e instanceof RegistryError) {
|
|
36774
|
+
return {
|
|
36775
|
+
name: "agents",
|
|
36776
|
+
status: "fail",
|
|
36777
|
+
detail: `invalid agent config: ${e.message}`,
|
|
36778
|
+
hint: "fix or remove ~/.config/chit/agents.json"
|
|
36779
|
+
};
|
|
36780
|
+
}
|
|
36781
|
+
throw e;
|
|
36782
|
+
}
|
|
36783
|
+
const ids = Object.keys(registry3.agents).sort().join(", ");
|
|
36784
|
+
const source = registry3.configPath ? `from ${registry3.configPath}` : "built-in defaults (no agents.json)";
|
|
36785
|
+
return { name: "agents", status: "pass", detail: `${ids || "none"} (${source})` };
|
|
36786
|
+
}
|
|
36787
|
+
function checkAgentCli(deps, bin) {
|
|
36788
|
+
if (deps.probe([bin, "--version"]).ok) {
|
|
36789
|
+
return { name: bin, status: "pass", detail: "available (auth confirmed on first run)" };
|
|
36790
|
+
}
|
|
36791
|
+
return {
|
|
36792
|
+
name: bin,
|
|
36793
|
+
status: "warn",
|
|
36794
|
+
detail: `not found on PATH`,
|
|
36795
|
+
hint: `install ${bin} and authenticate it; chit calls it as an agent`
|
|
36796
|
+
};
|
|
36797
|
+
}
|
|
36798
|
+
function checkMcpRegistration(deps) {
|
|
36799
|
+
if (!deps.probe(["claude", "--version"]).ok) {
|
|
36800
|
+
return {
|
|
36801
|
+
name: "mcp register",
|
|
36802
|
+
status: "warn",
|
|
36803
|
+
detail: "skipped (claude CLI not found)",
|
|
36804
|
+
hint: "with claude installed: claude mcp add chit --scope local -- chit mcp"
|
|
36805
|
+
};
|
|
36806
|
+
}
|
|
36807
|
+
if (deps.probe(["claude", "mcp", "get", "chit"]).ok) {
|
|
36808
|
+
return { name: "mcp register", status: "pass", detail: "chit registered as an MCP server" };
|
|
36809
|
+
}
|
|
36810
|
+
return {
|
|
36811
|
+
name: "mcp register",
|
|
36812
|
+
status: "warn",
|
|
36813
|
+
detail: "chit not registered as an MCP server",
|
|
36814
|
+
hint: "register it: claude mcp add chit --scope local -- chit mcp"
|
|
36815
|
+
};
|
|
36816
|
+
}
|
|
36817
|
+
function runChecks(deps) {
|
|
36818
|
+
return [
|
|
36819
|
+
checkBun(deps),
|
|
36820
|
+
checkChitOnPath(deps),
|
|
36821
|
+
checkAgentCli(deps, "codex"),
|
|
36822
|
+
checkAgentCli(deps, "claude"),
|
|
36823
|
+
checkRegistry(deps),
|
|
36824
|
+
checkMcpRegistration(deps),
|
|
36825
|
+
checkAuditDir(deps),
|
|
36826
|
+
checkGitRepo(deps)
|
|
36827
|
+
];
|
|
36828
|
+
}
|
|
36829
|
+
var SHAPE = { pass: "\u25CF", warn: "\u25CB", fail: "\u25C6" };
|
|
36830
|
+
function render(checks4, io) {
|
|
36831
|
+
io.out(`chit doctor
|
|
36832
|
+
|
|
36833
|
+
`);
|
|
36834
|
+
const width = Math.max(...checks4.map((c) => c.name.length));
|
|
36835
|
+
for (const c of checks4) {
|
|
36836
|
+
io.out(`${SHAPE[c.status]} ${c.name.padEnd(width)} ${c.detail}
|
|
36837
|
+
`);
|
|
36838
|
+
if (c.hint && c.status !== "pass")
|
|
36839
|
+
io.out(`${" ".repeat(width + 4)}\u21B3 ${c.hint}
|
|
36840
|
+
`);
|
|
36841
|
+
}
|
|
36842
|
+
const fails = checks4.filter((c) => c.status === "fail").length;
|
|
36843
|
+
const warns = checks4.filter((c) => c.status === "warn").length;
|
|
36844
|
+
io.out(`
|
|
36845
|
+
${fails} failure${fails === 1 ? "" : "s"}, ${warns} warning${warns === 1 ? "" : "s"}. Agent authentication is verified on the first real run.
|
|
36846
|
+
`);
|
|
36847
|
+
}
|
|
36848
|
+
var DOCTOR_HELP = `chit doctor
|
|
36849
|
+
|
|
36850
|
+
Preflight check for first-time setup. Runs no agents and changes nothing (it only
|
|
36851
|
+
writes and removes a probe file in the audit dir to confirm it is writable).
|
|
36852
|
+
|
|
36853
|
+
Checks: Bun, the chit binary on PATH, the codex and claude CLIs, the agent
|
|
36854
|
+
registry, MCP registration, the audit dir, and whether the cwd is a git repo.
|
|
36855
|
+
Agent authentication is not checked here; it is confirmed on the first real run.
|
|
36856
|
+
`;
|
|
36857
|
+
function runDoctor(argv, io = defaultIO3, deps = defaultDeps()) {
|
|
36858
|
+
if (argv[0] === "-h" || argv[0] === "--help") {
|
|
36859
|
+
io.out(DOCTOR_HELP);
|
|
36860
|
+
return 0;
|
|
36861
|
+
}
|
|
36862
|
+
if (argv.length > 0) {
|
|
36863
|
+
io.err(`chit doctor: unexpected argument ${JSON.stringify(argv[0])}
|
|
36864
|
+
|
|
36865
|
+
${DOCTOR_HELP}`);
|
|
36866
|
+
return 2;
|
|
36867
|
+
}
|
|
36868
|
+
const checks4 = runChecks(deps);
|
|
36869
|
+
render(checks4, io);
|
|
36870
|
+
return checks4.some((c) => c.status === "fail") ? 1 : 0;
|
|
36871
|
+
}
|
|
36872
|
+
|
|
36683
36873
|
// src/cli/loop-log.ts
|
|
36684
36874
|
init_src();
|
|
36685
36875
|
import { resolve as resolve4 } from "path";
|
|
36686
|
-
var
|
|
36876
|
+
var defaultIO4 = {
|
|
36687
36877
|
out: (s) => process.stdout.write(s),
|
|
36688
36878
|
err: (s) => process.stderr.write(s)
|
|
36689
36879
|
};
|
|
@@ -36798,7 +36988,7 @@ function renderLoop(records) {
|
|
|
36798
36988
|
`)}
|
|
36799
36989
|
`;
|
|
36800
36990
|
}
|
|
36801
|
-
function runLoopLog(argv, io =
|
|
36991
|
+
function runLoopLog(argv, io = defaultIO4) {
|
|
36802
36992
|
const verb = argv[0];
|
|
36803
36993
|
if (!verb || verb === "-h" || verb === "--help") {
|
|
36804
36994
|
(verb ? io.out : io.err)(LOOP_LOG_HELP);
|
|
@@ -37082,6 +37272,7 @@ var HELP = `Usage:
|
|
|
37082
37272
|
chit uninstall <name> [--to <dir>]
|
|
37083
37273
|
chit studio [path]
|
|
37084
37274
|
chit mcp (run the stdio MCP server)
|
|
37275
|
+
chit doctor (preflight: check setup)
|
|
37085
37276
|
chit loop-log <start|append|stop|show> [flags] (chit loop-log --help)
|
|
37086
37277
|
chit converge --task <text> --scope <id> [options] (chit converge --help)
|
|
37087
37278
|
chit audit <list|show> [options] (chit audit --help)
|
|
@@ -37172,6 +37363,8 @@ async function runMain(argv) {
|
|
|
37172
37363
|
return runConverge(argv.slice(1));
|
|
37173
37364
|
if (argv[0] === "audit")
|
|
37174
37365
|
return runAudit(argv.slice(1));
|
|
37366
|
+
if (argv[0] === "doctor")
|
|
37367
|
+
return runDoctor(argv.slice(1));
|
|
37175
37368
|
let args;
|
|
37176
37369
|
try {
|
|
37177
37370
|
args = parseArgs(argv);
|
|
@@ -37423,7 +37616,7 @@ ${HELP}`);
|
|
|
37423
37616
|
`);
|
|
37424
37617
|
return 2;
|
|
37425
37618
|
}
|
|
37426
|
-
const outputDir = args.outputDir ??
|
|
37619
|
+
const outputDir = args.outputDir ?? join12(homedir6(), ".claude", "skills");
|
|
37427
37620
|
const runtimePath = args.runtimePath ?? defaultRuntimePath();
|
|
37428
37621
|
try {
|
|
37429
37622
|
const result = installClaudeSkill({
|