Run a long-lived Smithers workflow in your repo, and control it from Telegram via Takopi. Includes a supervisor that posts periodic status updates, restarts on failure, and can auto-heal.
- Takopi: https://takopi.dev
- Smithers: https://smithers.sh
- Solo devs and small teams
- "I want an agent workflow that runs for hours/days and I can poke from my phone"
- Proof-of-concept friendly
# Initialize in your project
bunx takopi-smithers@latest init
# Configure Telegram credentials in .takopi-smithers/config.toml
# Then start the supervisor
bunx takopi-smithers startRequirements: Bun, Python 3.14+, Takopi, and at least one AI agent CLI (Claude Code, Codex, OpenCode, or Pi)
See Full Setup below for detailed installation instructions.
You need all of these before anything will work:
# Bun (runtime)
curl -fsSL https://bun.sh/install | bash
# Python 3.14+ and uv (Takopi needs these)
# macOS:
brew install python uv
# or see https://takopi.dev/tutorials/install/
# At least one agent CLI:
# Claude Code (recommended): https://docs.anthropic.com/en/docs/claude-code
# Codex: npm i -g @openai/codex
# OpenCode: go install github.com/opencode-ai/opencode@latest
# Pi: cargo install pi-cli- Open Telegram and message @BotFather
- Send
/newbot - Pick a name and username for your bot
- BotFather gives you a bot token like
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11-- save it
- Message your new bot in Telegram (send anything, e.g. "hello")
- Open this URL in your browser (replace
YOUR_BOT_TOKEN):https://api.telegram.org/botYOUR_BOT_TOKEN/getUpdates - Find
"chat":{"id":XXXXXXX}in the JSON response -- that number is your chat ID
pip install takopi
takopi --onboardThis creates ~/.takopi/takopi.toml with your Telegram credentials. The onboarding wizard will ask for your bot token and chat ID from steps 2-3.
cd your-repo
bunx takopi-smithers@latest initNote: Using
@latestensures you get the most recent version from npm. After the first run, you can omit@latest.
This creates:
.smithers/workflow.tsx-- the Smithers workflow (plan/implement/review/fix loop).takopi-smithers/config.toml-- supervisor configurationTAKOPI_SMITHERS.md-- operational rules for the agent- Updates to
CLAUDE.mdandAGENTS.md
Edit .takopi-smithers/config.toml and fill in your bot token and chat ID:
[telegram]
bot_token = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
chat_id = 123456789Or, if you already ran takopi --onboard, the supervisor will fall back to reading ~/.takopi/takopi.toml automatically.
If your workflow needs input (e.g. a spec file path), uncomment and set the input field:
[workflow]
script = ".smithers/workflow.tsx"
db = ".smithers/workflow.db"
input = { specPath = "SPEC.md" }This gets passed as --input '{"specPath":"SPEC.md"}' to smithers run and is available as ctx.input.specPath in your workflow.
bunx takopi-smithers doctorThis checks: Bun, git repo, smithers dependencies, config validity, SQLite write access, takopi config, and Telegram connectivity (sends a test message to your bot).
Fix anything that shows ❌ or ⚠️ before proceeding.
bunx takopi-smithers startThis launches three things:
- Takopi -- Telegram bridge (lets you message the agent from your phone)
- Smithers -- your workflow (
smithers run .smithers/workflow.tsx) - Supervisor -- monitors health, posts status updates every 10min, auto-restarts on crash
Open Telegram and message your bot. The supervisor will post periodic status updates automatically.
Ask it to write/update the Smithers workflow:
Create or refine the Smithers workflow in
.smithers/workflow.tsxto do: . Keep the workflow resumable and keepsupervisor.summaryup to date.
takopi-smithers init # Scaffold config + workflow + agent instructions
takopi-smithers start # Start supervisor (takopi + smithers + health monitor)
takopi-smithers start --dry-run # Start without launching takopi (for testing)
takopi-smithers status # Show workflow state from SQLite
takopi-smithers status --json # Machine-readable status output
takopi-smithers restart # Restart the smithers workflow (keeps takopi running)
takopi-smithers stop # Stop everything
takopi-smithers stop --keep-takopi # Stop workflow but keep Takopi running
takopi-smithers logs # View supervisor logs
takopi-smithers logs --follow # Tail logs in real-time
takopi-smithers logs --level error # Show only errors
takopi-smithers logs --lines 50 # Show last 50 lines
takopi-smithers doctor # Run diagnostics and verify setup.takopi-smithers/config.toml:
version = 1
[workflow]
script = ".smithers/workflow.tsx"
db = ".smithers/workflow.db"
# input = { specPath = "SPEC.md" } # passed as --input JSON to smithers
[updates]
enabled = true
interval_seconds = 600 # post status to Telegram every 10 min
[health]
heartbeat_key = "supervisor.heartbeat"
heartbeat_write_interval_seconds = 30
hang_threshold_seconds = 300 # kill workflow if heartbeat stale >5min
restart_backoff_seconds = [5, 30, 120, 600]
max_restart_attempts = 20
[telegram]
bot_token = "" # from BotFather
chat_id = 0 # from getUpdates API
# message_thread_id = 0 # for Telegram topics/threads
[autoheal]
enabled = true
engine = "claude" # "claude", "codex", "opencode", or "pi"
max_attempts = 3┌─────────────────────────────────────────────────────┐
│ takopi-smithers start │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Takopi │ │ Smithers │ │ Supervisor │ │
│ │ (Telegram │ │ (workflow │ │ (health + │ │
│ │ bridge) │ │ runner) │ │ updates + │ │
│ │ │ │ │ │ auto-heal) │ │
│ └──────────┘ └──────────────┘ └───────────────┘ │
│ │ │ │ │
│ │ .smithers/ │ │
│ │ workflow.db reads heartbeat │
│ │ (SQLite) from SQLite │
│ │ │ │ │
│ └───────── Telegram ─────────────┘ │
│ (status updates + commands) │
└─────────────────────────────────────────────────────┘
The supervisor:
- Polls
supervisor.heartbeatin the SQLite DB every 10s - Kills and restarts the workflow if heartbeat goes stale
- Posts formatted status updates to Telegram on a timer
- Watches
.smithers/workflow.tsxfor file changes and auto-restarts (with 1 second debounce) - On crash, optionally runs an auto-heal agent pass before restarting
The supervisor automatically watches your workflow file (.smithers/workflow.tsx) for changes. When you edit and save the file:
- Debounce: Changes are debounced with a 1-second delay (rapid successive saves only trigger one restart)
- Graceful Restart: The current Smithers process is killed gracefully and a new one starts
- Counter Reset: Restart attempt counters are reset (file changes are intentional, not crashes)
- Telegram Notification: You'll receive a notification that the workflow was reloaded
- Error Handling: If the file is deleted or has syntax errors, the supervisor logs the error and continues running
This makes iterative workflow development seamless - just save your changes and the supervisor handles the rest.
Smithers state persists in SQLite and can resume incomplete executions after restart.
Run independent workflows per git branch. Each worktree gets its own config, DB, workflow, and logs.
git worktree add ../myrepo-feature feature-branch
cd ../myrepo-feature
takopi-smithers init --worktree feature
takopi-smithers start --worktree featureWhen you have multiple worktrees configured, you can manage them all at once using the --all-worktrees flag:
# Start supervisors for all configured worktrees
takopi-smithers start --all-worktrees
# View status of all worktrees in a table
takopi-smithers status --all-worktrees
# Restart all running supervisors
takopi-smithers restart --all-worktrees
# Stop all supervisors
takopi-smithers stop --all-worktreesHow it works:
start --all-worktreesspawns a separate supervisor process for each worktree that has a config filestatus --all-worktreesshows a formatted table with branch name, status, heartbeat age, and summaryrestart --all-worktreessends restart signals to all running supervisorsstop --all-worktreesgracefully stops all supervisors
Note: The --all-worktrees flag is mutually exclusive with --worktree <name> - you can't use both together.
See docs/worktrees.md for detailed setup.
| Problem | Fix |
|---|---|
takopi: command not found |
pip install takopi |
takopi --onboard hangs |
Needs an interactive terminal (not inside an agent) |
| No Telegram messages | Run takopi-smithers doctor to test connectivity |
ENOENT .takopi-smithers/config.toml |
Run takopi-smithers init first |
| Bot doesn't respond to messages | Make sure you messaged the bot first, then check getUpdates |
| Workflow crashes in loop | Check takopi-smithers logs --level error, reduce max_restart_attempts |
| Heartbeat always stale | Your workflow must write supervisor.heartbeat to the state table every 30s |
| Auto-heal keeps failing | Check that your agent CLI (claude, codex, etc.) is on PATH and works non-interactively |
See docs/troubleshooting.md for more.
See docs/codespaces.md for a prebuilt devcontainer setup.
When you run takopi-smithers init, you can choose from several workflow templates:
-
Default (recommended) - Plan/Implement/Review/Fix loop
- General-purpose workflow for spec-driven development
- Iterative loop with quality gates
- Best for: Most projects, following a spec document
-
API Builder - Build REST API endpoints with tests
- Sequential pipeline: research → scaffold → implement → validate
- Idempotent task design (safe to restart)
- Best for: Building REST APIs, microservices
-
Refactoring - Systematic codebase refactoring
- Progressive refactoring with rollback support
- Module-by-module approach with validation gates
- Best for: Large-scale refactoring, technical debt reduction
-
Feature Implementation - Multi-step feature with validation
- Gated progression (must pass tests before next phase)
- Separates core logic, UI, integration, and docs
- Best for: New features requiring comprehensive testing
-
Minimal - Basic scaffold to build from scratch
- Clean slate with just supervisor state and one task
- Best for: Custom workflows, learning Smithers
To specify a template:
# Interactive prompt (default)
bunx takopi-smithers init
# Non-interactive with specific template
bunx takopi-smithers init --template api-builder
bunx takopi-smithers init --template refactor
bunx takopi-smithers init --template feature
bunx takopi-smithers init --template minimalAll templates include:
- ✅ Supervisor state management (status, summary, heartbeat)
- ✅ Error handling and graceful degradation
- ✅ Resumability across restarts
- ✅ Production-ready patterns
See examples/workflows/ for the full source code of each template.
See docs/workflow-authoring.md for a complete guide to writing production-ready workflows, including:
- Schema design best practices
- State key contract requirements
- Error handling patterns
- Resumability patterns
- Testing workflows locally
- Common pitfalls and solutions
Quick example:
import { smithers, Workflow, Task, ClaudeCodeAgent } from "smithers-orchestrator";
import { drizzle } from "drizzle-orm/bun-sqlite";
// 1. Define schema
const schema = { /* your tables */ };
const db = drizzle(".smithers/workflow.db", { schema });
// 2. Update supervisor state
function updateState(key: string, value: string) { /* ... */ }
updateState("supervisor.status", "running");
updateState("supervisor.heartbeat", new Date().toISOString());
// 3. Create agents
const agent = new ClaudeCodeAgent({ model: "sonnet", env: { ANTHROPIC_API_KEY: "" } });
// 4. Define workflow
export default smithers(db, (ctx) => (
<Workflow name="my-workflow">
<Task id="my-task" output={schema.output} agent={agent}>
Your prompt here
</Task>
</Workflow>
));bun run test # Unit tests
bun run test:e2e # E2E tests
bun run test:all # Unit + E2E
bun run test:ci # Full CI pipeline (typecheck + lint + all tests)# Link for local testing
bun link
cd another-project && bun link takopi-smithers
# Build
bun run build
# Test the built package
bun run test:packageThis runs agent CLIs with the ability to read/write files and run commands in your repo. Only use in trusted repositories and environments.