@chamba/claude-extras 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/README.md +54 -0
- package/assets/agents/planner.md +18 -0
- package/assets/commands/orq.md +8 -6
- package/assets/commands/ticket.md +27 -0
- package/dist/cli.js +90 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -117,6 +117,60 @@ records why — the config still drives every other editor through the MCP tool.
|
|
|
117
117
|
- **Why does `extreme` become `max` in Claude Code?** Claude Code's effort scale tops
|
|
118
118
|
out at `max`; `extreme` is chamba's name for "the ceiling".
|
|
119
119
|
|
|
120
|
+
## Multi-repo worktrees + the `/ticket` flow
|
|
121
|
+
|
|
122
|
+
If you work in a **workspace of several repos** (a parent dir with N git repos), chamba
|
|
123
|
+
can create an isolated worktree per repo for a ticket, reuse or fork the branch, copy
|
|
124
|
+
git-ignored `.env*` files, and write a `.code-workspace` — all driven by config.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx @chamba/claude-extras config worktrees init # interactive setup
|
|
128
|
+
npx @chamba/claude-extras config worktrees show # inspect the resolved policy
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
This writes a `worktrees` block to `~/.chamba/config.json` (or per project in
|
|
132
|
+
`./.chamba/config.json`):
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"version": 1,
|
|
137
|
+
"worktrees": {
|
|
138
|
+
"layout": "sibling",
|
|
139
|
+
"root": "WORKTREES",
|
|
140
|
+
"branchPrefix": "ticket/",
|
|
141
|
+
"baseBranch": "main",
|
|
142
|
+
"copyEnvFiles": true,
|
|
143
|
+
"editorWorkspace": "code-workspace",
|
|
144
|
+
"repos": ["api", "web", "functions"]
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- **layout** — `sibling` puts everything under `<workspace>/WORKTREES/<ticket>/<repo>`;
|
|
150
|
+
`nested` puts a worktree under each repo.
|
|
151
|
+
- **repos** — omit to autodetect the workspace's git repos.
|
|
152
|
+
- **command** — escape hatch: set it to your own script (e.g.
|
|
153
|
+
`"./ticket-create.sh {ticket} {repos}"`) and chamba shells out instead of using the
|
|
154
|
+
built-in. Migrate from a bespoke script to config whenever you want.
|
|
155
|
+
|
|
156
|
+
Then, in Claude Code:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
/ticket TICKET-123
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`/ticket` runs the full orchestrator-worker flow: create worktrees →
|
|
163
|
+
`chamba_load_context` → delegate the plan to the **planner** subagent →
|
|
164
|
+
`chamba_review_plan` + the **reviewer** subagent → delegate code to **implementer** and
|
|
165
|
+
tests to **tester** (all inside the worktrees) → `chamba_summarize_to_vault`. It runs to
|
|
166
|
+
the end and stops for your review. It **never commits, merges or pushes** — you review,
|
|
167
|
+
commit and send to code review by hand. Each worker runs with the model + effort you
|
|
168
|
+
configured above.
|
|
169
|
+
|
|
170
|
+
> **Security:** `copyEnvFiles` copies secrets into the worktree directories. Add your
|
|
171
|
+
> `worktrees.root` (e.g. `WORKTREES/`) to `.gitignore` so they're never committed. It's
|
|
172
|
+
> off by default.
|
|
173
|
+
|
|
120
174
|
## License
|
|
121
175
|
|
|
122
176
|
MIT
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planner
|
|
3
|
+
description: Produces a detailed, reviewable implementation plan for a ticket, decomposed by repo
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the **planner**. You receive a ticket and the loaded context (workspace
|
|
7
|
+
map + relevant notes). Produce a concrete, reviewable plan — do not write code.
|
|
8
|
+
|
|
9
|
+
- Decompose the work into subtasks, grouped by repo when it spans several.
|
|
10
|
+
- For each subtask: the goal, the files likely touched, and which worker does it.
|
|
11
|
+
- State explicit acceptance criteria and how they'll be verified (tests).
|
|
12
|
+
- Call out risks and any sensitive areas (auth, payments, migrations, data).
|
|
13
|
+
- Keep it tight and concrete enough that an implementer can execute it without
|
|
14
|
+
guessing. If the ticket is ambiguous, state the assumptions you made instead of
|
|
15
|
+
inventing scope.
|
|
16
|
+
|
|
17
|
+
Return the plan as structured markdown. The orchestrator runs it through
|
|
18
|
+
`chamba_review_plan` and the reviewer subagent before any code is written.
|
package/assets/commands/orq.md
CHANGED
|
@@ -6,15 +6,17 @@ argument-hint: <task>
|
|
|
6
6
|
You are orchestrating this task with chamba's MCP tools: **$ARGUMENTS**
|
|
7
7
|
|
|
8
8
|
Follow the orchestrator-worker flow. chamba provides context, plan validation,
|
|
9
|
-
worktrees and vault writing; you
|
|
9
|
+
worktrees and vault writing; you orchestrate and delegate to the subagents (which
|
|
10
|
+
run with the model + effort you configured via `chamba-config`).
|
|
10
11
|
|
|
11
12
|
1. Call `chamba_load_context` with the task to pull workspace + relevant notes.
|
|
12
|
-
2.
|
|
13
|
-
|
|
14
|
-
3. Call `chamba_review_plan` with
|
|
15
|
-
|
|
13
|
+
2. Delegate to the **planner** subagent to produce the plan (goal, acceptance
|
|
14
|
+
criteria, subtasks with workers, risks, files).
|
|
15
|
+
3. Call `chamba_review_plan` with the plan and have the **reviewer** subagent
|
|
16
|
+
audit it. If not approved, fix the issues and review again (max 3 rounds).
|
|
16
17
|
4. Show me the approved plan and wait for my go-ahead.
|
|
17
18
|
5. If this is a git repo, call `chamba_create_worktree` per worker for isolation.
|
|
18
|
-
6.
|
|
19
|
+
6. Delegate implementation to the **implementer** subagent (in its worktree) and
|
|
20
|
+
the tests to the **tester** subagent; run them.
|
|
19
21
|
7. When done, call `chamba_summarize_to_vault` with a summary of what changed.
|
|
20
22
|
8. Leave any worktree branches open — do not merge. Tell me the merge command.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Resolve a ticket end-to-end in isolated worktrees, delegating to chamba's agents
|
|
3
|
+
argument-hint: <ticket> [repo ...]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are orchestrating ticket **$ARGUMENTS** end-to-end. chamba provides the
|
|
7
|
+
worktrees, context, plan validation and vault memory; you delegate the thinking
|
|
8
|
+
and the code to the configured subagents. **Run to the end and stop only for my
|
|
9
|
+
final review** — do not pause for approval mid-way.
|
|
10
|
+
|
|
11
|
+
1. Create isolated worktrees: call `chamba_create_worktrees` with the ticket id
|
|
12
|
+
(and the repos if I named any). ALL work happens INSIDE these worktrees —
|
|
13
|
+
never edit the main checkouts. Note the branch and per-repo worktree paths.
|
|
14
|
+
2. Call `chamba_load_context` with the ticket to pull the workspace map + relevant
|
|
15
|
+
Obsidian notes.
|
|
16
|
+
3. Delegate to the **planner** subagent to produce the detailed plan. Run it
|
|
17
|
+
through `chamba_review_plan`; if not approved, fix and re-review (max 3 rounds).
|
|
18
|
+
Also have the **reviewer** subagent audit it. Do all of this WITHOUT stopping to
|
|
19
|
+
ask me — the heuristic review + the reviewer agent are the quality gate.
|
|
20
|
+
4. For each subtask/repo, delegate implementation to the **implementer** subagent,
|
|
21
|
+
working only in that repo's worktree. Delegate the tests to the **tester**
|
|
22
|
+
subagent and run them.
|
|
23
|
+
5. Call `chamba_summarize_to_vault` with a summary of what changed.
|
|
24
|
+
6. STOP and report for my review: per repo, what changed and the test results; the
|
|
25
|
+
`.code-workspace` to open; and the suggested commit + `git merge --no-ff`
|
|
26
|
+
commands. Do NOT commit, merge or push — I review, commit and send to my
|
|
27
|
+
company's code review by hand.
|
package/dist/cli.js
CHANGED
|
@@ -56,6 +56,19 @@ var ConfigStore = class {
|
|
|
56
56
|
await this.write(parsed.value);
|
|
57
57
|
return parsed.value;
|
|
58
58
|
}
|
|
59
|
+
/** Merge a patch into the `worktrees` block and persist (validated). */
|
|
60
|
+
async setWorktrees(patch) {
|
|
61
|
+
const current = await this.read();
|
|
62
|
+
const next = {
|
|
63
|
+
...current,
|
|
64
|
+
version: 1,
|
|
65
|
+
worktrees: { ...current.worktrees ?? {}, ...patch }
|
|
66
|
+
};
|
|
67
|
+
const parsed = parseChambaConfig(next);
|
|
68
|
+
if (!parsed.ok) throw new ConfigError(parsed.error);
|
|
69
|
+
await this.write(parsed.value);
|
|
70
|
+
return parsed.value;
|
|
71
|
+
}
|
|
59
72
|
/** Write the compiled defaults as the full config. */
|
|
60
73
|
async reset() {
|
|
61
74
|
await this.write({ version: 1, defaults: DEFAULT_CONFIG.defaults });
|
|
@@ -71,6 +84,7 @@ import { joinPath, loadConfig } from "@chamba/core";
|
|
|
71
84
|
// src/agent-frontmatter.ts
|
|
72
85
|
import { getModel } from "@chamba/core";
|
|
73
86
|
var AGENT_ROLE_BY_FILE = {
|
|
87
|
+
"planner.md": "planner",
|
|
74
88
|
"implementer.md": "implementer",
|
|
75
89
|
"reviewer.md": "reviewer",
|
|
76
90
|
"tester.md": "tester"
|
|
@@ -269,11 +283,12 @@ function asRecord(value) {
|
|
|
269
283
|
import {
|
|
270
284
|
AGENT_ROLES,
|
|
271
285
|
DEFAULT_CONFIG as DEFAULT_CONFIG2,
|
|
286
|
+
DEFAULT_WORKTREE_CONFIG,
|
|
272
287
|
EFFORT_LEVELS,
|
|
273
288
|
MODEL_CATALOG,
|
|
274
289
|
ROLE_DESCRIPTIONS
|
|
275
290
|
} from "@chamba/core";
|
|
276
|
-
import { confirm, select } from "@inquirer/prompts";
|
|
291
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
277
292
|
function defaultConfigFile() {
|
|
278
293
|
return { version: 1, defaults: DEFAULT_CONFIG2.defaults };
|
|
279
294
|
}
|
|
@@ -298,6 +313,42 @@ function effortChoices() {
|
|
|
298
313
|
function isCancellation(e) {
|
|
299
314
|
return e instanceof Error && e.name === "ExitPromptError";
|
|
300
315
|
}
|
|
316
|
+
async function runWorktreesWizard() {
|
|
317
|
+
const d = DEFAULT_WORKTREE_CONFIG;
|
|
318
|
+
const layout = await select({
|
|
319
|
+
message: "Worktree layout",
|
|
320
|
+
choices: [
|
|
321
|
+
{
|
|
322
|
+
name: "sibling \u2014 one folder per ticket (<root>/<ticket>/<repo>)",
|
|
323
|
+
value: "sibling"
|
|
324
|
+
},
|
|
325
|
+
{ name: "nested \u2014 a worktree under each repo", value: "nested" }
|
|
326
|
+
],
|
|
327
|
+
default: d.layout
|
|
328
|
+
});
|
|
329
|
+
const root = await input({
|
|
330
|
+
message: "Worktree root directory",
|
|
331
|
+
default: layout === "sibling" ? "WORKTREES" : ".chamba/worktrees"
|
|
332
|
+
});
|
|
333
|
+
const branchPrefix = await input({ message: "Branch prefix", default: "ticket/" });
|
|
334
|
+
const baseBranch = await input({ message: "Base branch to fork from", default: d.baseBranch });
|
|
335
|
+
const copyEnvFiles = await confirm({
|
|
336
|
+
message: "Copy git-ignored .env* files into worktrees?",
|
|
337
|
+
default: false
|
|
338
|
+
});
|
|
339
|
+
const editor = await confirm({
|
|
340
|
+
message: "Generate a .code-workspace per ticket?",
|
|
341
|
+
default: true
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
layout,
|
|
345
|
+
root,
|
|
346
|
+
branchPrefix,
|
|
347
|
+
baseBranch,
|
|
348
|
+
copyEnvFiles,
|
|
349
|
+
editorWorkspace: editor ? "code-workspace" : null
|
|
350
|
+
};
|
|
351
|
+
}
|
|
301
352
|
async function runWizard(opts = {}) {
|
|
302
353
|
if (opts.nonInteractive) return defaultConfigFile();
|
|
303
354
|
try {
|
|
@@ -379,6 +430,19 @@ async function cmdSet(store, args) {
|
|
|
379
430
|
const effortNote = args.effort ? ` with effort ${args.effort}` : "";
|
|
380
431
|
return `Set ${args.role} \u2192 ${args.model}${effortNote}. Run 'config apply' to regenerate subagents.`;
|
|
381
432
|
}
|
|
433
|
+
function formatWorktrees(w) {
|
|
434
|
+
return [
|
|
435
|
+
"worktrees config:",
|
|
436
|
+
` layout ${w.layout}`,
|
|
437
|
+
` root ${w.root}`,
|
|
438
|
+
` branchPrefix ${w.branchPrefix}`,
|
|
439
|
+
` baseBranch ${w.baseBranch}`,
|
|
440
|
+
` copyEnvFiles ${w.copyEnvFiles}`,
|
|
441
|
+
` editorWorkspace ${w.editorWorkspace ?? "(none)"}`,
|
|
442
|
+
` repos ${w.repos ? w.repos.join(", ") : "(autodetect)"}`,
|
|
443
|
+
` command ${w.command ?? "(none)"}`
|
|
444
|
+
].join("\n");
|
|
445
|
+
}
|
|
382
446
|
function buildInstaller(fs) {
|
|
383
447
|
const home = homedir();
|
|
384
448
|
const assetsDir = fileURLToPath(new URL("../assets", import.meta.url));
|
|
@@ -394,7 +458,7 @@ function parseEffortFlag(rest) {
|
|
|
394
458
|
const i = rest.indexOf("--effort");
|
|
395
459
|
return i >= 0 ? rest[i + 1] : void 0;
|
|
396
460
|
}
|
|
397
|
-
var USAGE = "Usage: chamba-install config <show|models|set|reset|wizard|apply|edit>\n show resolved config + where each value comes from\n models list the available models\n set <role> <model> [--effort <level>] change one role\n reset [--yes] restore defaults\n wizard [--defaults] (re)run the interactive wizard\n apply regenerate ~/.claude/agents from the config\n edit open the config in $EDITOR\n";
|
|
461
|
+
var USAGE = "Usage: chamba-install config <show|models|set|reset|wizard|apply|edit>\n show resolved config + where each value comes from\n models list the available models\n set <role> <model> [--effort <level>] change one role\n reset [--yes] restore defaults\n wizard [--defaults] (re)run the interactive wizard\n worktrees <show|init> show or configure the multi-repo worktree policy\n apply regenerate ~/.claude/agents from the config\n edit open the config in $EDITOR\n";
|
|
398
462
|
async function runConfigCommand(args) {
|
|
399
463
|
const [command, ...rest] = args;
|
|
400
464
|
const fs = new NodeFilesystem();
|
|
@@ -447,6 +511,30 @@ async function runConfigCommand(args) {
|
|
|
447
511
|
`);
|
|
448
512
|
return;
|
|
449
513
|
}
|
|
514
|
+
case "worktrees": {
|
|
515
|
+
const sub = rest[0];
|
|
516
|
+
if (sub === "show") {
|
|
517
|
+
const { worktrees } = await loadConfig2(fs, {
|
|
518
|
+
globalPath: globalConfigPath(),
|
|
519
|
+
projectPath: projectConfigPath()
|
|
520
|
+
});
|
|
521
|
+
process.stdout.write(`${formatWorktrees(worktrees)}
|
|
522
|
+
`);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
if (sub === "init") {
|
|
526
|
+
const patch = await runWorktreesWizard();
|
|
527
|
+
await store.setWorktrees(patch);
|
|
528
|
+
process.stdout.write(
|
|
529
|
+
`Wrote worktrees config to ${store.filePath}.${patch.copyEnvFiles ? ` Tip: add '${patch.root}/' to your .gitignore.` : ""}
|
|
530
|
+
`
|
|
531
|
+
);
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
process.stderr.write("Usage: config worktrees <show|init>\n");
|
|
535
|
+
process.exitCode = sub ? 1 : 0;
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
450
538
|
case "apply": {
|
|
451
539
|
const result = await buildInstaller(fs).applyConfig();
|
|
452
540
|
process.stdout.write(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chamba/claude-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Optional Claude Code extras for chamba: slash commands, subagents and hooks installer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@inquirer/prompts": "^7.0.0",
|
|
34
|
-
"@chamba/adapters": "0.
|
|
35
|
-
"@chamba/core": "0.
|
|
34
|
+
"@chamba/adapters": "0.3.0",
|
|
35
|
+
"@chamba/core": "0.3.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^22.0.0",
|