diff --git a/docs/codebuddy-integration.md b/docs/codebuddy-integration.md index 7e87269..c58fb4d 100644 --- a/docs/codebuddy-integration.md +++ b/docs/codebuddy-integration.md @@ -123,11 +123,25 @@ expected: - `doctor codebuddy` reports `health: ok` - the hook entry in `~/.codebuddy/settings.json` has `matcher: "Bash"` and a command containing `codebuddy-pre-tool-use --wrap-launcher ...` +- if CodeBuddy was already running when tokenjuice wrote the settings file, restart CodeBuddy or open `/hooks` and confirm the external settings change before expecting the hook to appear or fire in that session. CodeBuddy snapshots hook settings at startup and does not hot-load externally edited hooks. - `uninstall codebuddy` removes tokenjuice-managed `PreToolUse` and legacy `PostToolUse` entries while preserving unrelated hooks - wrapped shell commands show nested normalized command/argv in trace - `--raw` keeps `ratio = 1` - non-raw wraps usually produce `ratio < 1` +## runtime reload behavior + +`tokenjuice install codebuddy` edits `~/.codebuddy/settings.json` from outside +CodeBuddy. CodeBuddy can read that file (`codebuddy config get hooks` shows the +installed `PreToolUse` entry), but an already-running session keeps the hook +snapshot it loaded at startup. This means `tokenjuice doctor codebuddy` can +report `health: ok` while the current CodeBuddy `/hooks` panel still does not +show the new tokenjuice entry. + +After installing from another terminal, start a new CodeBuddy session. If you +intentionally edit hooks while a session is open, use `/hooks` to review and +accept the external settings change before relying on it. + ## environment variables | variable | effect | diff --git a/docs/spec.md b/docs/spec.md index 57c34a5..a6e37d2 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -378,7 +378,7 @@ supported host hooks: | Codegen | `tokenjuice install codegen` | `AGENTS.md` | ✴️ Beta. Inserts a marker-delimited instruction block into the current git/project root that tells Codegen agents to use `tokenjuice wrap` for noisy terminal commands and `tokenjuice wrap --raw -- ` only when raw bytes are needed; guidance-only, because Codegen rule files do not intercept command output; see `docs/codegen-integration.md` | | Coder Agents | `tokenjuice install coder-agents` | `.agents/skills/tokenjuice/SKILL.md` | ✴️ Beta. Writes a Coder workspace skill with `name: tokenjuice` frontmatter that tells Coder Agents to use `tokenjuice wrap` for noisy terminal commands and `tokenjuice wrap --raw -- ` only when raw bytes are needed; guidance-only, because Coder Agents skills do not intercept command output; see `docs/coder-agents-integration.md` | | CodeRabbit | `tokenjuice install coderabbit` | `.coderabbit.yaml` | ✴️ Beta. Inserts marker-delimited `reviews.path_instructions` guidance that tells CodeRabbit review, finishing-touch, chat, and tool workflows to use `tokenjuice wrap` for noisy terminal commands and `tokenjuice wrap --raw -- ` only when raw bytes are needed; guidance-only, because CodeRabbit config does not intercept review comments or command output; see `docs/coderabbit-integration.md` | -| CodeBuddy (Linux/macOS/WSL) | `tokenjuice install codebuddy` | `~/.codebuddy/settings.json` | Uses `PreToolUse` shell input rewriting (same pattern as Cursor) to route Bash commands through `tokenjuice wrap`; preserves unrelated hooks that share a matcher group with the tokenjuice entry; `tokenjuice install codebuddy --local` is available for repo-local verification; native Windows shell interception is intentionally blocked for now; see `docs/codebuddy-integration.md` | +| CodeBuddy (Linux/macOS/WSL) | `tokenjuice install codebuddy` | `~/.codebuddy/settings.json` | Uses `PreToolUse` shell input rewriting (same pattern as Cursor) to route Bash commands through `tokenjuice wrap`; preserves unrelated hooks that share a matcher group with the tokenjuice entry; restart CodeBuddy after install, or use `/hooks` to confirm external settings changes in an already-running session; `tokenjuice install codebuddy --local` is available for repo-local verification; native Windows shell interception is intentionally blocked for now; see `docs/codebuddy-integration.md` | | Command Code | `tokenjuice install command-code` | `~/.commandcode/settings.json` / `.commandcode/settings.json` | ✴️ Beta. Uses a `PostToolUse` hook with matcher `shell`; compacted context is injected through `hookSpecificOutput.additionalContext` alongside the original shell output; `tokenjuice install command-code --local` is available for repo-local verification; see `docs/command-code-integration.md` | | Codex CLI | `tokenjuice install codex` | `~/.codex/hooks.json` | `tokenjuice install codex --local` is available for repo-local verification | | Continue | `tokenjuice install continue` | `.continue/rules/tokenjuice.md` | ✴️ Beta. Installs a workspace rule that tells Continue agents to use `tokenjuice wrap` for noisy terminal commands and `tokenjuice wrap --raw -- ` only when raw bytes are needed; guidance-only, because Continue rules do not intercept tool output; see `docs/continue-integration.md` | diff --git a/src/cli/main.ts b/src/cli/main.ts index d2ca6d2..fe16945 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -14,6 +14,7 @@ import { parseReduceJsonRequest } from "../core/json-protocol.js"; import { WRAP_AUTHORITATIVE_FOOTER } from "../core/compaction-metadata.js"; import { reduceExecution } from "../core/reduce.js"; import { verifyRules } from "../core/rules.js"; +import { UNKNOWN_ARTIFACT_SOURCE } from "../core/source.js"; import { runWrappedCommand } from "../core/wrap.js"; import type { WrapResult } from "../types.js"; import { doctorAdalInstructions, installAdalInstructions, uninstallAdalInstructions } from "../hosts/adal/index.js"; @@ -1451,12 +1452,19 @@ async function runInstall(args: ParsedArgs): Promise { return 0; } - process.stdout.write(`installed codebuddy hook: ${result.settingsPath}\n`); - process.stdout.write(`command: ${result.command}\n`); + const details = [ + { label: "Settings", value: result.settingsPath }, + { label: "Command", value: result.command }, + // CodeBuddy snapshots hook settings at session startup. When tokenjuice is + // installed from another terminal, a running CodeBuddy session will not + // show or execute the new hook until the user reloads that snapshot. + { label: "Reload", value: "restart CodeBuddy, or open /hooks and confirm the external settings change" }, + { label: "Verify", value: `tokenjuice doctor hooks${args.local ? " --local" : ""}` }, + ]; if (result.backupPath) { - process.stdout.write(`backup: ${result.backupPath}\n`); + details.push({ label: "Backup", value: result.backupPath }); } - process.stdout.write(`doctor: tokenjuice doctor hooks${args.local ? " --local" : ""}\n`); + process.stdout.write(formatInstallSuccess("codebuddy", "hook", details)); return 0; } @@ -7315,9 +7323,14 @@ async function runStats(args: ParsedArgs): Promise { if (report.sources && report.sources.length > 0) { process.stdout.write("sources:\n"); - for (const source of report.sources) { + const sourcesByObservedCost = [...report.sources].sort((left, right) => + right.totals.rawChars - left.totals.rawChars + || right.totals.savedChars - left.totals.savedChars + || left.source.localeCompare(right.source) + ); + for (const source of sourcesByObservedCost) { process.stdout.write( - `source ${source.source}: entries=${formatMetric(source.totals.entries)} saved=${formatMetric(source.totals.savedChars)} avgRatio=${formatRatio(source.totals.avgRatio)}\n`, + `source ${source.source}: entries=${formatMetric(source.totals.entries)} raw=${formatMetric(source.totals.rawChars)} reduced=${formatMetric(source.totals.reducedChars)} saved=${formatMetric(source.totals.savedChars)} avgRatio=${formatRatio(source.totals.avgRatio)}\n`, ); if (source.reducers.length > 0) { process.stdout.write( @@ -7330,6 +7343,9 @@ async function runStats(args: ParsedArgs): Promise { ); } } + if (sourcesByObservedCost.some((source) => source.source === UNKNOWN_ARTIFACT_SOURCE)) { + process.stdout.write("note: source unknown means stored artifacts have missing or invalid source metadata, usually from older tokenjuice versions.\n"); + } } return 0;