Context
Phase 1 (currently deployed) widens the OpenCode tool.execute.before hook so it pipes whitelisted package-manager commands through terraphim-agent replace, using the Terraphim Engineer role's KG. Verified mappings include:
npm install → bun add
npx create-react-app foo → bunx create-react-app foo
pip install requests → uv add requests
pip install -r requirements.txt → uv sync
python -m pip install fastapi → uv add fastapi
git commit -m "fix npm install bug" → git commit -m "fix bun add bug"
See docs/src/command-rewriting-howto.md for the full Phase 1 guide.
Phase 1 uses only the curated KG at ~/.config/terraphim/docs/src/kg/. Captured corrections under ~/Library/Application Support/terraphim/learnings/correction-*.md (written by terraphim-agent learn hook --learn-hook-type user-prompt-submit) are stored but not applied. This issue tracks closing that loop.
Phase 2 – Wire user-prompt-submit into agent hooks
Goal: every time the user types "use X instead of Y" / "prefer X over Y" / "use X not Y" / "switch to X" in a prompt, the existing process_user_prompt_submit parser records a CorrectionType::ToolPreference file.
Work:
- Document which agent events map to
user-prompt-submit for each adapter (Claude Code, OpenCode, Codex). OpenCode exposes something like experimental.chat.messages.transform – confirm the exact event name in @opencode-ai/plugin/dist/index.d.ts.
- Add the hook invocation in:
examples/claude-code-hooks/ (shell script variant).
- An OpenCode plugin that pipes
{ user_prompt } JSON into terraphim-agent learn hook --format opencode --learn-hook-type user-prompt-submit.
- Unit tests covering the three pattern variants plus negative cases (
"I prefer tea over coffee" should NOT be captured as a tool preference).
- Docs: append a Phase 2 section to
docs/src/command-rewriting-howto.md and content/docs/command-rewriting-howto.md on the terraphim.ai Zola site.
Acceptance: uttering "use uv instead of pip" in a fresh session creates one file under .terraphim/learnings/correction-*.md or the global equivalent.
Phase 3 – Compile captured corrections into a thesaurus
Goal: captured ToolPreference corrections are turned into live replace rules without manual KG authoring.
Work in crates/terraphim_agent/src/learnings/capture.rs:
/// Compile stored corrections of given types into a Thesaurus usable by `replace`.
pub fn compile_corrections_to_thesaurus(
storage_dir: &Path,
correction_types: &[CorrectionType],
) -> Result<Thesaurus, LearningError>
/// Export as Logseq-style KG markdown (one file per corrected term) for review / version control.
pub fn export_corrections_as_kg(
storage_dir: &Path,
correction_type: CorrectionType,
output_dir: &Path,
) -> Result<usize, LearningError>
CLI subcommands in crates/terraphim_agent/src/main.rs:
terraphim-agent learn compile-thesaurus \
--type tool-preference \
--output ~/.config/terraphim/kg/compiled/corrections.json
terraphim-agent learn export-kg \
--type tool-preference \
--output ~/.config/terraphim/kg/commands/
Extend replace (or add a new --extra-thesaurus <file> flag) so hooks can merge compiled corrections over the role's KG thesaurus. Merge semantics: compiled corrections override the base KG (learnt preferences win).
Invalidation: the SQLite thesaurus cache at /tmp/terraphim_sqlite/terraphim.db (keyed thesaurus_<role>.json) must be invalidated when corrections change. Options: (a) touch the mtime of the KG directory; (b) include the corrections-dir mtime in the cache key; (c) ship a terraphim-agent cache invalidate --role <role> command.
Acceptance:
terraphim-agent learn capture-correction --original "pip install" --corrected "uv add" --correction-type tool-preference creates a file.
terraphim-agent learn compile-thesaurus --type tool-preference produces a JSON with the mapping.
terraphim-agent replace "pip install requests" --extra-thesaurus <compiled.json> returns uv add requests even if the base KG doesn't have that mapping.
- Integration test runs through steps 1-3 with
#[tokio::test] in crates/terraphim_agent/tests/.
Phase 3.5 – OpenCode plugin extension (optional polish)
Modify terraphim-hooks.js (and the reference script in examples/claude-code-hooks/) to:
- Detect when a new
correction-*.md is written (mtime check on the learnings dir).
- Automatically run
terraphim-agent learn compile-thesaurus and pass --extra-thesaurus to the next replace invocation.
This closes the feedback loop: user says "use uv instead of pip" once → captured → compiled → applied on the next bash call.
Non-goals for this issue
- Expanding the rewriteable-head whitelist beyond package managers. That is a separate conversation about risk (shell syntax is easy to corrupt).
- Multi-user/shared corrections with trust levels (the existing
shared_learning module is out of scope here; see CLAUDE.md for that roadmap).
Reference files
docs/src/command-rewriting-howto.md (this repo) – Phase 1 how-to, now on docs.terraphim.ai after next publish.
~/projects/personal/private_agents_settings/opencode/plugin/terraphim-hooks.js – current Phase 1 hook implementation (pushed to AlexMikhalev/private_agents_settings).
crates/terraphim_agent/src/learnings/hook.rs – process_user_prompt_submit, LearnHookType::UserPromptSubmit.
crates/terraphim_agent/src/learnings/capture.rs – CorrectionEvent, capture_correction.
crates/terraphim_automata/src/builder.rs – Logseq thesaurus builder.
crates/terraphim_automata/src/matcher.rs – Aho-Corasick replace_matches, MIN_PATTERN_LENGTH = 2.
Context
Phase 1 (currently deployed) widens the OpenCode
tool.execute.beforehook so it pipes whitelisted package-manager commands throughterraphim-agent replace, using theTerraphim Engineerrole's KG. Verified mappings include:npm install→bun addnpx create-react-app foo→bunx create-react-app foopip install requests→uv add requestspip install -r requirements.txt→uv syncpython -m pip install fastapi→uv add fastapigit commit -m "fix npm install bug"→git commit -m "fix bun add bug"See
docs/src/command-rewriting-howto.mdfor the full Phase 1 guide.Phase 1 uses only the curated KG at
~/.config/terraphim/docs/src/kg/. Captured corrections under~/Library/Application Support/terraphim/learnings/correction-*.md(written byterraphim-agent learn hook --learn-hook-type user-prompt-submit) are stored but not applied. This issue tracks closing that loop.Phase 2 – Wire
user-prompt-submitinto agent hooksGoal: every time the user types "use X instead of Y" / "prefer X over Y" / "use X not Y" / "switch to X" in a prompt, the existing
process_user_prompt_submitparser records aCorrectionType::ToolPreferencefile.Work:
user-prompt-submitfor each adapter (Claude Code, OpenCode, Codex). OpenCode exposes something likeexperimental.chat.messages.transform– confirm the exact event name in@opencode-ai/plugin/dist/index.d.ts.examples/claude-code-hooks/(shell script variant).{ user_prompt }JSON intoterraphim-agent learn hook --format opencode --learn-hook-type user-prompt-submit."I prefer tea over coffee"should NOT be captured as a tool preference).docs/src/command-rewriting-howto.mdandcontent/docs/command-rewriting-howto.mdon the terraphim.ai Zola site.Acceptance: uttering "use uv instead of pip" in a fresh session creates one file under
.terraphim/learnings/correction-*.mdor the global equivalent.Phase 3 – Compile captured corrections into a thesaurus
Goal: captured
ToolPreferencecorrections are turned into livereplacerules without manual KG authoring.Work in
crates/terraphim_agent/src/learnings/capture.rs:CLI subcommands in
crates/terraphim_agent/src/main.rs:Extend
replace(or add a new--extra-thesaurus <file>flag) so hooks can merge compiled corrections over the role's KG thesaurus. Merge semantics: compiled corrections override the base KG (learnt preferences win).Invalidation: the SQLite thesaurus cache at
/tmp/terraphim_sqlite/terraphim.db(keyedthesaurus_<role>.json) must be invalidated when corrections change. Options: (a) touch the mtime of the KG directory; (b) include the corrections-dir mtime in the cache key; (c) ship aterraphim-agent cache invalidate --role <role>command.Acceptance:
terraphim-agent learn capture-correction --original "pip install" --corrected "uv add" --correction-type tool-preferencecreates a file.terraphim-agent learn compile-thesaurus --type tool-preferenceproduces a JSON with the mapping.terraphim-agent replace "pip install requests" --extra-thesaurus <compiled.json>returnsuv add requestseven if the base KG doesn't have that mapping.#[tokio::test]incrates/terraphim_agent/tests/.Phase 3.5 – OpenCode plugin extension (optional polish)
Modify
terraphim-hooks.js(and the reference script inexamples/claude-code-hooks/) to:correction-*.mdis written (mtime check on the learnings dir).terraphim-agent learn compile-thesaurusand pass--extra-thesaurusto the nextreplaceinvocation.This closes the feedback loop: user says "use uv instead of pip" once → captured → compiled → applied on the next bash call.
Non-goals for this issue
shared_learningmodule is out of scope here; seeCLAUDE.mdfor that roadmap).Reference files
docs/src/command-rewriting-howto.md(this repo) – Phase 1 how-to, now on docs.terraphim.ai after next publish.~/projects/personal/private_agents_settings/opencode/plugin/terraphim-hooks.js– current Phase 1 hook implementation (pushed toAlexMikhalev/private_agents_settings).crates/terraphim_agent/src/learnings/hook.rs–process_user_prompt_submit,LearnHookType::UserPromptSubmit.crates/terraphim_agent/src/learnings/capture.rs–CorrectionEvent,capture_correction.crates/terraphim_automata/src/builder.rs– Logseq thesaurus builder.crates/terraphim_automata/src/matcher.rs– Aho-Corasickreplace_matches,MIN_PATTERN_LENGTH = 2.