impulso
v0.28.17
Published
Impulso — plugin bundle for opencode and Claude Code: Plannotator skills + Impulso-DirectSpeech (rethemed ex-Caveman). Harness-neutral repo; per-harness glue under harnesses/.
Maintainers
Readme
Impulso
Plugin bundle for opencode + Claude Code: Plannotator (vendored skills) + Impulso-DirectSpeech (terse communication mode).
Harness-neutral repo. Per-harness glue under harnesses/.
Contents
| Piece | What |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Plannotator | 3 vendored skills (annotate/last/review) + 3 commands. Skills invoke the plannotator CLI binary directly (user-installed); no npm plugin. |
| Impulso-DirectSpeech | Terse communication mode — always active, enforced by the harness. Ruleset in shared/AGENTS.md + per-turn reinforcement hook on each harness. No toggle. 3 auxiliary skills (compress/stats/help). |
Install routes
Four ways in — pick one per profile (combining the Claude plugin with the Claude installer duplicates hooks). The plugin route is the recommended default for both harnesses.
| Route | Harness | You get |
| --------------------------------------------------------- | -------- | -------------------------------------------------------------------- |
| Claude Code plugin (marketplace, recommended) | claude | hooks + skills + commands + tokensave MCP, versioned, auto-updatable |
| harnesses/claude/install.sh | claude | same + ruleset wired into CLAUDE.md; merge-safe into ~/.claude |
| Self-boot (run_here_claude.sh) | claude | everything, isolated to this repo — dev/testing |
| opencode plugin (recommended) / installer / self-boot | opencode | plugin composes everything; see below |
Install — Claude Code plugin (marketplace, recommended)
Inside any claude session:
/plugin marketplace add alexandrekm/Impulso
/plugin install impulso@impulsoLoads the hooks (preflight, DirectSpeech reinforcement — via
${CLAUDE_PLUGIN_ROOT}), all skills/commands, and the tokensave MCP server.
Update later with /plugin marketplace update impulso.
Not covered by the plugin (Claude Code plugins can't ship memory files): the
full ruleset in shared/AGENTS.md. DirectSpeech still enforces per turn via the
hook; for the complete ruleset add an import line to your ~/.claude/CLAUDE.md
pointing at a checked-out copy, or use the installer route instead.
Requires tokensave on PATH — the preflight hook blocks prompts otherwise
(that's the point).
Install — opencode plugin (recommended)
Install versioned package from npm:
npm install impulso@latestPinned package version:
npm install [email protected]Or add one entry to your opencode config:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["impulso@git+https://github.com/alexandrekm/Impulso.git"],
}Restart opencode (clear cache first):
rm -rf ~/.cache/opencode/node_modules/impulso
pkill -f opencode
opencodeThe single plugin entry internally composes DirectSpeech + bundled skills and
commands. Plannotator skills invoke the user-installed plannotator binary
directly — no npm plugin dependency.
Update
opencode caches git+https plugins locally and won't refetch on its own. Pull the latest revision with the same clear-cache-and-restart steps shown above:
rm -rf ~/.cache/opencode/node_modules/impulso
pkill -f opencode
opencodeIf pinned to a tag or commit, bump it in your config first, then run the same cache-clear + restart.
Pin a version
"plugin": ["impulso@git+https://github.com/alexandrekm/Impulso.git#v0.1.0"]Install from a local clone
"plugin": ["impulso@git+file:///abs/path/to/hip-liger"]The file:// URL must be an absolute path with three slashes
(file:///abs/...) and the directory must be a git repo (have .git/).
Quick start — target repo directly (no install)
Point XDG_CONFIG_HOME at the repo root:
cd /path/to/impulso
XDG_CONFIG_HOME=$(pwd) opencodeOr use the convenience wrapper:
./run_here.shPrerequisite: the
plannotatorbinary must be on yourPATHfor the Plannotator skills to launch the annotation UI. Install it separately (not bundled with this repo).
Quick start — Claude Code
Point CLAUDE_CONFIG_DIR at the repo's bundled claude/ config dir — no
install step, no separate profile dir. Skills and commands resolve via symlinks
inside claude/; hooks resolve via $CLAUDE_CONFIG_DIR shell expansion in
settings.json:
cd /path/to/impulso
CLAUDE_CONFIG_DIR=$(pwd)/claude claudeOr use the convenience wrapper:
./run_here_claude.shFor a permanent isolated install that leaves your main ~/.claude/ untouched:
./harnesses/claude/install.sh
CLAUDE_CONFIG_DIR=~/.config/impulso-profile/claude claudeTo install into ~/.claude/ directly (shared with your normal Claude Code
config): IMPULSO_CLAUDE_PROFILE="$HOME/.claude" ./harnesses/claude/install.sh
See harnesses/claude/README.md for Plannotator
upstream plugin setup.
Install — isolated profiles
For permanent installs that leave your main config dirs untouched:
./harnesses/opencode/install.sh
XDG_CONFIG_HOME=~/.config/impulso-profile opencode
./harnesses/claude/install.sh
CLAUDE_CONFIG_DIR=~/.config/impulso-profile/claude claudeThe tokensave MCP server additionally needs a per-project index — run
tokensave init once in each repo you work in (.tokensave/ is gitignored
globally by the installer).
Usage — everything in one place
Daily use
DirectSpeech is always on — nothing to activate, no off-switch. tokensave MCP
tools are available once tokensave init has been run in the project.
| Slash command | What it does |
| ---------------------------------------- | --------------------------------------------------- |
| /plannotator-annotate <file\|url\|dir> | browser annotation UI, feedback returned to session |
| /plannotator-last | annotate the latest assistant message |
| /plannotator-review [PR URL] | browser code review of worktree or PR |
| /impulso-directspeech-compress <file> | compress a .md file to terse prose (~46% tokens) |
| /impulso-directspeech-stats | token-savings stats |
| /impulso-directspeech-help | reference card |
Plannotator commands need the plannotator binary:
curl -fsSL https://plannotator.ai/install.sh | bash
Per-project setup
tokensave init # build the tokensave index (once per repo)Maintenance
impulso-hub doctor # health check: binaries, symlinks, configs, MCP
./harnesses/claude/uninstall.sh # reverse the claude install (targeted, safe)
./harnesses/opencode/uninstall.sh # remove the opencode profileDevelopment (this repo)
npm test # all unit suites
npm run lint && npm run format:check
npm run sync:commands # regen commands/ after editing skills/
./harnesses/opencode/integration-tests.sh # live boot tests; model resolved via
# IMPULSO_TEST_MODEL > bedrock auth > CLI_PROXY_URL
claude plugin validate . # check plugin/marketplace manifestsEditing rules: skills are the source — never edit commands/ by hand (CI drift
check will fail); the ruleset lives only in shared/AGENTS.md (claude/ and
opencode/ symlink it); claude hooks live in harnesses/claude/hooks/ and are
referenced from both claude/settings.json (self-boot/installer) and
hooks/hooks.json (plugin).
Agent orchestration
See docs/DETAILS.md for a full pipeline visual reference.
Multi-agent pipeline (orchestrator → specialist agents) on both harnesses, from
a single source of truth in shared/orchestration-config.cjs.
Roster
| Agent | Role | CC default | opencode default |
| -------------------- | ------------------------------------------------ | -------------- | -------------------------- |
| ImpulsoOrchestrator | Routes tasks to specialist agents; no file edits | session (null) | session (null) |
| scout | Read-only recon; returns path:line refs | haiku | llm/scout |
| planner | Drafts spec.md / plan.md | opus | llm/planner |
| implementer | Code, tests, refactors | sonnet | llm/implementer |
| implementer-frontend | UI, CSS, component trees | sonnet | llm/implementer-frontend |
| implementer-infra | Terraform, K8s, CI/CD | sonnet | llm/implementer-infra |
| reviewer | Code review (task-level and branch-level) | opus | llm/reviewer |
| debugger | Root-cause analysis, regression test, fix | sonnet | llm/debugger |
| shipper | Commits, push, PR | haiku | llm/shipper |
| generalist | Catch-all; prefer specialists when type is known | sonnet | llm/generalist |
Pipeline
Key orchestration behaviors:
- Route self-check: Estimate blast radius before committing to a route.
Prefer
smallfor config-only / ≤~3-file / unambiguous changes; propose a downgrade when the route feels heavier than the diff. - Brainstorm: Batch all independent questions in one round (sequential only for dependent decisions). Any post-plan design change restarts the brainstorm cycle — no mid-pipeline pivots.
- Spec: Confirmed in chat with the user — no Plannotator gate at this phase. Plannotator gates remain at Plan and the final branch/code review.
- Parallel dispatch: Plan tasks carry a
parallel-safe: yes|nofield. The orchestrator fans outparallel-safe: yestasks concurrently (edit-only implementers; orchestrator owns gate state + commits);parallel-safe: notasks run sequentially.
Override — .impulso/models.json
Ladder (highest wins): <repo>/.impulso/models.json >
~/.impulso/models.json > shipped defaults.
The file is harness-partitioned: top-level keys must be claude and/or
opencode. Flat keys (e.g. "planner": "opus") are rejected with a
migration-hint error. A file may carry only one block; the absent block
contributes no overrides.
Each block maps an agent key (roster name) to a model string or
{ "model", "effort" } object; fields merge per-key down the ladder, so an
effort-only override keeps the lower-rung model. Unknown keys or bad JSON = hard
fail, no silent fallback.
{
"claude": { "planner": "opus", "reviewer": "opus" },
"opencode": { "planner": "llm/deep", "implementer": { "effort": "xhigh" } }
}opencode values are pass-through strings — either a logical alias
(llm/deep) or a concrete provider model. Impulso does not resolve or validate
them; they replace the shipped llm/<key> default verbatim.
effort inside a claude block is a hard error — Claude Code effort comes
from agents/<name>.md frontmatter, not models.json. Place effort overrides
in the opencode block only.
opencode aliases (BYO-config required)
opencode ships logical aliases, not concrete model IDs. Every agent in the
opencode block resolves through an llm/<key> alias that must be mapped in
your opencode provider config — Impulso provides no fallback. An undefined alias
fails at dispatch. impulso-hub doctor warns when aliases are active (spec §7).
| Agent | Shipped alias |
| -------------------- | -------------------------- |
| scout | llm/scout |
| scout-writer | llm/scout-writer |
| planner | llm/planner |
| implementer | llm/implementer |
| implementer-frontend | llm/implementer-frontend |
| implementer-infra | llm/implementer-infra |
| reviewer | llm/reviewer |
| debugger | llm/debugger |
| shipper | llm/shipper |
| generalist | llm/generalist |
To wire up aliases, define each llm/<key> entry in your opencode provider
config (exact syntax depends on your provider plugin). Alternatively, override
the opencode block in .impulso/models.json with concrete model IDs — that
bypasses the alias layer entirely.
Inspection
impulso-hub models # full resolved map (claude, default)
impulso-hub models --agent reviewer # single agent
impulso-hub models --harness opencode # opencode alias mapTelematics
Enabled Impulso telemetry writes grouped session logs under
~/.impulso/logs/sessions/<session-id>/. Each session directory contains a
manifest.json with lifecycle metadata, Git context, and child process records,
plus per-PID events.ndjson files. All storage is read-only to the CLI — no
mutation, migration, or legacy-log impact.
# list all sessions (human rows)
impulso-hub telematics sessions
# list all sessions (single JSON document)
impulso-hub telematics sessions --json
# inspect one session in detail
impulso-hub telematics show <correlation-id>
# inspect one session as JSON
impulso-hub telematics show <correlation-id> --jsonCaveats
Model strings are not validated at config load — a typo surfaces at dispatch
when the provider rejects the ID. Aliases (sonnet/haiku/opus) on the CC
side track the harness's default for that tier; pin full model IDs to lock a
specific version.
Migration (flat models.json): Existing files with flat top-level keys
(e.g. { "planner": "opus" }) now fail at boot with a migration-hint error.
Wrap the content under "claude" and/or "opencode" blocks. Move any effort
values into the opencode block, or into agents/<name>.md frontmatter for
Claude Code effort.
opencode default behavior change: opencode no longer defaults to concrete
models; it defaults to llm/<key> aliases (see table above). Users who did not
previously override models must either define the llm/* aliases in their
opencode provider config or pin concrete models in the opencode block of
models.json. There is no fallback — undefined aliases fail at dispatch.
Harness differences
Effort behaves differently per harness:
- opencode:
effortis registered at boot asreasoningEfforton the agent config — a provider-passthrough value. Themodels.jsonladder applies. Interpretation is provider-specific. - Claude Code: the Agent tool has no dispatch-time effort parameter, so the
models.jsoneffort ladder does not apply — specifyingeffortin theclaudeblock ofmodels.jsonis a hard error (useagents/<name>.mdfrontmatter instead). Effort is a staticeffort:frontmatter key inagents/*.md(validated bysync:agents; unset = inherit session).
Model dispatch:
- opencode: models are pinned at boot in
config.agent[name].model. Boot values are thellm/<key>aliases by default (see alias table). - Claude Code: orchestrator pins the resolved model on every dispatch via
the Agent tool
modelparameter.
Use impulso-hub models --harness claude|opencode (default claude) to inspect
the full resolved map for either harness.
Model ID format and [1m] context-suffix: no difference. Neither harness
transforms or validates model IDs; no [1m] suffix support exists in either.
Deterministic orchestration ownership
Deterministic state and precondition validation
(impulso-hub status --json schema v1) are owned by impulso-hub. Specialized
skills retain human interview, dispatch, and remediation policy.
Structure
impulso/
├── AGENTS.md # contributor guide for AI agents working on this repo
├── CLAUDE.md # @AGENTS.md import (Claude Code reads CLAUDE.md)
├── .claude-plugin/ # plugin.json + marketplace.json (claude plugin route)
├── hooks/hooks.json # plugin hook declarations (${CLAUDE_PLUGIN_ROOT})
├── .mcp.json # tokensave MCP (plugin route + project-local)
├── run_here.sh # boots opencode against this repo
├── run_here_claude.sh # boots Claude Code against this repo
├── opencode/ # self-boot config: opencode.jsonc + AGENTS.md -> shared/ + symlinks
├── claude/ # self-boot config: settings.json + CLAUDE.md + AGENTS.md -> shared/ + symlinks
├── skills/ # harness-agnostic skill files (SKILL.md per dir)
├── commands/ # auto-generated from skills/ (sync-commands.js)
├── shared/ # harness-neutral: AGENTS.md (canonical ruleset), directspeech-config.cjs, tests.cjs
└── harnesses/
├── opencode/ # opencode-specific glue
│ ├── plugin.js # orchestrator (composes DirectSpeech + bundled skills/commands)
│ ├── compose.js # hook merging helper
│ ├── frontmatter.js # shared YAML frontmatter parser
│ ├── commands-loader.js # runtime command registration
│ ├── sync-commands.js # build-time cmd generation from skills
│ ├── install.sh # isolated profile installer
│ ├── uninstall.sh # removes the isolated profile
│ ├── directspeech/ # DirectSpeech plugin (always-on reinforcement)
└── claude/ # Claude Code glue
├── install.sh # profile installer (merge-safe for shared profiles)
├── uninstall.sh # targeted reversal — never touches foreign content
├── merge-settings.cjs # settings.json merge (foreign hooks/keys survive)
├── tests.cjs
└── hooks/ # preflight.cjs, directspeech-context.cjs