@bunshin-cc/bunshin 0.3.1 → 0.3.2
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/bin.js +30 -2
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -4175,11 +4175,13 @@ var init_exports = {};
|
|
|
4175
4175
|
__export(init_exports, {
|
|
4176
4176
|
CODEX_HOOK_EVENTS: () => CODEX_HOOK_EVENTS,
|
|
4177
4177
|
HOOK_EVENTS: () => HOOK_EVENTS,
|
|
4178
|
+
LEARN_COMMAND: () => LEARN_COMMAND,
|
|
4178
4179
|
PRE_TOOL_MATCHER: () => PRE_TOOL_MATCHER,
|
|
4179
4180
|
bunshinHookEntry: () => bunshinHookEntry,
|
|
4180
4181
|
claudeSettingsPath: () => claudeSettingsPath,
|
|
4181
4182
|
countBunshinHooks: () => countBunshinHooks,
|
|
4182
4183
|
installClaudeHooks: () => installClaudeHooks,
|
|
4184
|
+
installLearnCommand: () => installLearnCommand,
|
|
4183
4185
|
installMcpConfig: () => installMcpConfig,
|
|
4184
4186
|
installPiExtension: () => installPiExtension,
|
|
4185
4187
|
isBunshinEntry: () => isBunshinEntry,
|
|
@@ -4290,6 +4292,24 @@ function mcpLauncher(bin) {
|
|
|
4290
4292
|
}
|
|
4291
4293
|
return { command: process.execPath, args: [script, "mcp"] };
|
|
4292
4294
|
}
|
|
4295
|
+
function installLearnCommand({ file, remove = false }) {
|
|
4296
|
+
try {
|
|
4297
|
+
const current = fileExists(file) ? fs13.readFileSync(file, "utf8") : null;
|
|
4298
|
+
const ours = current === null || current === LEARN_COMMAND;
|
|
4299
|
+
if (remove) {
|
|
4300
|
+
if (current !== null && ours) fs13.unlinkSync(file);
|
|
4301
|
+
return { file, installed: 0, changed: current !== null && ours };
|
|
4302
|
+
}
|
|
4303
|
+
if (!ours) return { file, installed: 0, changed: false, error: "a different learn.md is already there; left as it is" };
|
|
4304
|
+
if (current === null) {
|
|
4305
|
+
fs13.mkdirSync(path10.dirname(file), { recursive: true });
|
|
4306
|
+
fs13.writeFileSync(file, LEARN_COMMAND);
|
|
4307
|
+
}
|
|
4308
|
+
return { file, installed: 1, changed: current === null };
|
|
4309
|
+
} catch (err) {
|
|
4310
|
+
return { file, installed: 0, changed: false, error: err instanceof Error ? err.message : String(err) };
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4293
4313
|
function installMcpConfig({ file, launcher, remove = false }) {
|
|
4294
4314
|
try {
|
|
4295
4315
|
const before = fileExists(file) ? JSON.parse(fs13.readFileSync(file, "utf8")) : {};
|
|
@@ -4362,15 +4382,18 @@ function runInit(opts = {}) {
|
|
|
4362
4382
|
if (hooks.error) warnings.push(`could not update ${hooks.file}: ${hooks.error}`);
|
|
4363
4383
|
}
|
|
4364
4384
|
let mcp;
|
|
4385
|
+
let learnCommand;
|
|
4365
4386
|
if ((opts.removeHooks || !opts.noHooks) && config.harness === "claude-code" && scope === "repo") {
|
|
4366
4387
|
mcp = installMcpConfig({ file: path10.join(cwd, ".mcp.json"), launcher: opts.mcp ?? mcpLauncher(opts.bin), remove: opts.removeHooks });
|
|
4367
4388
|
if (mcp.error) warnings.push(`could not update ${mcp.file}: ${mcp.error}`);
|
|
4389
|
+
learnCommand = installLearnCommand({ file: path10.join(cwd, ".claude", "commands", "learn.md"), remove: opts.removeHooks });
|
|
4390
|
+
if (learnCommand.error) warnings.push(`/learn not installed at ${learnCommand.file}: ${learnCommand.error}`);
|
|
4368
4391
|
}
|
|
4369
4392
|
if (!resolveBackend(config)) {
|
|
4370
4393
|
warnings.push("No model backend found. Install and sign in to Codex or Claude Code before using automatic learning.");
|
|
4371
4394
|
}
|
|
4372
4395
|
store.log("init", { root, scope, role: config.role, orgUnit: config.orgUnit, hooks: hooks?.installed ?? 0 });
|
|
4373
|
-
return { root, config, created: !existed, hooks, ...mcp ? { mcp } : {}, warnings };
|
|
4396
|
+
return { root, config, created: !existed, hooks, ...mcp ? { mcp } : {}, ...learnCommand ? { learnCommand } : {}, warnings };
|
|
4374
4397
|
}
|
|
4375
4398
|
function otherHarnessInstructions() {
|
|
4376
4399
|
return [
|
|
@@ -4386,7 +4409,7 @@ function otherHarnessInstructions() {
|
|
|
4386
4409
|
" Claude Code plugin users need no settings.json wiring \u2014 the plugin ships hooks/hooks.json."
|
|
4387
4410
|
].join("\n");
|
|
4388
4411
|
}
|
|
4389
|
-
var PRE_TOOL_MATCHER, HOOK_EVENTS, CODEX_HOOK_EVENTS;
|
|
4412
|
+
var PRE_TOOL_MATCHER, HOOK_EVENTS, CODEX_HOOK_EVENTS, LEARN_COMMAND;
|
|
4390
4413
|
var init_init = __esm({
|
|
4391
4414
|
"src/init.ts"() {
|
|
4392
4415
|
"use strict";
|
|
@@ -4410,6 +4433,7 @@ var init_init = __esm({
|
|
|
4410
4433
|
{ event: "PreCompact", arg: "pre-compact", timeout: 10 },
|
|
4411
4434
|
{ event: "SessionEnd", arg: "session-end", timeout: 3 }
|
|
4412
4435
|
];
|
|
4436
|
+
LEARN_COMMAND = '---\ndescription: Capture what this session learned into the Bunshin library now (applied locally as a trial, submitted for the nightly review)\nargument-hint: "[what to capture, e.g. \\"the ledger must be reconciled before closing\\"]"\nallowed-tools: Bash(bunshin learn:*)\n---\n\nCapture knowledge from this session into Bunshin.\n\nRun exactly this with the Bash tool (it takes up to two minutes; use a timeout of 180000 ms):\n\n```bash\nbunshin learn "$ARGUMENTS"\n```\n\n`bunshin learn` forks this conversation (`claude -p --resume <this session> --fork-session`),\nso the reflection sees everything you saw without re-sending the transcript. It applies what it\nfinds locally as a trial and queues it for the nightly review:\n\n- edits to this repo\'s SPEC.md / TESTING.md / SKILL.md land in the working tree (they show up\n in `git diff`);\n- knowledge with no repo home becomes a local overlay on the Bunshin library;\n- per-machine values stay private.\n\nRelay its output to the user as it is. Each line reads\n`captured: <summary> \u2192 <section or file#anchor>`. If it prints `nothing new to capture.`, say so\nin one line; that is the normal outcome. If it reports an error, show it and stop; do not retry\nin a loop, and do not edit the library files by hand.\n\nIf the user named nothing specific, run it without arguments. Do not continue with other work in\nthe same reply unless the user asked you to.\n';
|
|
4413
4437
|
}
|
|
4414
4438
|
});
|
|
4415
4439
|
|
|
@@ -8440,6 +8464,10 @@ Key saved privately outside the project.
|
|
|
8440
8464
|
`);
|
|
8441
8465
|
if (result.hooks?.error) throw new Error(`Connected, but hooks could not be configured: ${result.hooks.error}. Fix the file and run setup again.`);
|
|
8442
8466
|
if (result.hooks) out(`${result.hooks.installed} ${harness === "pi" ? "extension" : "hooks"} configured in ${result.hooks.file}
|
|
8467
|
+
`);
|
|
8468
|
+
if (result.learnCommand?.installed) out(`/learn installed in ${result.learnCommand.file}
|
|
8469
|
+
`);
|
|
8470
|
+
else if (result.learnCommand?.error) out(`/learn not installed: ${result.learnCommand.error} (${result.learnCommand.file})
|
|
8443
8471
|
`);
|
|
8444
8472
|
if (result.hooks?.sharedWithWorktrees) out("Codex shares these hooks with the repository\u2019s linked worktrees. Each connected worktree keeps its own Bunshin store.\n");
|
|
8445
8473
|
if (harness === "codex" && result.hooks) out("Run codex interactively in this project. Review and accept project trust, then run /hooks and review and trust the five Bunshin hooks.\n");
|