Inspired by pi-mono, Karl uses a layered monorepo:
karl/
├── packages/
│ ├── karl-providers/ # LLM provider abstraction
│ ├── karl-core/ # Agent loop, tool execution
│ ├── karl-tools/ # Built-in tool implementations
│ └── karl-cli/ # CLI interface, volley scheduler
└── plugins/ # Example custom tools
Clean abstraction over OpenAI, Anthropic, OpenRouter, Ollama, vLLM. Swap providers without touching agent code.
The agent loop: parse response → execute tools → feed result → repeat. No UI concerns.
Default tools as a separate package. Users can replace entirely or extend.
The user-facing binary. Volley scheduler, progress display, config loading.
Lockstep versioning: All packages share the same version. Bump together, publish together.
- Language: TypeScript (Bun runtime for speed)
- Build: esbuild for fast bundling
- Binary: Bun's single-file compiler
- Testing: Vitest, skip LLM tests in CI
- TUI: Differential rendering for flicker-free updates
- Speed over features — Fast startup, minimal deps
- Unix philosophy — One job, compose with pipes
- Minimal tools — 4 core, extend via plugins
- No state — Each run is fresh
- Transparent — Show tools, tokens, cost
- Extensible — Skills, hooks, custom tools