impulso
v0.29.1
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
When a legacy planner bootstrap task 0 is recovered during a plan amendment,
inspect it with impulso-hub status --json. The legacyTaskRecoveries array is
the audit history; human status reports its count. Automatic recovery is
intentionally narrow. If criteria are rejected or ambiguous, preserve
state.json, review task and dispatch provenance, and remediate the live entry
manually before retrying—never discard the archive.
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. - Artifact amendments: User-confirmed revisions use
impulso-hub amend start (--spec|--plan|--spec --plan) --approved-by <user|orchestrator> --reason <text>and finish withimpulso-hub amend finish; active amendments are exclusive, selected gates are revision-bound, and finish restores the affected workflow withoutadvance. See the canonical skills and regeneratedcommands/files. - Command discovery: Edit
skills/<name>/SKILL.md, then runnpm run sync:commands; generated command files must remain canonical-parity copies and are not edited by hand.
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