@swarmdo/cli 1.50.0 → 1.58.1
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/README.md +6 -3
- package/dist/src/agent-bridge/bridge.d.ts +104 -0
- package/dist/src/agent-bridge/bridge.d.ts.map +1 -0
- package/dist/src/agent-bridge/bridge.js +133 -0
- package/dist/src/agent-bridge/bridge.js.map +1 -0
- package/dist/src/command-usage/usage.d.ts +74 -0
- package/dist/src/command-usage/usage.d.ts.map +1 -0
- package/dist/src/command-usage/usage.js +161 -0
- package/dist/src/command-usage/usage.js.map +1 -0
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +133 -1
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/commands.d.ts +19 -0
- package/dist/src/commands/commands.d.ts.map +1 -0
- package/dist/src/commands/commands.js +107 -0
- package/dist/src/commands/commands.js.map +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +11 -3
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/standup.d.ts +18 -0
- package/dist/src/commands/standup.d.ts.map +1 -0
- package/dist/src/commands/standup.js +116 -0
- package/dist/src/commands/standup.js.map +1 -0
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +29 -0
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/usage.d.ts.map +1 -1
- package/dist/src/commands/usage.js +57 -1
- package/dist/src/commands/usage.js.map +1 -1
- package/dist/src/comms/store.d.ts +11 -1
- package/dist/src/comms/store.d.ts.map +1 -1
- package/dist/src/comms/store.js +16 -2
- package/dist/src/comms/store.js.map +1 -1
- package/dist/src/init/helpers-generator.d.ts.map +1 -1
- package/dist/src/init/helpers-generator.js +41 -1
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +9 -2
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/integrations/integrations.d.ts.map +1 -1
- package/dist/src/integrations/integrations.js +19 -8
- package/dist/src/integrations/integrations.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +166 -0
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/comms-tools.js +4 -4
- package/dist/src/mcp-tools/comms-tools.js.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts +33 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +73 -38
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/standup/standup.d.ts +83 -0
- package/dist/src/standup/standup.d.ts.map +1 -0
- package/dist/src/standup/standup.js +157 -0
- package/dist/src/standup/standup.js.map +1 -0
- package/dist/src/usage/transcript-friction.d.ts +77 -0
- package/dist/src/usage/transcript-friction.d.ts.map +1 -0
- package/dist/src/usage/transcript-friction.js +151 -0
- package/dist/src/usage/transcript-friction.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://swarmdo.com)
|
|
4
4
|
|
|
5
|
-
[](https://img.shields.io/badge/npx%20swarmdo-v1.58.1-cb3837?style=for-the-badge&logo=npm&logoColor=white)](https://github.com/SwarmDo/swarmdo/releases)
|
|
6
6
|
[](https://github.com/SwarmDo/swarmdo/blob/main/LICENSE)
|
|
7
7
|
[](https://swarmdo.com)
|
|
8
8
|
[](https://github.com/SwarmDo/swarmdo)
|
|
@@ -271,7 +271,7 @@ The recent release train added a full day-to-day operations layer around the swa
|
|
|
271
271
|
|
|
272
272
|
| Command | What it does |
|
|
273
273
|
|---------|-------------|
|
|
274
|
-
| `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `weekly`, `monthly` (with a month-end spend projection), `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), `cache` (prompt-cache efficiency + $ saved), `diff` (period-over-period comparison with per-model movers), `reflect` (a wrapped-style retrospective — busiest day, streak, top models/projects, peak hour, delegation ratio — with a shareable `--html` dashboard), and `limits` (an official-quota **exhaustion forecaster** over Claude Code's `rate_limits`); the standard views take `--csv` for spreadsheet export |
|
|
274
|
+
| `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `weekly`, `monthly` (with a month-end spend projection), `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), `friction` (how often you interrupt Claude + which tool was running + dominant error categories), `cache` (prompt-cache efficiency + $ saved), `diff` (period-over-period comparison with per-model movers), `reflect` (a wrapped-style retrospective — busiest day, streak, top models/projects, peak hour, delegation ratio — with a shareable `--html` dashboard), and `limits` (an official-quota **exhaustion forecaster** over Claude Code's `rate_limits`); the standard views take `--csv` for spreadsheet export |
|
|
275
275
|
| `swarmdo usage guard` | **Budget policy** — limits for the active 5h block / today / month via flags or `SWARMDO_GUARD_*` env → ok / warn / over; `--strict` exits 1, safe for CI gates and Stop hooks |
|
|
276
276
|
| `swarmdo hud` | **One-screen ops HUD** — 5h block burn, task readiness, daemon workers, memory snapshots (`--watch`, `--json`) |
|
|
277
277
|
| `swarmdo repair` (alias `tdd-repair`) | **Test-Driven Repair** — a bounded, budget-capped headless `claude` loop that fixes source until a failing test passes; dry-run unless `--confirm` |
|
|
@@ -292,6 +292,9 @@ The recent release train added a full day-to-day operations layer around the swa
|
|
|
292
292
|
| `swarmdo coupling` | **Files that change together** — the empirical complement to `affected`'s static import graph: mine git history for file pairs that keep landing in the same commit (a schema and its type, a serializer split across modules) so you catch the co-edit you'd otherwise forget. `--file <path>` answers "what changes with X?", `--since`, `--min-shared`, `--csv`. Modeled on code-maat / CodeScene. Also an MCP tool (`coupling`). Deterministic |
|
|
293
293
|
| `swarmdo ownership` | **Who owns each file, and what breaks if they leave** — a per-file knowledge map + bus factor from git history: the dominant author, ownership concentration, and the fewest authors whose churn clears 50% (a lone owner is flagged ⚠ key-person), plus a repo-wide truck factor. `--since`, `--min-churn`, `--top`, `--csv`, `--format json`. code-maat main-dev / CodeScene "Knowledge Map"; also an MCP tool (`ownership`). Deterministic |
|
|
294
294
|
| `swarmdo hidden-coupling` | **Co-change with no import edge** — join the two graphs swarmdo already owns (temporal `coupling` from git + `codegraph`'s import graph) and emit the set difference: file pairs that keep changing together yet nothing in the code links them ("logical minus structural coupling" — a config and its consumers, a schema and its mirror type). The co-edit `affected` can't see. `--since`, `--min-shared`, `--csv`, `--format json`. Grounded in Gall et al. (ICSM 1998). Deterministic |
|
|
295
|
+
| `swarmdo standup` (alias `mine`) | **What did I do?** — your commits since your last working day, grouped by day with a diffstat. **Weekend-aware** (git-standup parity): on Monday it reaches back to Friday, on Sunday to Friday, otherwise to yesterday — one-command recall for a standup or for re-orienting at the start of a session. Defaults to the current git user; `--author <name>`/`--all` for teammates, `--days N` or `--since 2w` to override the window, `--format json`. Pure engine (weekend math + per-day fold) → fixture-tested. Deterministic |
|
|
296
|
+
| `swarmdo commands` (alias `slash`) | **Hot/cold/orphan usage report** for your authored `.claude/` surface — which custom slash-commands (`.claude/commands/**`) and subagents (`.claude/agents/**`) you actually invoke (**hot**, with counts), which are **cold** (defined but never used → prune candidates), and which are **orphan** (invoked but undefined → a typo or a builtin). `config lint` says "are these valid?"; this says "are these used?" — joining the defined files against invocation counts mined from local transcripts (`<command-name>` markers + `subagent_type` fields). `--unused` prints just the prune list, `--unused --strict` is a CI gate (exit 1 if anything's dead), `--all` counts across every project, `--json`. Pure parsers + join → fixture-tested |
|
|
297
|
+
| `swarmdo agent bridge` | **Link Claude Code agents ⇄ Swarmdo** — the fix for "Swarmdo is installed but never actually used." Swarmdo can't call Claude Code's `Agent` tool (only the main loop can), so `agent bridge register -n <name>` binds a real Claude Code agent into Swarmdo's registry (`swarmdo agent list` stops being empty) and **auto-spins-up a swarm from your config, enrolling the agent** — the next bind joins the same swarm. `bridge list` (bound vs native), `bridge sync --live a,b` (reconcile drift), `bridge advise "<prompt>"` (should this warrant a swarm? which roles?). Also MCP tools `agent_bridge_register`/`agent_bridge_list`. Pure engine → 16 tests |
|
|
295
298
|
| `swarmdo testreport` | **JUnit/TAP → failure digest** — turn raw test-result files into the exact failing test names + `file:line` + assertion messages, instead of scanning hundreds of log lines. The front-half of the test→fix loop: feed the failures straight into `repair`. Reads a file, a directory, or stdin; `--ci` exits 1 on any failure, `--format json`. Also an MCP tool (`testreport`). Deterministic |
|
|
296
299
|
| `swarmdo integrations` (alias `integrate`) | **Use swarmdo from Codex CLI, GitHub Copilot CLI, and pi** — one command wires AGENTS.md + each CLI's MCP config (idempotent, dry-run first, never touches your Claude Code setup) |
|
|
297
300
|
| OpenRouter model pool | **Let swarms pick from any models you configure** — declare tier-mapped OpenRouter models in `swarmdo.config.json`; the router Thompson-samples among them per task and the execution layer dispatches the winner |
|
|
@@ -299,7 +302,7 @@ The recent release train added a full day-to-day operations layer around the swa
|
|
|
299
302
|
| `swarmdo mcp doctor` | **MCP config diagnosis** — missing binaries, bad URLs, malformed entries across `.mcp.json` + `~/.claude.json` |
|
|
300
303
|
| `swarmdo config lint` | **Static config validation** — the pure shape layer for `swarmdo.config.json`, the `.claude/settings*.json` hooks block, `.mcp.json`, **`.claude/agents/*.md` subagents** (missing `name`/`description`, a `name` duplicated across files — CC silently loads only one — a bad `model`, malformed frontmatter), and **custom slash commands + skills** (malformed YAML that makes CC load empty metadata, a bad `effort`, an inline `` !`cmd` `` bash-injection that's inert or not covered by `allowed-tools`). `--strict` gates CI |
|
|
301
304
|
| `swarmdo permissions` (alias `perms`) | **Audit your Claude Code permission rules** — static analysis of `permissions.allow`/`deny`/`ask` in `.claude/settings*.json`: flags allow↔deny conflicts (dead rules), over-broad `Bash(*)` grants, shadowed/redundant rules, duplicates, and malformed entries. `--strict` gates CI. Read-only; the static-safety sibling of `config lint` / `mcp doctor` |
|
|
302
|
-
| `swarmdo comms` (alias `mailbox`) | **Cross-session agent mailbox** — one Claude Code
|
|
305
|
+
| `swarmdo comms` (alias `mailbox`) | **Cross-session, cross-tool agent mailbox** — one agent session (Claude Code, Codex, Copilot, or pi) messages another by name (`send -t <session>`, `-t all` broadcasts, `inbox`, `read`, `watch`); sessions on the same repo share `.swarmdo/comms/`. Non-Claude agents set `$SWARMDO_AGENT` for a stable identity. `inbox --hook` surfaces new mail as prompt context without polling. Also MCP tools (`comms_send`/`comms_inbox`) |
|
|
303
306
|
| `swarmdo hooks memory-inject` | **Prompt-time semantic memory injection** — embeds each prompt, vector-searches your stored memories, and injects the most relevant under a token budget (recall at the moment of need); wire it with `hooks recipe memory-inject` |
|
|
304
307
|
| `swarmdo hooks notify -d` | **Desktop notifications** — OS-native toast (macOS `osascript`, Linux `notify-send`) |
|
|
305
308
|
| `swarmdo hooks recipe` | **One-command Claude Code hooks** — install `notify-done`/`notify-input` (desktop pings), `memory-inject` (relevant memories each prompt), `comms-inbox` (new mail as context), or `command-guard` (a PreToolUse deny hook that blocks dangerous bash — `rm -rf /`, pipe-to-shell, force-push to main — the net swarmdo needs when running headless); dry-run by default, idempotent merge that never clobbers your settings |
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-bridge/bridge.ts — link Claude Code Agent-tool agents to Swarmdo's
|
|
3
|
+
* agent registry so the two systems share ONE view.
|
|
4
|
+
*
|
|
5
|
+
* The problem this solves: Swarmdo (MCP server + CLI + hooks) runs
|
|
6
|
+
* out-of-process and CANNOT invoke Claude Code's `Agent` tool — only the main
|
|
7
|
+
* Claude Code loop can spawn real LLM workers. So today a session can run four
|
|
8
|
+
* Claude Code agents while `swarmdo agent list` stays empty: installed but
|
|
9
|
+
* inert. The honest integration is a BINDING — when a real Claude Code agent is
|
|
10
|
+
* spawned, register a bound record in Swarmdo's canonical store
|
|
11
|
+
* (`.swarmdo/agents/store.json`, via the existing `agent_spawn`/registerAgent
|
|
12
|
+
* path — NO parallel store) so `swarmdo agent list` / `swarm_status` reflect
|
|
13
|
+
* reality, and reconcile the two sides on demand.
|
|
14
|
+
*
|
|
15
|
+
* Pure + deterministic: these functions build the registration input, classify
|
|
16
|
+
* whether a prompt warrants a swarm, and diff the two rosters. All fs / MCP /
|
|
17
|
+
* spawning lives in the command + hook layers, so this module is
|
|
18
|
+
* fully fixture-testable.
|
|
19
|
+
*/
|
|
20
|
+
/** A real Claude Code agent, as the main loop sees it (name@session-…). */
|
|
21
|
+
export interface ClaudeAgentDescriptor {
|
|
22
|
+
/** the Agent-tool name, e.g. "research-ccgap" */
|
|
23
|
+
name: string;
|
|
24
|
+
/** the Claude Code session id, e.g. "cec69c3c" (from `name@session-cec69c3c`) */
|
|
25
|
+
sessionId?: string;
|
|
26
|
+
/** the subagent_type, e.g. "general-purpose" / "coder" */
|
|
27
|
+
agentType: string;
|
|
28
|
+
/** one-line task/prompt summary */
|
|
29
|
+
task?: string;
|
|
30
|
+
/** last-known lifecycle state */
|
|
31
|
+
status?: 'idle' | 'busy' | 'terminated';
|
|
32
|
+
}
|
|
33
|
+
/** The Swarmdo-side binding, stored inside an AgentRecord's `config.binding`. */
|
|
34
|
+
export interface AgentBinding {
|
|
35
|
+
origin: 'claude-code';
|
|
36
|
+
claudeName: string;
|
|
37
|
+
sessionId?: string;
|
|
38
|
+
task?: string;
|
|
39
|
+
/** ISO timestamp the binding was created/refreshed */
|
|
40
|
+
boundAt: string;
|
|
41
|
+
}
|
|
42
|
+
/** Minimal shape of a Swarmdo AgentRecord needed for reconciliation. */
|
|
43
|
+
export interface SwarmdoAgentLike {
|
|
44
|
+
agentId: string;
|
|
45
|
+
agentType: string;
|
|
46
|
+
status?: string;
|
|
47
|
+
config?: Record<string, unknown> & {
|
|
48
|
+
binding?: AgentBinding;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Deterministic Swarmdo agentId for a Claude Code agent — stable across
|
|
53
|
+
* re-registration so binding the same agent twice UPDATES the record rather
|
|
54
|
+
* than spawning a duplicate (registerAgent honors an explicit `agentId`). Pure.
|
|
55
|
+
*/
|
|
56
|
+
export declare function bridgeAgentId(d: ClaudeAgentDescriptor): string;
|
|
57
|
+
/**
|
|
58
|
+
* Build the `agent_spawn` input that registers a bound Swarmdo record for a
|
|
59
|
+
* Claude Code agent. Pure — returns the input object; the caller persists it via
|
|
60
|
+
* the real registerAgent / `agent_spawn` path (so the swarm-join + graph-node +
|
|
61
|
+
* store all happen exactly as for a native Swarmdo agent). `nowIso` is injected
|
|
62
|
+
* for testability.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildSpawnInput(d: ClaudeAgentDescriptor, nowIso: string): Record<string, unknown>;
|
|
65
|
+
/** Is a Swarmdo record a Claude-Code binding (vs a native Swarmdo agent)? Pure. */
|
|
66
|
+
export declare function isBound(a: SwarmdoAgentLike): boolean;
|
|
67
|
+
export interface Reconciliation {
|
|
68
|
+
/** claudeName present in BOTH the live roster and the Swarmdo store */
|
|
69
|
+
mirrored: string[];
|
|
70
|
+
/** live Claude Code agents with NO bound Swarmdo record (need registering) */
|
|
71
|
+
unmirrored: string[];
|
|
72
|
+
/** bound Swarmdo records whose Claude Code agent is gone (stale — reap) */
|
|
73
|
+
orphaned: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Diff the live Claude Code roster against the Swarmdo store. Pure. Only
|
|
77
|
+
* Claude-Code-bound records participate (native Swarmdo agents are ignored).
|
|
78
|
+
* Returns sorted, de-duplicated name lists so output is deterministic.
|
|
79
|
+
*/
|
|
80
|
+
export declare function reconcile(swarmdoAgents: SwarmdoAgentLike[], liveClaudeNames: string[]): Reconciliation;
|
|
81
|
+
/**
|
|
82
|
+
* agentIds of Claude-Code-bound records whose bound agent is NOT in the live
|
|
83
|
+
* roster — the orphans to reap so stale bindings don't accumulate across
|
|
84
|
+
* sessions. Native (unbound) Swarmdo agents are never selected. Pure; sorted
|
|
85
|
+
* for deterministic pruning. Complements `reconcile` (which reports orphan
|
|
86
|
+
* NAMES) by giving the store keys the prune path deletes.
|
|
87
|
+
*/
|
|
88
|
+
export declare function orphanedAgentIds(swarmdoAgents: SwarmdoAgentLike[], liveClaudeNames: string[]): string[];
|
|
89
|
+
export interface SwarmIntent {
|
|
90
|
+
/** true when the prompt is substantial enough to warrant bound agents */
|
|
91
|
+
requiresAgents: boolean;
|
|
92
|
+
/** short human reason (which signal fired) */
|
|
93
|
+
reason: string;
|
|
94
|
+
/** suggested agent roles, most-important first (empty when !requiresAgents) */
|
|
95
|
+
suggestedRoles: string[];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Decide whether a prompt warrants a bound-agent swarm, and which roles. Pure.
|
|
99
|
+
* requiresAgents is true when an agentic verb fires AND the prompt is long
|
|
100
|
+
* enough that it isn't a one-line question — a trivial/conversational signal
|
|
101
|
+
* alone (with no agentic verb) suppresses it. Deterministic; no LLM.
|
|
102
|
+
*/
|
|
103
|
+
export declare function classifyPrompt(prompt: string): SwarmIntent;
|
|
104
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../../src/agent-bridge/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;CACzC;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAI9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAejG;AAED,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAEpD;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,aAAa,EAAE,gBAAgB,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,cAAc,CActG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,gBAAgB,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAMvG;AAQD,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAiBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAe1D"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-bridge/bridge.ts — link Claude Code Agent-tool agents to Swarmdo's
|
|
3
|
+
* agent registry so the two systems share ONE view.
|
|
4
|
+
*
|
|
5
|
+
* The problem this solves: Swarmdo (MCP server + CLI + hooks) runs
|
|
6
|
+
* out-of-process and CANNOT invoke Claude Code's `Agent` tool — only the main
|
|
7
|
+
* Claude Code loop can spawn real LLM workers. So today a session can run four
|
|
8
|
+
* Claude Code agents while `swarmdo agent list` stays empty: installed but
|
|
9
|
+
* inert. The honest integration is a BINDING — when a real Claude Code agent is
|
|
10
|
+
* spawned, register a bound record in Swarmdo's canonical store
|
|
11
|
+
* (`.swarmdo/agents/store.json`, via the existing `agent_spawn`/registerAgent
|
|
12
|
+
* path — NO parallel store) so `swarmdo agent list` / `swarm_status` reflect
|
|
13
|
+
* reality, and reconcile the two sides on demand.
|
|
14
|
+
*
|
|
15
|
+
* Pure + deterministic: these functions build the registration input, classify
|
|
16
|
+
* whether a prompt warrants a swarm, and diff the two rosters. All fs / MCP /
|
|
17
|
+
* spawning lives in the command + hook layers, so this module is
|
|
18
|
+
* fully fixture-testable.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Deterministic Swarmdo agentId for a Claude Code agent — stable across
|
|
22
|
+
* re-registration so binding the same agent twice UPDATES the record rather
|
|
23
|
+
* than spawning a duplicate (registerAgent honors an explicit `agentId`). Pure.
|
|
24
|
+
*/
|
|
25
|
+
export function bridgeAgentId(d) {
|
|
26
|
+
const sess = d.sessionId ? d.sessionId.replace(/[^A-Za-z0-9]/g, '').slice(0, 8) || 'nosess' : 'nosess';
|
|
27
|
+
const safe = d.name.replace(/[^A-Za-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'agent';
|
|
28
|
+
return `cc-${sess}-${safe}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build the `agent_spawn` input that registers a bound Swarmdo record for a
|
|
32
|
+
* Claude Code agent. Pure — returns the input object; the caller persists it via
|
|
33
|
+
* the real registerAgent / `agent_spawn` path (so the swarm-join + graph-node +
|
|
34
|
+
* store all happen exactly as for a native Swarmdo agent). `nowIso` is injected
|
|
35
|
+
* for testability.
|
|
36
|
+
*/
|
|
37
|
+
export function buildSpawnInput(d, nowIso) {
|
|
38
|
+
const binding = {
|
|
39
|
+
origin: 'claude-code',
|
|
40
|
+
claudeName: d.name,
|
|
41
|
+
...(d.sessionId ? { sessionId: d.sessionId } : {}),
|
|
42
|
+
...(d.task ? { task: d.task } : {}),
|
|
43
|
+
boundAt: nowIso,
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
agentId: bridgeAgentId(d),
|
|
47
|
+
agentType: d.agentType,
|
|
48
|
+
domain: 'claude-code-bridge',
|
|
49
|
+
...(d.task ? { task: d.task } : {}),
|
|
50
|
+
config: { binding },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Is a Swarmdo record a Claude-Code binding (vs a native Swarmdo agent)? Pure. */
|
|
54
|
+
export function isBound(a) {
|
|
55
|
+
return a.config?.binding?.origin === 'claude-code';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Diff the live Claude Code roster against the Swarmdo store. Pure. Only
|
|
59
|
+
* Claude-Code-bound records participate (native Swarmdo agents are ignored).
|
|
60
|
+
* Returns sorted, de-duplicated name lists so output is deterministic.
|
|
61
|
+
*/
|
|
62
|
+
export function reconcile(swarmdoAgents, liveClaudeNames) {
|
|
63
|
+
const live = new Set(liveClaudeNames);
|
|
64
|
+
const bound = swarmdoAgents.filter(isBound);
|
|
65
|
+
const boundNames = new Set(bound.map((a) => a.config.binding.claudeName));
|
|
66
|
+
const mirrored = [];
|
|
67
|
+
const orphaned = [];
|
|
68
|
+
for (const a of bound) {
|
|
69
|
+
const nm = a.config.binding.claudeName;
|
|
70
|
+
if (live.has(nm))
|
|
71
|
+
mirrored.push(nm);
|
|
72
|
+
else
|
|
73
|
+
orphaned.push(nm);
|
|
74
|
+
}
|
|
75
|
+
const unmirrored = liveClaudeNames.filter((nm) => !boundNames.has(nm));
|
|
76
|
+
const uniqSort = (xs) => [...new Set(xs)].sort();
|
|
77
|
+
return { mirrored: uniqSort(mirrored), unmirrored: uniqSort(unmirrored), orphaned: uniqSort(orphaned) };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* agentIds of Claude-Code-bound records whose bound agent is NOT in the live
|
|
81
|
+
* roster — the orphans to reap so stale bindings don't accumulate across
|
|
82
|
+
* sessions. Native (unbound) Swarmdo agents are never selected. Pure; sorted
|
|
83
|
+
* for deterministic pruning. Complements `reconcile` (which reports orphan
|
|
84
|
+
* NAMES) by giving the store keys the prune path deletes.
|
|
85
|
+
*/
|
|
86
|
+
export function orphanedAgentIds(swarmdoAgents, liveClaudeNames) {
|
|
87
|
+
const live = new Set(liveClaudeNames);
|
|
88
|
+
return swarmdoAgents
|
|
89
|
+
.filter((a) => isBound(a) && !live.has(a.config.binding.claudeName))
|
|
90
|
+
.map((a) => a.agentId)
|
|
91
|
+
.sort();
|
|
92
|
+
}
|
|
93
|
+
// Work that benefits from a swarm — verbs that imply multi-step build/change.
|
|
94
|
+
const AGENTIC_RE = /\b(implement|build|create|add(?:ing)?|develop|refactor\w*|migrat\w*|redesign|re-?architect\w*|architect\w*|feature|integrat\w*|overhaul|rewrite|port|scaffold|end-to-end|multi-file|test suite|coverage|audit|harden\w*|vulnerab\w*|cve|fix\w*|debug\w*|optimi[sz]e|performance)\b/i;
|
|
95
|
+
// Signals the task is trivial / conversational — a single edit or a question.
|
|
96
|
+
const TRIVIAL_RE = /\b(what|why|how|explain|describe|show|list|find|search|where|which|typo|readme|comment|one-?liner|quick question|rename|bump (?:the )?version|status|help)\b/i;
|
|
97
|
+
// Role-selecting signals (checked in priority order).
|
|
98
|
+
const ROLE_SIGNALS = [
|
|
99
|
+
{ re: /\b(security|vulnerab\w*|cve|auth\w*|inject\w*|xss|ssrf)\b/i, roles: ['security-auditor', 'coder', 'reviewer'] },
|
|
100
|
+
{ re: /\b(refactor\w*|migrat\w*|redesign|re-?architect\w*|overhaul|rewrite)\b/i, roles: ['system-architect', 'coder', 'reviewer'] },
|
|
101
|
+
{ re: /\b(perf\w*|optimi[sz]e|benchmark|latency|throughput)\b/i, roles: ['perf-analyzer', 'coder', 'tester'] },
|
|
102
|
+
{ re: /\b(test|coverage|tdd|spec)\b/i, roles: ['tester', 'coder', 'reviewer'] },
|
|
103
|
+
{ re: /\b(feature|implement|build|integrat\w*|end-to-end|api)\b/i, roles: ['researcher', 'system-architect', 'coder', 'tester', 'reviewer'] },
|
|
104
|
+
];
|
|
105
|
+
/**
|
|
106
|
+
* Decide whether a prompt warrants a bound-agent swarm, and which roles. Pure.
|
|
107
|
+
* requiresAgents is true when an agentic verb fires AND the prompt is long
|
|
108
|
+
* enough that it isn't a one-line question — a trivial/conversational signal
|
|
109
|
+
* alone (with no agentic verb) suppresses it. Deterministic; no LLM.
|
|
110
|
+
*/
|
|
111
|
+
export function classifyPrompt(prompt) {
|
|
112
|
+
const p = (prompt || '').trim();
|
|
113
|
+
if (!p)
|
|
114
|
+
return { requiresAgents: false, reason: 'empty prompt', suggestedRoles: [] };
|
|
115
|
+
const agentic = AGENTIC_RE.test(p);
|
|
116
|
+
const trivial = TRIVIAL_RE.test(p);
|
|
117
|
+
// A short prompt (< 24 chars) with no agentic verb is almost always a question.
|
|
118
|
+
if (!agentic)
|
|
119
|
+
return { requiresAgents: false, reason: trivial ? 'conversational / single-step' : 'no agentic intent detected', suggestedRoles: [] };
|
|
120
|
+
// Agentic verb present but the prompt is a bare one-liner AND reads trivial →
|
|
121
|
+
// treat as a quick edit, not a swarm (e.g. "add a comment", "rename the flag").
|
|
122
|
+
if (trivial && p.length < 40)
|
|
123
|
+
return { requiresAgents: false, reason: 'agentic verb but reads as a quick single edit', suggestedRoles: [] };
|
|
124
|
+
let roles = ['coder'];
|
|
125
|
+
for (const sig of ROLE_SIGNALS) {
|
|
126
|
+
if (sig.re.test(p)) {
|
|
127
|
+
roles = sig.roles;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { requiresAgents: true, reason: 'agentic task — swarm recommended', suggestedRoles: roles };
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../src/agent-bridge/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* command-usage/usage.ts — a hot/cold/orphan USAGE report for a project's
|
|
3
|
+
* authored `.claude/` surface. `config lint` validates these files; this answers
|
|
4
|
+
* the orthogonal "are they actually used?" by joining the DEFINED set
|
|
5
|
+
* (`.claude/commands/**/*.md` + `.claude/agents/**/*.md`) against INVOCATION
|
|
6
|
+
* counts mined from the local transcripts (`<command-name>` markers +
|
|
7
|
+
* `"subagent_type"` fields). Three buckets: hot (defined & invoked), cold
|
|
8
|
+
* (defined, never invoked → prune candidates), orphan (invoked, not defined →
|
|
9
|
+
* typo / removed / builtin). #101.
|
|
10
|
+
*
|
|
11
|
+
* The parsers + join are pure and unit-tested; only collectCommandUsage touches
|
|
12
|
+
* the filesystem. Reuses defaultClaudeProjectDirs/findTranscriptFiles.
|
|
13
|
+
*/
|
|
14
|
+
export interface UsageItem {
|
|
15
|
+
name: string;
|
|
16
|
+
count: number;
|
|
17
|
+
}
|
|
18
|
+
export interface UsageBuckets {
|
|
19
|
+
/** defined AND invoked (count > 0), desc by count */
|
|
20
|
+
hot: UsageItem[];
|
|
21
|
+
/** defined but never invoked — prune candidates, sorted */
|
|
22
|
+
cold: string[];
|
|
23
|
+
/** invoked but not defined (typo / removed / builtin), sorted */
|
|
24
|
+
orphan: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface CommandUsageReport {
|
|
27
|
+
commands: UsageBuckets;
|
|
28
|
+
agents: UsageBuckets;
|
|
29
|
+
filesScanned: number;
|
|
30
|
+
definedCommands: number;
|
|
31
|
+
definedAgents: number;
|
|
32
|
+
scope: 'project' | 'all';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Count custom slash-command invocations from raw transcript lines. Scoped to
|
|
36
|
+
* user-role lines (the `<command-name>` marker is injected on the user turn) so
|
|
37
|
+
* an assistant merely quoting the marker never inflates a count. The captured
|
|
38
|
+
* name is de-slashed (`/goal` → `goal`) to match the discovered-file key space.
|
|
39
|
+
* Pure.
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseCommandInvocations(lines: string[]): Map<string, number>;
|
|
42
|
+
/**
|
|
43
|
+
* Count subagent (Task tool) invocations by `subagent_type` from raw transcript
|
|
44
|
+
* lines. Not user-scoped — the field lives in an assistant `tool_use` block. Pure.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseSubagentInvocations(lines: string[]): Map<string, number>;
|
|
47
|
+
/** Merge src counts into dest (dest mutated). */
|
|
48
|
+
export declare function mergeCounts(dest: Map<string, number>, src: Map<string, number>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Join a DEFINED name list against INVOCATION counts into hot/cold/orphan. Both
|
|
51
|
+
* sides are compared de-slashed, so a defined `/build` matches a `build` count
|
|
52
|
+
* (agents carry no slash, so they're unaffected). Pure & deterministic. */
|
|
53
|
+
export declare function joinUsage(defined: string[], counts: Map<string, number> | Record<string, number>): UsageBuckets;
|
|
54
|
+
/**
|
|
55
|
+
* Discover the authored `.claude/` surface for a project. Command names use
|
|
56
|
+
* Claude Code's subdir namespacing (`.claude/commands/sDo/x.md` → `sDo:x`, top
|
|
57
|
+
* level → `x`) to match the `<command-name>` marker; agent names are the file
|
|
58
|
+
* basename (subagent_type is never namespaced). Pure w.r.t. inputs (reads fs).
|
|
59
|
+
*/
|
|
60
|
+
export declare function discoverAuthored(cwd: string): {
|
|
61
|
+
commands: string[];
|
|
62
|
+
agents: string[];
|
|
63
|
+
};
|
|
64
|
+
export interface CollectOptions {
|
|
65
|
+
cwd?: string;
|
|
66
|
+
/** scan every project's transcripts (default: only the current project) */
|
|
67
|
+
all?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/** The encoded transcript-dir name Claude Code uses for a project path. */
|
|
70
|
+
export declare function encodeProjectDir(cwd: string): string;
|
|
71
|
+
/** Build the full report: discover authored files, mine invocation counts from
|
|
72
|
+
* the (project-scoped, or --all) transcripts, and join. fs-touching wrapper. */
|
|
73
|
+
export declare function collectCommandUsage(opts?: CollectOptions): CommandUsageReport;
|
|
74
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/command-usage/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC3D,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,GAAG,EAAE,SAAS,EAAE,CAAC;IACjB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iEAAiE;IACjE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AACD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC;CAC1B;AAID;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAW5E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAS7E;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAErF;AAED;;;2EAG2E;AAC3E,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAmB/G;AAqBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAQtF;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;gFACgF;AAChF,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,cAAmB,GAAG,kBAAkB,CA6BjF"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* command-usage/usage.ts — a hot/cold/orphan USAGE report for a project's
|
|
3
|
+
* authored `.claude/` surface. `config lint` validates these files; this answers
|
|
4
|
+
* the orthogonal "are they actually used?" by joining the DEFINED set
|
|
5
|
+
* (`.claude/commands/**/*.md` + `.claude/agents/**/*.md`) against INVOCATION
|
|
6
|
+
* counts mined from the local transcripts (`<command-name>` markers +
|
|
7
|
+
* `"subagent_type"` fields). Three buckets: hot (defined & invoked), cold
|
|
8
|
+
* (defined, never invoked → prune candidates), orphan (invoked, not defined →
|
|
9
|
+
* typo / removed / builtin). #101.
|
|
10
|
+
*
|
|
11
|
+
* The parsers + join are pure and unit-tested; only collectCommandUsage touches
|
|
12
|
+
* the filesystem. Reuses defaultClaudeProjectDirs/findTranscriptFiles.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import { defaultClaudeProjectDirs, findTranscriptFiles } from '../usage/transcript-usage.js';
|
|
17
|
+
const uniqSort = (xs) => [...new Set(xs)].sort((a, b) => a.localeCompare(b));
|
|
18
|
+
/**
|
|
19
|
+
* Count custom slash-command invocations from raw transcript lines. Scoped to
|
|
20
|
+
* user-role lines (the `<command-name>` marker is injected on the user turn) so
|
|
21
|
+
* an assistant merely quoting the marker never inflates a count. The captured
|
|
22
|
+
* name is de-slashed (`/goal` → `goal`) to match the discovered-file key space.
|
|
23
|
+
* Pure.
|
|
24
|
+
*/
|
|
25
|
+
export function parseCommandInvocations(lines) {
|
|
26
|
+
const counts = new Map();
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
if (!/"(?:type|role)"\s*:\s*"user"/.test(line))
|
|
29
|
+
continue;
|
|
30
|
+
for (const m of line.matchAll(/<command-name>([^<]+)<\/command-name>/g)) {
|
|
31
|
+
const name = m[1].trim().replace(/^\/+/, '');
|
|
32
|
+
if (!name || name === '…')
|
|
33
|
+
continue;
|
|
34
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return counts;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Count subagent (Task tool) invocations by `subagent_type` from raw transcript
|
|
41
|
+
* lines. Not user-scoped — the field lives in an assistant `tool_use` block. Pure.
|
|
42
|
+
*/
|
|
43
|
+
export function parseSubagentInvocations(lines) {
|
|
44
|
+
const counts = new Map();
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
for (const m of line.matchAll(/"subagent_type"\s*:\s*"([^"]+)"/g)) {
|
|
47
|
+
const name = m[1].trim();
|
|
48
|
+
if (name)
|
|
49
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return counts;
|
|
53
|
+
}
|
|
54
|
+
/** Merge src counts into dest (dest mutated). */
|
|
55
|
+
export function mergeCounts(dest, src) {
|
|
56
|
+
for (const [k, v] of src)
|
|
57
|
+
dest.set(k, (dest.get(k) ?? 0) + v);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Join a DEFINED name list against INVOCATION counts into hot/cold/orphan. Both
|
|
61
|
+
* sides are compared de-slashed, so a defined `/build` matches a `build` count
|
|
62
|
+
* (agents carry no slash, so they're unaffected). Pure & deterministic. */
|
|
63
|
+
export function joinUsage(defined, counts) {
|
|
64
|
+
const asMap = counts instanceof Map ? counts : new Map(Object.entries(counts));
|
|
65
|
+
const norm = (n) => n.replace(/^\/+/, '');
|
|
66
|
+
const get = (n) => asMap.get(norm(n)) ?? 0;
|
|
67
|
+
const definedNorm = new Set(defined.map(norm));
|
|
68
|
+
const hot = [];
|
|
69
|
+
const cold = [];
|
|
70
|
+
for (const d of defined) {
|
|
71
|
+
const c = get(d);
|
|
72
|
+
if (c > 0)
|
|
73
|
+
hot.push({ name: d, count: c });
|
|
74
|
+
else
|
|
75
|
+
cold.push(d);
|
|
76
|
+
}
|
|
77
|
+
const orphan = [];
|
|
78
|
+
for (const [k, v] of asMap) {
|
|
79
|
+
if (v > 0 && !definedNorm.has(norm(k)))
|
|
80
|
+
orphan.push(k);
|
|
81
|
+
}
|
|
82
|
+
hot.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
83
|
+
return { hot, cold: uniqSort(cold), orphan: uniqSort(orphan) };
|
|
84
|
+
}
|
|
85
|
+
/** All `.md` files under `root`, as paths RELATIVE to root (recursive; skips
|
|
86
|
+
* dotfiles). Mirrors config.ts's walkMd so `config lint` and this command agree
|
|
87
|
+
* on what counts as "defined". */
|
|
88
|
+
function walkMdRel(root) {
|
|
89
|
+
const out = [];
|
|
90
|
+
const rec = (dir, prefix) => {
|
|
91
|
+
let entries;
|
|
92
|
+
try {
|
|
93
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
for (const e of entries) {
|
|
99
|
+
if (e.name.startsWith('.'))
|
|
100
|
+
continue;
|
|
101
|
+
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
102
|
+
if (e.isDirectory())
|
|
103
|
+
rec(path.join(dir, e.name), rel);
|
|
104
|
+
else if (e.isFile() && e.name.endsWith('.md'))
|
|
105
|
+
out.push(rel);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
rec(root, '');
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Discover the authored `.claude/` surface for a project. Command names use
|
|
113
|
+
* Claude Code's subdir namespacing (`.claude/commands/sDo/x.md` → `sDo:x`, top
|
|
114
|
+
* level → `x`) to match the `<command-name>` marker; agent names are the file
|
|
115
|
+
* basename (subagent_type is never namespaced). Pure w.r.t. inputs (reads fs).
|
|
116
|
+
*/
|
|
117
|
+
export function discoverAuthored(cwd) {
|
|
118
|
+
const commands = walkMdRel(path.join(cwd, '.claude', 'commands')).map((rel) => rel.replace(/\.md$/, '').split('/').join(':'));
|
|
119
|
+
const agents = walkMdRel(path.join(cwd, '.claude', 'agents')).map((rel) => path.basename(rel).replace(/\.md$/, ''));
|
|
120
|
+
return { commands: uniqSort(commands), agents: uniqSort(agents) };
|
|
121
|
+
}
|
|
122
|
+
/** The encoded transcript-dir name Claude Code uses for a project path. */
|
|
123
|
+
export function encodeProjectDir(cwd) {
|
|
124
|
+
return cwd.replace(/\//g, '-');
|
|
125
|
+
}
|
|
126
|
+
/** Build the full report: discover authored files, mine invocation counts from
|
|
127
|
+
* the (project-scoped, or --all) transcripts, and join. fs-touching wrapper. */
|
|
128
|
+
export function collectCommandUsage(opts = {}) {
|
|
129
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
130
|
+
const { commands: definedCommands, agents: definedAgents } = discoverAuthored(cwd);
|
|
131
|
+
const encoded = encodeProjectDir(cwd);
|
|
132
|
+
const cmdCounts = new Map();
|
|
133
|
+
const agentCounts = new Map();
|
|
134
|
+
let filesScanned = 0;
|
|
135
|
+
for (const dir of defaultClaudeProjectDirs()) {
|
|
136
|
+
for (const t of findTranscriptFiles(dir)) {
|
|
137
|
+
if (!opts.all && t.project !== encoded)
|
|
138
|
+
continue;
|
|
139
|
+
filesScanned++;
|
|
140
|
+
let content;
|
|
141
|
+
try {
|
|
142
|
+
content = fs.readFileSync(t.file, 'utf8');
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const fileLines = content.split('\n');
|
|
148
|
+
mergeCounts(cmdCounts, parseCommandInvocations(fileLines));
|
|
149
|
+
mergeCounts(agentCounts, parseSubagentInvocations(fileLines));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
commands: joinUsage(definedCommands, cmdCounts),
|
|
154
|
+
agents: joinUsage(definedAgents, agentCounts),
|
|
155
|
+
filesScanned,
|
|
156
|
+
definedCommands: definedCommands.length,
|
|
157
|
+
definedAgents: definedAgents.length,
|
|
158
|
+
scope: opts.all ? 'all' : 'project',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/command-usage/usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/commands/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/commands/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;AAolC1E,eAAO,MAAM,YAAY,EAAE,OAqC1B,CAAC;AAoCF,eAAe,YAAY,CAAC"}
|