Install globally. Open a chat. Done.
# 1. install globally (or: npm install && npm run build && npm link) npm i -g tachi-agent # 2. pull a local brain (or set TACHI_DRIVER=openai + OPENAI_API_KEY) ollama serve & ollama pull qwen2.5 # 3. point at your MCP servers export TACHIBOT_CMD="npx -y tachibot-mcp" export DOKORO_CMD="npx -y @devlog-mcp/core" # optional # 4. preflight check tachi-agent doctor # 5. open interactive chat tachi-agent
tachi-agent doctor checks your Ollama endpoint, required env vars, and MCP server commands — run it the first time and whenever something looks off.
Bare tachi-agent opens a persistent REPL session. The prompt shows tachi [driver·skill] ›. Type your task, or use /help to see the unified command list.
Ctrl+D or /exit to leave.
One-shot tasks and local development.
# one-shot task (pass a string argument) tachi-agent "verify HEAD against ADR-1..3" # develop from source npm install npm test # vitest — core orchestrator, fully mocked npm run build # tsc → dist/
Ctrl + C halts the run cleanly (AbortSignal →
aborted). Progress streams to stderr; the final answer
prints to stdout — so you can pipe the answer while still watching steps.
Talk to the same hub, any surface.
- CLI / REPL (default) — bare
tachi-agentopens the interactive REPL; pass a string for a one-shot task. - Skills —
--skill <name>loads a.tachi/skills/*.mdrecipe (system prompt + tool allowlist + driver preset). - Telegram — bot front-end with allowed user-ids; unified
/commandssurface. - Slack — Socket Mode app.
- Claude Code — connect in via the
run_agentMCP server. - HTTP / SSE Gateway — async jobs + streamed events.
- OpenClaw bridge — delegate over the gateway with
GatewayClient. - Swarm — fan-out / synthesize bin:
npm run swarm. - Standalone daemon — unattended queue + schedules + notifications:
tachi-agent service install(macOS launchd, primary path) ornode dist/daemon/index.jsunder systemd — Standalone page.
Env vars are the config surface.
| Variable | What it does |
|---|---|
TACHI_DRIVER | Default brain by registered name: ollama (default, local) · hermes · openai · openrouter. A queued task's driver field overrides per task. |
OLLAMA_BASE_URL | Ollama endpoint for the local brain (defaults to 127.0.0.1). |
OLLAMA_MODEL | Local model id, e.g. qwen2.5. |
TACHIBOT_CMD | Command to launch the tachibot MCP server (council tools). |
DOKORO_CMD | Command to launch the dokoro MCP server (memory). Optional. |
TACHI_ALLOW | Tool allowlist — restricts which namespaced tools the agent may call. |
TACHI_SWARM_ROLES | Comma-separated roles for the swarm; name or name:driver; empty = defaults. |
GATEWAY_TOKEN / GATEWAY_PORT | Bearer token and port for the HTTP/SSE gateway. |
TACHI_MAX_TOOL_RESULT_CHARS | Truncate tool results before they reach the model context — defaults to 30000; 0 disables. |
TACHI_MAX_EMPTY_TURNS | Consecutive blank model turns nudged through before halting as empty-response (default 2). |
TACHI_SKILLS_DIR | Directory of *.md skill files (default .tachi/skills). Malformed files are skipped with a warning. |
The standalone surface — queue, schedules, drivers, notifications, run logs (TACHI_QUEUE_FILE, TACHI_SCHEDULES_FILE, TACHI_NOTIFY, TACHI_RUN_LOG_DIR, …) — lives on the Standalone page.
Extend without forking.
Register any brain, build the hub from a name, run. Implement Driver / ToolHost / Memory to extend — no core changes.
import { createOrchestrator, registerDriver } from "tachi-agent"; // 1. register any brain (Hermes, a cloud model, OpenClaw, a Kimi-swarm driver) registerDriver("hermes", () => new HermesDriver()); // 2. build the hub from a registered name (or a raw Driver instance) const controller = new AbortController(); const result = await createOrchestrator({ driver: "hermes", host, memory, options: { maxIterations: 12, timeoutMs: 90_000, signal: controller.signal, // memoryInLoop: true // opt-in: refresh recall + write a working-memory note // // each iteration. Off by default (adds per-step tool calls). }, }).run("verify HEAD against ADR-1..3"); // elsewhere: controller.abort() → run halts with haltedBy: "aborted"
The complete public API is three interfaces — see src/types.ts. Implement Driver, ToolHost, or Memory and compose the same hub; no core changes required.