plugin-maintenance
GitHub指导修改Chorus插件(涵盖Claude Code、Codex等六个平台)、更新技能文档及发布新版本。包含文件结构说明、多平台同步机制及版本发布流程。
Trigger Scenarios
Install
npx skills add Chorus-AIDLC/Chorus --skill plugin-maintenance -g -y
SKILL.md
Frontmatter
{
"name": "plugin-maintenance",
"license": "AGPL-3.0",
"metadata": {
"author": "chorus",
"version": "0.5.0",
"category": "development"
},
"description": "Guide for modifying the Chorus plugin (Claude Code, Codex, OpenClaw, Kiro, Pi, and dsh ports), updating skill documentation, and releasing new plugin versions."
}
Chorus Plugin & Skill Maintenance
How to modify the Chorus plugin, update skill documentation, and release new versions. Six plugin packages are maintained in parallel — Claude Code, Codex, OpenClaw, Kiro, Pi, and dsh (DeepSeek Harness) — plus the standalone skill surface. That is seven skill surfaces total; when you change skill content, sweep all seven (see Skill Content Changes — Seven Surfaces).
File Structure
.claude-plugin/
marketplace.json ← Claude Code marketplace registry (version here)
public/chorus-plugin/ ← Claude Code plugin package
.claude-plugin/
plugin.json ← Plugin metadata (version here)
hooks.json ← Hook definitions (SubagentStart, etc.)
bin/ ← Hook scripts (bash) — stateful via API state-get/set
skills/
chorus/SKILL.md ← Core skill
develop/ idea/ proposal/ quick-dev/ review/ yolo/SKILL.md
agents/ ← Reviewer agents as .md (Claude Code style)
proposal-reviewer.md
task-reviewer.md
plugins/chorus/ ← Codex plugin package (separate from Claude Code)
.codex-plugin/
plugin.json ← Plugin metadata (version here)
hooks.json
hooks/ ← Hook scripts (bash) — intentionally stateless
on-session-start.sh
on-post-submit-proposal.sh
on-post-submit-for-verify.sh
chorus-mcp-call.sh ← MCP helper (has hardcoded clientInfo version)
hook-output.sh
skills/
chorus/SKILL.md ← Codex port — mentions $skill syntax, ~/.codex/config.toml
develop/ idea/ proposal/ quick-dev/ review/ yolo/SKILL.md
chorus-proposal-reviewer/SKILL.md ← Reviewers as skills in Codex (no agents/)
chorus-task-reviewer/SKILL.md
packages/openclaw-plugin/ ← OpenClaw plugin package (TS runtime + skills)
openclaw.plugin.json ← Plugin manifest (id, skills dir, activation, configSchema) — NO version field
package.json ← npm package (version here; `openclaw` block: extensions, runtimeExtensions, install/compat)
src/ ← TypeScript runtime (index.ts, mcp-client.ts, sse-listener.ts, event-router.ts, wake.ts)
— real-time SSE event bridge + MCP registration; NOT bash hooks
dist/ ← Compiled JS (npm install loads this; linked install loads src/ via jiti)
skills/
chorus/SKILL.md ← OpenClaw port — tools namespaced `chorus__<tool>`, inline OpenSpec detection
develop/ idea/ proposal/ quick-dev/ review/ yolo/ brainstorm/ openspec-aware/SKILL.md
proposal-reviewer/SKILL.md ← Reviewers as skills (like Codex, no agents/)
task-reviewer/SKILL.md
public/kiro-plugin/ ← Kiro CLI plugin (loose .kiro/ template tree + install script)
.kiro/
settings/mcp.json ← Chorus remote MCP server (${env:CHORUS_API_KEY} bearer, disabled:false)
skills/chorus-*/SKILL.md ← 8 chorus-PREFIXED skills (no bare names — global-install distinctiveness)
agents/chorus.json ← main agent (.json — Kiro CLI, NOT .md); hosts all hooks via __CHORUS_BIN__ placeholder
agents/chorus.md ← main-agent system-prompt sidecar (file://./chorus.md)
agents/chorus-*-reviewer.json ← 3 read-only reviewer subagents (tools:["read","@chorus"])
steering/chorus.md ← platform overview + AI-DLC context (folds in the `chorus` overview skill)
bin/ ← Hook scripts (bash, 3.2-safe) + chorus-api.sh + test-syntax.sh
installer copies these into <KIRO_DIR>/chorus-bin/ and resolves __CHORUS_BIN__
(public/install-kiro.sh) ← one-shot curl|bash installer → merges .kiro/ into ~/.kiro/ (or <cwd>/.kiro/ with --workspace)
packages/chorus-pi/ ← Pi coding agent package (TS extension + skills)
package.json ← npm package + Pi manifest (version here)
extensions/chorus.ts ← Native Pi event handlers; auto checkin/session lifecycle/reviewer nudges
lib/lib.ts ← Pure helpers used by the extension and unit tests
bin/chorus-mcp-call.sh ← MCP helper for byte-exact OpenSpec document mirroring
skills/
chorus/SKILL.md ← Core skill; Pi `/skill:<name>` syntax
develop/ idea/ proposal/ quick-dev/ review/ yolo/ openspec-aware/SKILL.md
agents/ ← 3 read-only reviewer agents copied to ~/.pi/agent/agents/
test/ ← Static, helper-unit, extension-event, and manual-session verification
packages/chorus-dsh/ ← DeepSeek Harness (dsh) plugin — published npm bundle @chorus-aidlc/chorus-dsh
package.json ← npm package + dsh bundle patch (version here; tracks the APP version, e.g. 0.16.3)
src/index.ts ← Cordis plugin apply(): injects skills/persona/MCP wrapper; daemon-backend gate
cordis.patch.yml ← dsh composition patch shipped in the bundle
bin/chorus-mcp-call.mjs ← Node MCP-over-HTTP helper (clientInfo.version auto-read from package.json — no manual bump)
skills/
chorus/SKILL.md ← Core overview (dsh HAS a chorus/ overview, unlike Kiro)
<stage>-chorus/SKILL.md ← 13 stage/reviewer skills, `-chorus` SUFFIX (brainstorm/develop/idea/
proposal/quick-dev/review/yolo/docs/orchestrate/openspec-aware/
code-reviewer/proposal-reviewer/task-reviewer)
public/skill/ ← Standalone skill (any MCP-compatible agent)
chorus/SKILL.md ← Same structure, softer language, IDE-agnostic
proposal-chorus/SKILL.md
quick-dev-chorus/SKILL.md
Plugin key differences
| Aspect | Claude Code | Codex | OpenClaw | Kiro CLI | Pi |
|---|---|---|---|---|---|
| Skill invocation | /chorus:develop |
$develop |
/develop |
/chorus-develop |
/skill:develop |
| Tool names | chorus_<tool> |
chorus_<tool> |
chorus__<tool> |
chorus_<tool> / @chorus matcher |
MCP gateway may expose chorus_chorus_<tool>; extension uses native chorus_<tool> |
| MCP config | .mcp.json |
~/.codex/config.toml |
Plugin config | ~/.kiro/settings/mcp.json |
.mcp.json or ~/.pi/agent/mcp.json via pi-mcp-adapter |
| Session lifecycle | SubagentStart/Stop hooks | Manual/stateless | Manual | agentSpawn/stop hooks |
Automatic via mutable subagent_spawn and subagent_manage events |
| Reviewers | agents/*.md via Task |
Skills mounted in spawn_agent |
Reviewer skills via sessions_spawn |
Native JSON subagents | agents/chorus-*-reviewer.md via pi-subagents |
| User interaction | AskUserQuestion |
Plain text | Plain text | Plain text | Plain text |
| OpenSpec detection | SessionStart hook | SessionStart hook | Inline | agentSpawn hook |
session_start extension event |
| Runtime/hooks | Stateful bash hooks | Stateless bash hooks | TypeScript SSE runtime | Bash 3.2 hooks in chorus.json |
TypeScript native extension; shell only for OpenSpec mirroring |
| Task execution | Agent Teams waves | spawn_agent |
Main-agent waves | Kiro subagents | subagent_spawn workers |
| Install | Marketplace | install-codex.sh |
OpenClaw plugin manager | install-kiro.sh |
GitHub checkout + pi install <checkout>/packages/chorus-pi |
When porting a change between plugins, preserve these intentional differences. Don't add state files to the Codex/OpenClaw plugins, don't use $-prefix outside Codex, keep OpenClaw's chorus__ names and manual-session/inline-detection wording, and preserve Kiro's chorus- skill prefix, @chorus/<tool> matchers, and __CHORUS_BIN__ placeholder. For Pi, use /skill:<name>, subagent_spawn, native extension events, and plain-text interaction; do not introduce Claude hooks or Codex session wording.
dsh (DeepSeek Harness) is a published npm bundle (@chorus-aidlc/chorus-dsh) added to a dsh profile via dsh plugin --profile <name> add -w. It is Cordis-based: src/index.ts's apply() injects the -chorus-suffixed skills, persona, and a Node MCP wrapper. Skills use the -chorus suffix (like standalone) but it keeps a chorus/SKILL.md overview. Its version tracks the app version (0.16.3+), NOT the 0.9.x skill sequence. The dsh daemon backend (cli/dsh-spawner.mjs / dsh-managed-config.mjs) is currently de-listed / offline — kept dormant, not advertised; do NOT re-add it to the daemon install menu, CLI --agent help, or DAEMON.md / MCP_TOOLS.md without bringing the backend back online.
When to Update What
"All six plugin skills" = Claude Code + Codex + OpenClaw + Kiro + Pi + dsh. "All seven surfaces" additionally includes standalone public/skill/. Note the Kiro surface has no chorus/SKILL.md — its overview lives in steering/chorus.md, and its stage skills are chorus-prefixed; dsh keeps a chorus/SKILL.md overview and uses -chorus-suffixed stage skills.
| Change | Files to update |
|---|---|
| New MCP tool added | src/mcp/tools/*.ts + docs/MCP_TOOLS.md + all six plugin overviews (Kiro: steering/chorus.md) + standalone overview |
| MCP tool description changed | src/mcp/tools/*.ts only (skill docs reference tool names, not descriptions) |
| Skill content / wording (e.g. AC now required) | The matching stage skill in all seven surfaces |
| New workflow step | All six plugin stage skills + standalone equivalent |
| New Idea/Task status | All six plugin overviews + standalone overview + locale messages |
| New execution rule | All six plugin overviews + standalone overview (softer wording) |
| Permission model change | All six plugin overviews + affected stage skills + runtime checks where applicable |
| Hook script change (Claude Code) | public/chorus-plugin/bin/*.sh + hooks.json if new hook. Never copy hook changes blindly into plugins/chorus/hooks/ — Codex hooks are intentionally stateless and lack subagent events. OpenClaw has no bash hooks at all. |
| Hook script change (Codex) | plugins/chorus/hooks/*.sh — rarely needed; session-start, post-submit-proposal, post-submit-for-verify are the only three. If bumping plugin version, also update the hardcoded clientInfo.version in chorus-mcp-call.sh. |
| OpenClaw runtime change | packages/openclaw-plugin/src/*.ts (TS SSE/MCP runtime) + npm run typecheck + npm run test. Not bash hooks — this is a compiled TypeScript extension. |
| Pi runtime change | packages/chorus-pi/extensions/*.ts + lib/*.ts; run bash test/all.sh from the package directory |
| Any plugin change | Bump version in every file for that package (see Version Bump Checklist) |
Version Bump Checklist
Every time any plugin package changes, bump the version in all of that package's locations. There are two version sequences in play:
- Skill-frontmatter sequence — shared by corresponding
SKILL.mdfiles across the six plugin ports. When the same skill content ships to multiple plugins, bump them together. - Per-package plugin sequences — Claude Code + Codex share one (
marketplace.json/ bothplugin.json, currently0.9.x); OpenClaw'spackage.jsonhas its own sequence (currently0.5.x). These are independent files — edit each.
Claude Code plugin — bump together
.claude-plugin/marketplace.json—"version": "X.Y.Z"public/chorus-plugin/.claude-plugin/plugin.json—"version": "X.Y.Z"- Every skill under
public/chorus-plugin/skills/*/SKILL.md—metadata.version: "X.Y.Z"(all skills, includingquick-dev/, now use the standard nestedmetadata:block)
Codex plugin — bump together
plugins/chorus/.codex-plugin/plugin.json—"version": "X.Y.Z"- Every skill under
plugins/chorus/skills/*/SKILL.md—metadata.version: "X.Y.Z"(all skills, includingquick-dev/, now use the standard nestedmetadata:block). Don't forget the two reviewer skills:chorus-proposal-reviewer/SKILL.mdandchorus-task-reviewer/SKILL.md. plugins/chorus/hooks/chorus-mcp-call.sh— hardcodedclientInfo.versionstring in the JSON-RPCinitializepayload
OpenClaw plugin — bump together
packages/openclaw-plugin/package.json—"version": "X.Y.Z"using OpenClaw's own sequence (0.5.x), NOT the skill sequence.openclaw.plugin.jsonhas no version field — nothing to edit there.- Every skill under
packages/openclaw-plugin/skills/*/SKILL.md—metadata.version: "X.Y.Z"on the skill sequence (0.9.x, matching the other plugins' skills). Includes the two reviewer skillsproposal-reviewer/SKILL.mdandtask-reviewer/SKILL.md.- Do NOT touch
src/mcp-client.ts'sclientInfo.version(0.1.0) — it is a static MCP client identifier, not the plugin version.
- Do NOT touch
Kiro plugin — bump together
Kiro has no plugin.json / marketplace registry (it reads loose .kiro/ files), so the only versioned files are the skill frontmatters.
10. Every skill under public/kiro-plugin/.kiro/skills/chorus-*/SKILL.md — metadata.version: "X.Y.Z" on the shared skill sequence (all 8 chorus-* skills). The agents/*.json and steering/chorus.md carry no version field — nothing to edit there.
11. public/kiro-plugin/bin/chorus-api.sh — hardcoded clientInfo.version string in the JSON-RPC initialize payload (same as the Codex chorus-mcp-call.sh helper).
Pi package — bump together
packages/chorus-pi/package.json—"version": "X.Y.Z".- Every skill under
packages/chorus-pi/skills/*/SKILL.md—metadata.version: "X.Y.Z", includingopenspec-aware. packages/chorus-pi/extensions/chorus.ts— hardcoded MCPclientInfo.version.
dsh (DeepSeek Harness) plugin — bump together
dsh tracks the app version (currently 0.16.3), NOT the 0.9.x skill sequence.
16. packages/chorus-dsh/package.json — "version": "X.Y.Z" (the published @chorus-aidlc/chorus-dsh bundle).
17. Every skill under packages/chorus-dsh/skills/*/SKILL.md — metadata.version: "X.Y.Z" (the chorus/ overview + all 13 -chorus-suffixed stage/reviewer skills).
- Do NOT hardcode a version in
bin/chorus-mcp-call.mjs— itsclientInfo.versionis auto-read frompackage.json, so it never drifts.
Standalone skills — independent versioning
public/skill/*/SKILL.md— bump only the standalone skills that changed, using their own version sequence.
Quick way to check all versions:
grep -rn '"version"\|^ version:\|^version:\|clientInfo' \
.claude-plugin/marketplace.json \
public/chorus-plugin/.claude-plugin/plugin.json \
public/chorus-plugin/skills/*/SKILL.md \
plugins/chorus/.codex-plugin/plugin.json \
plugins/chorus/skills/*/SKILL.md \
plugins/chorus/hooks/chorus-mcp-call.sh \
packages/openclaw-plugin/package.json \
packages/openclaw-plugin/skills/*/SKILL.md \
public/kiro-plugin/.kiro/skills/*/SKILL.md \
public/kiro-plugin/bin/chorus-api.sh \
packages/chorus-pi/package.json \
packages/chorus-pi/skills/*/SKILL.md \
packages/chorus-pi/extensions/chorus.ts \
packages/chorus-dsh/package.json \
packages/chorus-dsh/skills/*/SKILL.md \
public/skill/*/SKILL.md
Users update via:
/plugin update chorus@chorus-plugins # Claude Code
codex plugin update chorus@chorus-plugins # Codex
# OpenClaw: reinstall/update via the OpenClaw plugin manager (npm spec @chorus-aidlc/chorus-openclaw-plugin)
# Kiro: re-run the installer — curl -fsSL "$CHORUS_URL/install-kiro.sh" | bash (idempotent; merges into ~/.kiro/)
# Pi: pull the Chorus checkout, then reinstall its packages/chorus-pi local path
Pi accepts GitHub sources such as pi install git:github.com/user/repo@ref, but it does not support selecting a package subdirectory. Do not point it at the Chorus monorepo root: Pi would inspect the root package.json, not packages/chorus-pi/package.json. Until Pi is published from a dedicated package-root repository or branch, clone/pull Chorus and install the package by local path.
Skill Content Changes — Seven Surfaces
Chorus skill content lives in seven parallel surfaces. A content change must sweep all seven:
public/chorus-plugin/skills/<skill>/SKILL.md— Claude Codeplugins/chorus/skills/<skill>/SKILL.md— Codexpackages/openclaw-plugin/skills/<skill>/SKILL.md— OpenClawpublic/kiro-plugin/.kiro/skills/chorus-<skill>/SKILL.md— Kiro (note thechorus-prefix; the overview lives insteering/chorus.md, not achorus/SKILL.md)packages/chorus-pi/skills/<skill>/SKILL.md— Pipackages/chorus-dsh/skills/<skill>-chorus/SKILL.md— dsh (note the-chorussuffix; keeps achorus/SKILL.mdoverview)public/skill/<skill>-chorus/SKILL.md— standalone (note the-chorussuffix and flatter set)
Sweep command — find every occurrence before editing so nothing is missed:
grep -rniE "<your-search-term>" \
public/chorus-plugin/skills/ plugins/chorus/skills/ \
packages/openclaw-plugin/skills/ public/kiro-plugin/.kiro/skills/ \
packages/chorus-pi/skills/ packages/chorus-dsh/skills/ public/skill/
Then bump the relevant version sequences (shared skill frontmatter across plugin surfaces 1–5, independent standalone version for #6, and per-package versions as needed).
Porting Changes Between Plugins
Whenever you change content in one plugin, mirror it into the other plugin surfaces unless the difference is intentional. Typical workflow:
- Make the change in
public/chorus-plugin/skills/<skill>/SKILL.md - Diff-check the counterparts:
diff public/chorus-plugin/skills/<skill>/SKILL.md plugins/chorus/skills/<skill>/SKILL.mddiff public/chorus-plugin/skills/<skill>/SKILL.md packages/openclaw-plugin/skills/<skill>/SKILL.mddiff public/chorus-plugin/skills/<skill>/SKILL.md packages/chorus-pi/skills/<skill>/SKILL.md
- Apply the same semantic change to every port, but preserve intentional phrasing:
- Codex:
.mcp.json→~/.codex/config.toml,Task tool→spawn_agent,/chorus:X→$X, "sessions auto-managed" → "sessions are optional / stateless port" - OpenClaw: tool names
chorus_<tool>→chorus__<tool>,AskUserQuestion→ plain-text prompt, reviewers viasessions_spawn, OpenSpec detection is inline (no SessionStart hook), sessions are manual - Kiro:
chorus-skill prefix, native JSON subagents,@chorustools, and hook-driven context - Pi:
/skill:X,subagent_spawn, plain-text prompts, reviewer.mdagents, extension-managed worker sessions
- Codex:
- Bump all affected plugins' versions (all files in the Version Bump Checklist)
- For the Codex plugin, also verify
chorus-mcp-call.shclientInfo.versionmatches
Plugin vs Standalone Skill: Tone Differences
The plugin skill targets Claude Code specifically. The standalone skill targets any MCP-compatible agent (Cursor, Kiro, etc.).
| Aspect | Plugin (public/chorus-plugin/skills/) |
Standalone (public/skill/) |
|---|---|---|
| AskUserQuestion | "ALWAYS use... NEVER display as text" | "prefer your IDE's interactive prompt if available" |
| Session management | "Do NOT create sessions — plugin handles it" | "Create or reopen a session before starting work" |
| Skip elaboration | "you MUST ask the user for permission first" | "confirm with the user first" |
| Hook references | References specific hooks (SubagentStart, etc.) | No hook references |
Rule of thumb: Plugin version uses MUST/NEVER/ALWAYS. Standalone version uses "prefer", "confirm", "consider".
Adding a New MCP Tool — Full Checklist
- Implement in
src/mcp/tools/*.ts(pm.ts, public.ts, etc.) - Add to
docs/MCP_TOOLS.md - Update permission tables and tool lists in all seven overview surfaces:
public/chorus-plugin/skills/chorus/SKILL.mdplugins/chorus/skills/chorus/SKILL.mdpackages/openclaw-plugin/skills/chorus/SKILL.md(use thechorus__<tool>namespaced form)public/kiro-plugin/.kiro/steering/chorus.md(Kiro has nochorus/SKILL.md— the overview is the steering doc)packages/chorus-pi/skills/chorus/SKILL.mdpackages/chorus-dsh/skills/chorus/SKILL.mdpublic/skill/chorus/SKILL.md
- If it changes a stage workflow, update the matching stage skill in all seven locations.
- Bump every affected plugin's versions (see Version Bump Checklist)
- Run
npx tsc --noEmitto verify
Modifying Hook Scripts
Claude Code plugin hooks (public/chorus-plugin/bin/)
on-session-start.sh— SessionStart hook (cachesagent_permissionsvia"$API" state-set)on-user-prompt.sh— UserPromptSubmit hookon-subagent-start.sh— SubagentStart hookon-subagent-stop.sh— SubagentStop hook (readsagent_permissionsviastate-get)on-teammate-idle.sh— TeammateIdle hookon-pre-enter-plan.sh,on-pre-exit-plan.sh— Plan mode hookson-task-completed.sh— TaskCompleted hookon-post-submit-proposal.sh,on-post-submit-for-verify.sh— PostToolUse reviewer reminders
Codex plugin hooks (plugins/chorus/hooks/)
on-session-start.sh— SessionStart hook (stateless; no caching)on-post-submit-proposal.sh— PostToolUse forchorus_pm_submit_proposalon-post-submit-for-verify.sh— PostToolUse forchorus_submit_for_verifychorus-mcp-call.sh— shared MCP-over-HTTP helper (bumpclientInfo.versionon release)hook-output.sh— stdout-formatting helper
Codex has no SubagentStart/Stop events — do not try to port lifecycle hooks from the Claude Code plugin. Instead, session management is documented as a main-agent responsibility in plugins/chorus/skills/develop/SKILL.md and $yolo.
OpenClaw plugin — TypeScript runtime, not bash hooks (packages/openclaw-plugin/src/)
OpenClaw has no bash hooks at all. Its real-time behavior is a compiled TypeScript extension declared in package.json's openclaw block (extensions: ["./src/index.ts"], runtimeExtensions: ["./dist/index.js"]):
index.ts— entry point / activation (activation.onStartupinopenclaw.plugin.json)mcp-client.ts,mcp-registration.ts— registers Chorus MCP tools (namespacedchorus__<tool>)sse-listener.ts,event-router.ts,wake.ts— SSE event stream → agent wake (the OpenClaw analogue of the other plugins' notification hooks)config.ts,commands.ts— config schema handling and slash commands
After modifying the runtime: cd packages/openclaw-plugin && npm run typecheck && npm run test. A linked install loads src/ directly via jiti; an npm install requires the compiled dist/ (npm run build). Bash 3.2 rules do not apply here (it's TypeScript, not shell). Two known runtime gotchas: a linked install loads TS via jiti (no dist) while an npm install needs compiled dist + runtimeExtensions; and SSE→agent wake requires activation.onStartup + runEmbeddedAgent with an explicit provider/model.
Kiro plugin hooks (public/kiro-plugin/bin/)
Kiro hooks are bash (Bash-3.2 rules apply) but declared inside agents/chorus.json (Kiro has no standalone hooks.json), and each hook's STDOUT is added to the agent context as plain text (there is no additionalContext JSON envelope like Claude Code). Scripts:
on-agent-spawn.sh—agentSpawnhook:chorus_checkin→ startup context (owner/permissions/idea-tracker). "Not configured" if Chorus env is unset; never aborts the spawn.on-stop.sh—stophook: best-effort session heartbeat/checkout; never blocks the turn.on-post-submit-proposal.sh/on-post-submit-for-verify.sh/on-post-verify-task.sh—postToolUsehooks matched to@chorus/chorus_pm_submit_proposal/@chorus/chorus_submit_for_verify/@chorus/chorus_admin_verify_task; emit a nudge to spawn the matching reviewer subagent. Exit 0 with no output if no parseable UUID.chorus-api.sh— the reused MCP-over-HTTP wrapper (bump the hardcodedclientInfo.versionon release, like Codex'schorus-mcp-call.sh). Hook scripts reference it via a path relative to their own location, never a hard-coded repo path.test-syntax.sh— Bash-3.2 parse + mock-event smoke test harness.
Hook command strings in the repo chorus.json use the __CHORUS_BIN__ placeholder; public/install-kiro.sh copies bin/*.sh into <KIRO_DIR>/chorus-bin/, chmod +x, and substitutes __CHORUS_BIN__ with that absolute path. Never commit a concrete machine path in the repo copy — only the installed copy is concretized.
Pi extension (packages/chorus-pi/extensions/)
Pi uses a native TypeScript extension instead of lifecycle bash hooks:
session_startperforms checkin, OpenSpec detection, and startup notification.before_agent_startinjects checkin context once.- Mutable
tool_callonsubagent_spawncreates a session only forworkerand injects its UUID/workflow. tool_resultandtool_execution_endmap spawned agent IDs, close sessions, and emit reviewer nudges.session_shutdownretries retained session closures.
Keep pure parsing/path/banner helpers in lib/lib.ts. Preserve failed-close mappings for shutdown retry, and do not create sessions for scout/planner/reviewer/custom agents. The OpenSpec shell wrapper must resolve both env and .mcp.json configuration, but it is not a lifecycle hook.
After modifying the Pi package, run cd packages/chorus-pi && bash test/all.sh. This covers static checks, pure helper tests, and extension-event tests; update test/verify-pi-session.md when behavior requires live Pi verification.
CRITICAL: All hook scripts MUST be compatible with Bash 3.2. macOS ships with /bin/bash 3.2 (due to GPL licensing) and Claude Code + Codex + Kiro all use it to execute hooks. Do NOT use Bash 4+ features:
| Bash 4+ (FORBIDDEN) | Bash 3.2 alternative |
|---|---|
${VAR,,} (lowercase) |
$(printf '%s' "$VAR" | tr '[:upper:]' '[:lower:]') |
${VAR^^} (uppercase) |
$(printf '%s' "$VAR" | tr '[:lower:]' '[:upper:]') |
declare -A (associative arrays) |
Use separate variables or jq |
readarray / mapfile |
while IFS= read -r line loop |
|& (pipe stderr) |
2>&1 | |
&>> (append both) |
>> file 2>&1 |
After modifying:
- Run
/bin/bash public/chorus-plugin/bin/test-syntax.sh(Claude Code + Codex hooks) and/bin/bash public/kiro-plugin/bin/test-syntax.sh(Kiro hooks) on macOS to verify Bash 3.2 compatibility — OpenClaw and Pi lifecycle code are TypeScript - Test locally:
claude --plugin-dir public/chorus-plugin(Claude Code), install viacodex plugin installand reload (Codex), re-runinstall-kiro.sh(Kiro), orpi install "$PWD/packages/chorus-pi"from the Chorus checkout (Pi) - Bump plugin version for whichever packages changed (all affected packages)
- Users must restart the affected agent after updating (Kiro: re-run the installer; Pi: reinstall the package)
Testing Plugin Changes
# Claude Code — load plugin locally (no install needed)
claude --plugin-dir public/chorus-plugin
# Or update installed plugin
/plugin update chorus@chorus-plugins
# Verify plugin loaded
/plugin list
# OpenClaw — typecheck + test the TypeScript runtime
cd packages/openclaw-plugin && npm run typecheck && npm run test
# Kiro — dry-run the installer into a throwaway HOME, then assert the tree
HOME=$(mktemp -d) CHORUS_URL=https://example.com CHORUS_API_KEY=cho_test \
bash public/install-kiro.sh < /dev/null
# verify hook scripts parse under Bash 3.2
bash public/kiro-plugin/bin/test-syntax.sh
# Pi — static checks + helper and extension-event tests
cd packages/chorus-pi && bash test/all.sh
# dsh — typecheck + lint + unit tests + published-bundle validation
cd packages/chorus-dsh && pnpm run typecheck && pnpm run lint && pnpm test && pnpm run check:package
Version History
-
96a2f67
Current 2026-08-20 02:30
新增dsh (DeepSeek Harness)插件支持,维护插件数量由4个增至6个,技能表面由5个增至7个。
- c08357a 2026-07-25 08:34


