pikiloom is a layered, open Agent orchestrator. Four conceptual layers — terminals, agents, models, tools — sit on top of cross-cutting infrastructure. This document covers the design principles and extension recipes; the full source tree is in CLAUDE.md.
┌─────────────────────────────────────────────────────────────┐
│ cli/ CLI entry point, terminal setup │
│ dashboard/ Web server, API routes, runtime singleton │
├─────────────────────────────────────────────────────────────┤
│ channels/ Per-IM transport + bot orchestration │
├─────────────────────────────────────────────────────────────┤
│ bot/ Shared bot runtime, commands, streaming │
├─────────────────────────────────────────────────────────────┤
│ agent/ Agent drivers, sessions, MCP tools, CLI │
├─────────────────────────────────────────────────────────────┤
│ catalog/ Data-only extension manifests │
│ core/ Constants, logging, config, utilities │
└─────────────────────────────────────────────────────────────┘
Imports flow strictly downward. core/ and catalog/ import from nothing inside src/. No layer imports from a layer above it. This keeps the lower layers testable in isolation and prevents circular dependencies.
- Channels: Telegram, Feishu, WeChat, Slack, Discord, DingTalk, WeCom
- Agent drivers: Claude Code (
claude,claude-tui), Codex, Gemini, Hermes (via ACP) - Project skills:
.pikiloom/skills/*/SKILL.mdplus legacy.claude/commands/*.mdcompatibility - Session-scoped MCP tools:
im_list_files,im_send_file,im_ask_user - Browser automation: managed Chromium via
@playwright/mcp, supervised bybrowser-supervisor.ts - macOS desktop automation: built-in Peekaboo MCP — Accessibility API + ScreenCaptureKit
- Dashboard: Hono server + React SPA at
http://localhost:3939
Incoming IM message
→ channels/*/channel.ts normalizes text / files / context
→ channels/*/bot.ts resolves command vs free text
→ bot/orchestration.ts handleIncomingMessage()
→ placeholder message created
→ channels/telegram/live-preview.ts (channel-agnostic) updates the placeholder while streaming
→ bot/bot.ts runStream() prepares agent options + MCP bridge
→ agent/stream.ts dispatches to AgentDriver via agent/driver.ts registry
→ if Codex requests user input, or im_ask_user is invoked, bot/human-loop.ts renders the prompt in-channel
→ final reply rendered via channels/*/render.ts
→ artifacts / im_send_file callbacks delivered back to IM
Business logic lives in shared bot/ modules:
bot.tsowns runtime statecommands.tsreturns structured command datacommand-ui.tsbuilds shared selection UIsorchestration.tsowns the message pipeline
Channels differ only in transport, rendering format, callback payloads, and capability flags.
agent/driver.ts exposes the AgentDriver interface (doStream / getSessions / getSessionTail / listModels / getUsage / shutdown). agent/index.ts imports drivers for side effects; higher layers talk only to the registry.
Each conversation runs against a pikiloom-managed session workspace used for staged attachments, session metadata, project skill discovery, and MCP tool visibility. This is why file return, skills, and per-session tools behave consistently across agents.
agent/stream.tsstartsagent/mcp/bridge.ts- The bridge launches a localhost callback server
agent/mcp/extensions.tsmerges global + workspace MCP config (resolving disabled flags and OAuth bearer headers)- The agent CLI launches
agent/mcp/session-server.ts - MCP tools call back into the parent process and stream artifacts to the IM chat in real time
bot/human-loop.ts is a single state machine handling both Codex's structured user-input requests and the im_ask_user MCP tool. It renders an IM card or dashboard prompt, waits for the answer, and resumes the same task.
catalog/*.ts files are arrays of TypeScript objects consumed by the dashboard and registries. Adding a recommended server, CLI, or skill is a one-file PR.
browser-supervisor.ts owns the managed Chrome profile across all streams. Streams ensure() it (singleflight-ed); invalidate() is called only on confirmed failure.
The dashboard is not just a setup page — it is the main local control plane for channel validation, agent detection, model discovery, session browsing, workdir switching, extension management, and macOS permission checks. All persistent config lives in ~/.pikiloom/setting.json.
Registered by agent/mcp/session-server.ts:
im_list_filesim_send_file— hands a file to the user via the active terminal. On an IM channel it uploads to the chat; on the dashboard it is recorded to the per-session delivered-artifact manifest (agent/artifacts.ts) and served over HTTP by the attachment endpoint, so a remote browser can fetch it. Both paths record the delivery, so a session watched from either terminal shows the same artifacts (live via the stream snapshot, durably on reload).im_ask_user
Built-in MCP servers togglable from the Extensions tab:
pikiloom-browser—@playwright/mcpagainst a pikiloom-managed persistent Chrome profile. Toggled bybrowserEnabled.peekaboo— Peekaboo MCP for native macOS GUI automation. Toggled bypeekabooEnabled; macOS only; requires Screen Recording + Accessibility permissions.
- Create
src/agent/drivers/xxx.tsimplementingAgentDriver - Import it from
src/agent/index.ts(side-effect import triggers registration) - Add model / extra-args config handling in
core/config/runtime-config.tsif needed - If the agent ships an external CLI, add an entry to
catalog/cli-tools.tsand any auth flow underagent/cli/ - Add unit tests, and live E2E coverage where possible
You usually do not need to touch channels/*/bot.ts, bot/commands.ts, or bot/command-ui.ts — those consume the driver registry generically.
- Implement
channels/xxx/channel.tsextendingChannel - Implement
channels/xxx/render.tsfor platform-specific rendering - Implement
channels/xxx/bot.tsfor command routing and streaming lifecycle - Register it from
cli/main.ts - Extend
core/config/validation.tsandcli/setup-wizard.tsif the channel has its own credentials
See INTEGRATION.md for the full channel guide.
- Create or extend a module in
src/agent/mcp/tools/ - Export
toolsdefinitions and ahandle()implementation - Register the module in
agent/mcp/session-server.ts - Keep tool results text-based and JSON-serializable
- For tools with IM side effects, use the callback URL path exposed by the bridge
- Append a new entry to the appropriate
catalog/*.tsfile - For MCP servers needing OAuth, declare an
authspec —agent/mcp/oauth.tshandles the flow - For CLIs needing browser-based auth, declare an
authspec —agent/cli/auth.tsdrives the session - No other code changes are required — the dashboard picks it up from the catalog
- README.md
- CLAUDE.md — project structure tree, key concepts, quick reference
- INTEGRATION.md — channel integration guide
- TESTING.md
- CONTRIBUTING.md