pi-muselinn-harness

Kimi Code-style agent orchestration harness for Pi coding agent — Swarm (concurrent subagents + braille TUI), Goal (lifecycle + budget + queue), Plan (plan mode + tool restrictions), Permission (18-level policy chain: auto/yolo/manual), Task (background +

Packages

Package details

extension

Install pi-muselinn-harness from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-muselinn-harness
Package
pi-muselinn-harness
Version
0.9.15
Published
Aug 1, 2026
Downloads
3,196/mo · 1,779/wk
Author
muselinn
License
MIT
Types
extension
Size
720.4 KB
Dependencies
1 dependency · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-muselinn-harness

test

Kimi Code-style agent orchestration for the Pi coding agent — Swarm · Goal · Plan · Permission · Ask · Task · Cron · Todo · Hooks · Skills · TUI, one package that builds the features Pi deliberately skips (sub-agents, plan mode, todo, …) and aligns them with Kimi Code's subsystem behavior.

Compatible with pi 0.81.x–0.83.x on macOS, Ubuntu, and Windows · Node 22/24 · CI-tested on Ubuntu + Windows.

Closed-box editor with streaming state in the top border

What is this?

Pi is a focused coding agent: no sub-agents, no plan mode, no todo. This harness adds them — in the same style as Kimi Code — as a single install:

You want You get
Parallel sub-agents agent_swarm / agent — real max_concurrency, live braille-grid TUI, run_in_background, /resume
Plan before execution enter_plan_mode — read-only exploration, approval gate, Kimi Code permission model
Stay on task /goal — lifecycle, budgets, queue, completion-criterion gate
Safety rails 18-level permission chain (auto / yolo / manual), destructive-command + .env guards
Work that outlives the turn run_background + cron_create — persistent tasks and scheduled prompts
The agent asks properly ask_user_question — tabbed multi-question dialog with previews
Task tracking /todo + todo_list — phased plan with inline panel and reminders
A nicer editor ╭─╮ │ ╰─╯ closed-box TUI with spinner + model in the border
Lifecycle automation [[hooks]] engine — 16 events, blockable PreToolUse/Stop/UserPromptSubmit

Quick start

pi install npm:pi-muselinn-harness     # or: pi install git:github.com/MuseLinn/pi-muselinn-harness
pi                                      # restart, then:

Try it out:

/swarm on                                # enable swarm mode
/goal Refactor the auth module           # set a goal with budget tracking
/todo init "Phase 1: scanner"            # start a phased task plan
/plan                                    # enter plan mode (read-only exploration)
/tui style plain|boxed|compact           # switch editor chrome anytime

Everything works out of the box — no companion extensions required. All tools are model-callable, all commands are slash commands with Tab completion.

Upgrading from ≤ 0.7.4? Remove the old companion extensions — they conflict with the built-in tools (pi refuses to start on duplicate tool names):

pi remove npm:@juicesharp/rpiv-ask-user-question
pi remove npm:rpiv-todo

Features

Swarm

  • In-process subagentscreateAgentSession() execution, coder / explore / plan types
  • Real concurrency controlrunProgressive() worker pool with true max_concurrency cap + exponential backoff retries
  • 30-minute timeout — per-subagent AbortSignal.timeout (aligned with Kimi Code)
  • run_in_background — whole swarm goes to a background task, early task-ID return, report written to output_path
  • Smart model routing — task-aware selection from ctx.modelRegistry
  • Braille progress bars — driven by real tool-call progress, 250 ms frames with a state-fingerprint gate (unchanged frames cost nothing)
  • Harness-branded spinner — single-width braille rotation by default (PI_MUSELINN_SPINNER=braille|pulse|bounce|moon, incl. Kimi moon-phase compat)
  • Adaptive layout — pi-tui Component protocol, status bar width adapts to the terminal (10–60)
  • Three-pane task browser — status glyphs (○ pending / ◐ running / ✓ done / ✗ failed / ▲ aborted), strikethrough on done rows, overflow collapse (+N more, running kept first), named keybindings, ctrl+shift+t
  • Cancel / resume — UserCancellationError + AbortSignal chain, two-step /cancel

Goal

  • Lifecycle — active / paused / blocked / complete / usage_limited / budget_limited
  • Active Guardcreate_goal refuses to silently overwrite an active goal (replace=true or /goal replace)
  • Blocked 3-turn threshold — three consecutive blocks for the same reason before really blocking
  • Completion-criterion gate — a declared criterion must be verified before completing (verified=true in the same update_goal call; documented in the tool description)
  • Triple budget checks — tokenBudget + turnBudget + wallClockBudgetMs (turns/tokens/ms/s/minutes/hours)
  • Goal Queue — FIFO + high/normal priority + auto-switch + prioritize/drop/skip
  • Persistence — appendEntry + session_start restore; counters merge monotonically (max per goalId), so a stale entry can never pull turns/tokens backwards; clear() writes a tombstone entry so completed goals stay completed
  • Context injection<untrusted_objective> tag into the system prompt
  • Recovery — compaction preservation + context-overflow detection + 429 detection

Plan

  • Plan mode — the LLM explores, writes a plan, and only executes after approval
  • Kimi Code permission model — bash is NOT blocked in plan mode; it follows the normal permission mode (auto/yolo/manual). Only Write/Edit (outside plan file), TaskStop, CronCreate, CronDelete are blocked
  • Plan file path matching — exact path, local:// scheme basename, and resolved absolute path under sessionDir/plans/ — all three accepted
  • ExitPlanMode reads the plan file — presentation matches what was actually written to disk
  • Revise keeps your plan — a revised or cancelled review re-enters plan mode with the same plan object (id/path/content), never a trap, never lost work; review timeout 600 s
  • Restore validation — a stale persisted active-plan entry with no content and no file on disk deactivates plan mode instead of trapping the session
  • Context injection — the plan is injected into the system prompt

Permission

  • 18-level policy chainauto / yolo / manual; safety policies (destructive, sensitive files) short-circuit before modes
  • Destructive detectionrm -rf / git push --force / drop table / git reset --hard regex recognition, always asks, never short-circuited by session approvals
  • Sensitive-file guard.env / id_rsa / *.key read/write interception, even in auto mode
  • Session approval fingerprints — approvals remembered per sessionId + input fingerprint, never degrading into "permanent allow"
  • Approval panel — numbered dialog with per-tool action titles ("Run this command?" / "Apply these edits?"), digit-key direct select, four outcomes: Allow once / Always allow (session) / Deny / Deny with reason (reason relayed to the model)
  • Subagent gating — swarm worker tool calls run through the same policy chain (shared in-process manager): /mode switches propagate to in-flight subagents by construction, ask verdicts degrade to blocks (never silent approval)
  • AGENTS.md hierarchy — project (nearest AGENTS.md or .kimi-code/AGENTS.md) → global $KIMI_CODE_HOME/AGENTS.md → cross-tool ~/.agents/AGENTS.md, aggregated; destructive-ask-always can upgrade ask to deny
  • Config cache — permission config cached by file mtime, edits take effect immediately

Task (background + cron)

  • run_background — subagent in the background, immediate task ID; output_path pages full output via Read
  • 30-minute timeout — background tasks auto-fail (stopReason=timeout_30min)
  • task_list / task_output / task_stopactive_only filter, block+timeout waiting, offset/limit paging
  • 50-task cap + 7-day stale cleanup + orphaned tasks degrade to process_restart on restart
  • Incremental persistence — single-task changes append a single entry; restore stays compatible with old snapshots
  • Cron — 5-field cron (local timezone) + deterministic jitter (10% of period, ≤15 min) + recurring/one-shot + 50 cap + 7-day stale auto-delete

Hooks

  • Kimi Code-aligned [[hooks]] engine — reads $KIMI_CODE_HOME/config.toml (default ~/.kimi-code/config.toml) + project .kimi-code/config.toml; event/matcher/command/timeout fields
  • Full event coverage — UserPromptSubmit / PreToolUse / Stop (blockable) + PostToolUse / PostToolUseFailure / PermissionRequest / PermissionResult / SessionStart / SessionEnd / SubagentStart / SubagentStop / StopFailure / Interrupt / PreCompact / PostCompact / Notification
  • Exit-code semantics0 allow (stdout appended as context), 2 block (stderr as reason), anything else / timeout / crash fails open; stdout JSON permissionDecision: deny supported
  • Built-in TOML mini-parser — zero dependencies; invalid rules warn and skip without breaking the extension; mtime-cached hot reload
  • Safety net — Stop auto-disables after 3 consecutive blocks (anti-loop); every trigger mirrored to pi.events for other extensions

Skills

  • Seven-scope pi-native scanning — project .pi/skills, .kimi-code/skills (Kimi compat), .agents/skills → user ~/.pi/agent/skills, ~/.pi/skills, $KIMI_CODE_HOME/skills, ~/.agents/skills; pi-native dirs win, Kimi dirs as compat layer, dedupe by name
  • Directory + flat formsSKILL.md subdirs (with auxiliary files) and single .md files; full frontmatter fields (name/description/type/whenToUse/disableModelInvocation/arguments, kebab/snake variants)
  • Available to subagents — swarm and background subagent sessions receive skills via resourceLoader; the main session is injected via resources_discover (collision-free: only files from dirs pi does not scan natively, minus names pi already provides)
  • Zero-dependency frontmatter parser + mtime directory-tree cache

TUI

  • Closed-box editor — Kimi Code's wrapWithSideBorders ported: pi-tui's horizontal-only borders post-processed into a ╭╮│╰╯ closed box; spinner + working state (Thinking/Streaming/Running tools) embedded in the top border; three styles plain | boxed | compact (pi-spark-style info border = compact), default boxed; model name opt-in via "modelInBorder": true

    The first content line carries a prompt chevron (│❯ text │), padding is clamped to ≥2 so the bars never touch the text or cursor.

  • /tui command — hot-switch styles without restarting (pi preserves text/focus/keybindings when swapping editors); /tui timing shows render timing; config persisted to ~/.pi/agent/muselinn-tui.json (project .pi/ override)

  • Plan badgeplan text badge on the top border while plan mode is active (no border recoloring — zero conflict with pi's thinking-level colors)

  • Timing probePI_MUSELINN_HARNESS_TUI_TIMING=1 records editor render() P50/P99; spinner only ticks at 250 ms while the agent works

  • Shimmer working message (OMP-style) — the working label in the editor border gets a wall-clock driven light-band sweep (classic cosine band or kitt K.I.T.T. scanner); the crest paints accent+bold so dim text stays legible mid-animation. low: dim / mid: muted / high: accent by default; /tui shimmer <classic|kitt|disabled> switches live, config persisted

  • Stable animation frame-rate — the keep-alive timer uses a fixed 200ms quiet gate (≈10fps ceiling) so the animation cadence never changes; natural streaming renders ride pi's own frames at zero extra cost, and a stalled agent loop costs at most ~10 full-tree renders per second even on very large sessions. (Adaptive thresholds based on measured render latency were tried and rejected: latency noise made the frame rate stutter.)

Ask (interactive questions)

  • ask_user_question tool — the agent asks 1-4 structured questions in one tabbed dialog: per-question header tabs (1/3 · header, ←/→/Tab to switch), numbered options with description sub-lines, multi_select checkboxes (Space toggles, Enter confirms), and an automatic free-text Other option on every question; digit keys 1-9 jump straight to an option, arrows/jk navigate, Esc cancels
  • Robust by default — long option lists scroll inside a bounded window, duplicate answers are deduplicated, and questions can be posed from background tasks without wedging the UI
  • Previews, notes, chat row — options can carry Markdown previews (side-by-side pane on wide terminals, stacked below on narrow ones); attach a per-option note with n; a Chat about this row ends the dialog with a chat result so the user can discuss the question instead of answering it
  • Shared dialog component — the same component backs permission approval (single-select, no Other); in print/RPC mode the tool returns the questions as text instead of blocking
  • Answer reporting — per-question answers (multi-select as an array); skipped questions and Esc-cancelled dialogs are reported distinctly
  • Auto-mode safe — auto mode denies ask_user_question by policy (no unattended hangs)

Todo

  • Inline panel — above-editor widget with roman-numeral phase tree (Ⅰ. Scanner · 2/4), /todo toggle expand/collapse; finished tasks auto-clear after PI_MUSELINN_TODO_CLEAR_DELAY seconds (default 60, 0 = instant, -1 = manual) so completed plans fade out of the HUD instead of lingering
  • /todo command — full oh-my-pi phase model: init, start, done, drop, rm, append, export, import, copy, edit, add_notes, update_details, bare /todo prints Markdown
  • todo_list tool — model-driven task management with same ops
  • Reminder system — incomplete todos injected as <system-reminder> when agent stops (max 3 reminders, debounced)
  • Subagent matching — pending tasks matching swarm subagent descriptions get highlighted with spinner
  • Markdown round-trip/todo export/import for persistence and sharing between sessions
  • Notes — per-task notes via add_notes / update_details
  • Phase counts — widget header shows N active · M pending · K done
  • Session persistence — survives hot-reload and session restart

Web fetch

  • fetch_url tool — no-auth URL fetch (20s timeout, 5MB stream cap, redirect follow); HTML → readable text (dependency-free extractor), JSON → pretty-print, everything else raw; 20k char cap with max_chars tuning

Plugins (declarative bundles)

  • muselinn.plugin.json — six declarative capabilities: skills (skill dirs merged into discovery), sessionStart (context injected on the session's first turn), hooks (merged into the [[hooks]] engine), commands (.md files become slash commands), plus mcpServers / interface recorded with skipped-diagnostics
  • Discovery — project .pi/plugins/*/ then user ~/.pi/agent/plugins/*/, first-wins name dedupe; /plugins lists capabilities and diagnostics

Output truncation

  • Oversized tool results spill to disk — results over 40k chars are written to <sessionDir>/tool-results/ and replaced in context with a sanitized head+tail preview carrying the output_path and read-paging instructions (Kimi toolResultTruncation pattern)

Commands

Command Description
/swarm on|off Toggle swarm mode
/cancel Cancel current work (two-step confirm)
/resume Resume an interrupted swarm
/tasks Task browser (ctrl+shift+t)
/goal <objective> Set a goal
/todo Task plan with phase model; shortcuts: start done drop export import copy edit toggle
/todo toggle Expand/collapse the todo panel (replaces former alt+t)
/plugins List loaded plugins and their capabilities
/swarm-status Show status

/goal /swarm /plan /mode /tui all support Tab completion.

Tools

Tool Description
agent_swarm Batch parallel subagents (max_concurrency / run_in_background / output_path / model_map)
agent Single subagent
create_goal / get_goal / update_goal / set_goal_budget Goal management
enter_plan_mode / exit_plan_mode Plan mode
ask_user_question Tabbed structured questions (multi-select, Other free text)
todo_list Model-driven task plan with inline panel
fetch_url No-auth URL fetch with content-aware extraction
run_background / task_list / task_output / task_stop Background tasks
cron_create / cron_list / cron_delete Cron jobs

Kimi Code alignment

Against the Kimi Code CLI docs — Agents & Subagents:

Capability Status Notes
Three built-in subagent types (coder/explore/plan) coder=read/write+bash; explore=read-only; plan=read-only, no shell
Context isolation Independent sessions; only final results flow back
Parallel dispatch + max_concurrency Real worker-pool cap + progressive launch
30-minute timeout Per-subagent AbortSignal.timeout
Background execution (run_in_background) Early task-ID return, blockable task_output, report to output_path
Resume an existing subagent ⚠️ Conservative semantics: same-id re-run; resume validated (saved state + nothing in flight + remaining items); true session resume pending pi-coding-agent API
Nested subagents (coder spawning more) Deliberately closed — no recursive dispatch; subagent toolset excludes agent/agent_swarm
Permission inheritance Worker tool calls pass through the shared policy chain; /mode propagates by construction; asks degrade to blocks
Instruction-file hierarchy Project AGENTS.md / .kimi-code/AGENTS.md$KIMI_CODE_HOME/AGENTS.md~/.agents/AGENTS.md
wire.jsonl session persistence Subagents use SessionManager.inMemory() (in-process lifecycle)
Hooks ([[hooks]] lifecycle) All 16 events, exit-code/stdout-JSON block semantics, fail-open
Agent Skills (four scopes) ✅+ Kimi's four covered and extended to seven pi-native scopes; directory + flat forms; subagent + main-session channels

Architecture

Core/adapter split: packages/core/ is pure logic with zero pi imports; the repo root holds the pi adapter (entry, pi-tui components, tool registration).

pi-muselinn-harness/
├── index.ts               entry (agent_swarm/agent tools, background runner, module wiring)
├── state.ts               shared state
├── packages/core/         @muselinn/core — pure logic, no host imports
│   ├── ports.ts           host contracts (PersistencePort, ScopeDirs)
│   ├── text-utils.ts      visibleWidth & friends
│   ├── shell-output.ts    control-sequence sanitizer
│   ├── truncation/        oversized tool-result spill (pure)
│   ├── webfetch/          HTML→text / JSON extraction (pure)
│   ├── completions.ts     slash-command argument completions
│   ├── ask/               question spec + formatting (pure)
│   ├── todo/              todo model + Kimi folding strategy (pure)
│   ├── plugin/            muselinn.plugin.json manifest parse/discovery
│   ├── goal/              Goal module (state machine, budgets, queue, persistence)
│   ├── plan/              Plan module (tool whitelist, path guard, injection)
│   ├── permission/        Permission module (18-level chain, approval contract)
│   ├── hooks/             Hooks module (TOML mini-parser, executor, 16 events)
│   ├── skills/            Skills module (frontmatter, seven-scope scanner)
│   ├── swarm/             pure swarm half
│   │   ├── types.ts       state/constants (+ goal re-export)
│   │   ├── helpers.ts     braille bars / layout / spinner (memoized)
│   │   ├── estimator.ts   progress estimation (geometric mean)
│   │   ├── widget-lines.ts braille grid line builders (pure)
│   │   ├── wrap-tools.ts  permission gate wrapper (pure)
│   │   ├── resume-guard.ts resume ownership/idle validation (pure)
│   │   ├── report.ts      swarm report formatting
│   │   └── task-list-utils.ts collapse + key routing
│   ├── task/              cron + task persistence state (pure)
│   └── tui/               box/config/parse/switch/timing (pure chrome parts)
├── swarm/                 adapter: subagent execution, /swarm commands,
│                          SwarmWidgetComponent, three-pane task browser
├── task/                  adapter: background task manager (session spawn)
├── tui/                   adapter: MuselinnEditor + event wiring
├── ask/                   adapter: question dialog + ask_user_question tool
├── todo/                  adapter: todo_list tool + inline panel widget
├── webfetch/              adapter: fetch_url tool
├── plugin/                adapter: plugin loader + /plugins command
└── tests/                 node-level unit tests (below)

Tests

Pure node-level unit tests, no model quota needed (23 suites, 660+ assertions):

npm test                                        # all suites (node tests/run-all.mjs)

or individually:

node tests/musepi-config.test.mjs                 # MusePi config compat — 9
node tests/permission.test.mjs                    # Permission policy chain + subagent gate — 22
node tests/goal.test.mjs                          # Goal state machine + monotonic restore — 32
node tests/plan.test.mjs                          # Plan mode round-trip + restore validation — 42
node tests/task.test.mjs                          # Task restore/list/output/block + loader runtime — 16
node tests/cron.test.mjs                          # Cron subsystem — 16
node tests/hooks.test.mjs                         # Hooks engine — 43
node tests/skills.test.mjs                        # Skills scan/parse/scopes/discover — 38
node tests/tui.test.mjs                           # TUI collapse/keys/completions/spinner — 62
node tests/tui-box.test.mjs                       # TUI box/config/probe/switch — 61
node tests/agent-file.test.mjs                   # agent file discovery/parse — 11
node tests/agent-lifecycle.test.mjs               # agent lifecycle events — 6
node tests/ask.test.mjs                           # ask spec/dialog/answers/approval titles — 123
node tests/tool-policy.test.mjs                  # tool policy gate — 13
node tests/todo.test.mjs                          # todo model + folding strategy — 21
node tests/shell-output.test.mjs                  # output sanitizer — 21
node tests/shimmer.test.mjs                     # shimmer sweep engine — 10
node tests/truncation.test.mjs                    # tool-result spill — 13
node tests/resume-guard.test.mjs                  # swarm resume validation — 6
node tests/webfetch.test.mjs                      # web extraction — 12
node tests/plugin.test.mjs                        # plugin manifest/discovery — 17
node tests/renderer.test.mjs                      # incremental renderer buffer/tree — 16
node tests/stream-rules.test.mjs                  # stream entry rules — 14

The suites run on Node 20/22/24 (20 via tests/ts-esm-loader.mjs, a TypeScript-transpile ESM loader; 22.6+ strips types natively). CI runs the full matrix — ubuntu + windows × node 20/22 — on every push and PR.

Roadmap

  • i18n — bilingual harness UI text and notifications (docs are already split en/zh-CN; the project page has an EN/中 toggle)
  • Math renderer graduation — merge feature/math-renderer once compaction-path context safety is confirmed
  • Clustered diff preview — kimi-style ±3-line clustered diffs in edit/write approval messages (deferred from the P1 batch)
  • True fullscreen — container-swap fullscreen (kimi tasks-browser pattern); no alt-screen, preserving terminal scrollback

Dependencies

  • Pi >= 0.80.0
  • @earendil-works/pi-coding-agent, @earendil-works/pi-ai, @earendil-works/pi-tui (peers)
  • typebox

Experimental branches

  • feature/math-renderer — renders $$...$$ display math in assistant messages via txm (cell-based 2D typesetting, works in Windows Terminal; no image protocol). Context-safe: the original Markdown is restored before every LLM call. Enable with /tui math on after cargo install txm.

Acknowledgments

Design and implementation inspired by these open-source projects:

Kimi Code (Moonshot AI)

  • Agent Swarm concurrency architecture (max_concurrency worker pool, 30-min timeout, run_in_background)
  • Goal system design (GoalActor tracking, Budget Report, blocked 3-turn threshold, context injection)
  • Plan-mode lifecycle (enter/exit/approve/reject, ExitPlanMode disk read)
  • Permission policy chain (auto/yolo/manual, destructive-always-ask, AGENTS.md priority)
  • Cron scheduling (5-field + jitter + 7-day stale + 50 cap)
  • TUI component design (braille progress bars, three-pane task browser, wrapWithSideBorders closed-box editor)
  • Cancel/resume mechanism (AbortSignal chain, UserCancellationError)

pi-spark (zlliang)

  • Editor top-border info slots (spinner + working state + model embedded in the border)
  • Component-replacement TUI customization path (setEditorComponent / setFooter / setWidget)

@narumitw/pi-goal (narumitw)

  • Goal Queue FIFO + auto-switch mechanism
  • usage_limited / budget_limited state design
  • Wrap-up instruction injection (post-budget behavior)
  • Stale Tool Blocking design
  • Compaction retention policy

pi-codex-goal (fitchmultz)

  • Goal persistence (appendEntry + session_start restore)
  • Goal state transitions
  • Budget checking
  • Recovery Machine concept (simplified)

Note: this extension is mostly an independent implementation. Exception: tui/box.ts's wrapWithSideBorders is ported from Kimi Code (MIT), with attribution kept in comments and used under the MIT license.

Releasing (maintainers)

Tag to mark the release (CI publish removed — publish locally with OTP):

npm run version-patch && git tag v0.9.1 && git push origin v0.9.1

Changelog

See CHANGELOG.md for the full version history.

License

MIT