# ollie Ollie is an AI agent runtime. A single binary (`olliesrv`) exposes agent sessions over two surfaces: a **9P2000 filesystem** (the canonical interface) and a **D-Bus service** (`org.ollie.SessionManager`). Both are thin adapters over the same core — the agent loop, tool dispatch, sandboxing, and multi-backend routing. Choice of surface is per-deployment: 9P for its Unix composability, D-Bus for desktop integration, or both. The core is deliberately minimal. Capabilities come from composing small pieces — tool executables, skill files, metadata sidecars — rather than building a monolithic framework. ## Getting started ```sh git clone --recurse-submodules https://git.lneely.de/lkn/ollie.git cd ollie just ``` Requires [just](https://github.com/casey/just): ```sh cargo install just ``` See [doc/USAGE.md](doc/USAGE.md) for usage instructions. ## Configuration ### Environment: `~/.config/ollie/env` ``` OLLIE_BACKEND=openai # ollama | openai | anthropic | copilot | kiro (default: ollama) OLLIE_OLLAMA_URL= # base URL for Ollama (default: http://localhost:11434) OLLIE_OPENAI_URL=https://openrouter.ai/api OLLIE_OPENAI_KEY=sk-or-... OLLIE_ANTHROPIC_KEY=sk-ant-... OLLIE_COPILOT_TOKEN=... OLLIE_KIRO_TOKEN=... # bearer token or sqlite:// path (auto-detected from Kiro CLI if unset) OLLIE_MODEL=qwen/qwen3-235b-a22b OLLIE_TOOLS_PATH=~/.config/ollie/tools # directory for tool executables + .meta files OLLIE_MEMORY_PATH=~/.config/ollie/memory # directory for memory files OLLIE_ELEVATE_SOCKET=${XDG_RUNTIME_DIR}/ollie/elevate.sock OLLIE_COMPLETE_BACKEND=ollama # backend for code completion OLLIE_COMPLETE_MODEL=qwen3:latest # model for code completion OLLIE_ENABLED_BACKENDS=openrouter,kiro # backends available for routing (comma-separated) OLLIE_ROUTE_BACKEND=ollama # backend for the /route classifier OLLIE_ROUTE_MODEL=qwen3:8b # model for task routing ``` Shell environment variables take precedence over the env file. ## Repository layout Single Go module with one Git submodule (kde). | Directory | Language | Description | |-----------|----------|-------------| | `agent/` | Go | Agent loop, history, hooks, prompt resolution, commands | | `backend/` | Go | LLM providers (Anthropic, OpenAI, Ollama, Gemini, Copilot, CodeWhisperer) | | `toolsrv/` | Go | Tool server, registry, sandboxed execution, remote execution | | `tools/builtin/` | Go | Built-in tool handlers (shell, reasoning, tool/skill registry) | | `tools/lsp/` | Go | LSP bridge daemon + client library (gopls, clangd, intelephense) | | `session/` | Go | Session lifecycle, config, persistence | | `fs/session/` | Go | 9P filesystem tree for session namespace | | `dbus/` | Go | D-Bus adapter (`org.ollie.SessionManager`) | | `detach/` | Go | Background process management | | `elevate/` | Go | Elevation broker (privilege escalation) | | `mount/` | Go | FUSE-based 9P mount for network transparency | | `sandbox/` | Go | Landlock sandbox config | | `cmd/olliesrv/` | Go | The main binary | | `cmd/ollie-9p/` | Go | 9P client | | `cmd/ollie-remote/` | Go | Remote execution binary | | `kde/` | C++/Qt6 | KDE plasmoid, GUI, Kate plugin, KRunner, tray *(submodule)* | | `data/agents/` | JSON | Agent configs | | `data/prompts/` | Markdown | System prompt templates | | `data/tools/` | Mixed | Tool executables (scripts + compiled) + `.meta` sidecar files | | `data/skills/` | Markdown | Domain knowledge modules | | `doc/` | Markdown | Architecture docs, usage guide | ## Architecture ```mermaid graph TB subgraph Frontends ACME[Plan 9 acme] EMACS[Emacs
ellie.el] KDE[KDE
plasmoid / GUI / Kate
KRunner / tray] end subgraph "olliesrv" P9[9P Filesystem
session/ namespace] DBUS[D-Bus Adapter
org.ollie.SessionManager] SM[Session Manager] AG[agent.Agent
loop · compaction
prompt templates] ROUTE[Router
complete · generate · route] TOOLS[toolsrv.Server
dynamic registry · dispatch] SB[Landlock Sandbox] end subgraph "LLM Backends" OLL[Ollama] OAI[OpenAI / OpenRouter] ANT[Anthropic] COP[Copilot] KIRO[Kiro] end subgraph Execution LOCAL[Tool Scripts
file_* · lsp_* · memory_*
gui_* · subagent_*] REMOTE[ollie-remote
via SSH] RTOOL[Remote Tools] end ACME & EMACS -->|9P| P9 KDE -->|D-Bus| DBUS P9 --> SM DBUS --> SM SM --> AG AG --> ROUTE AG --> TOOLS TOOLS --> SB AG -->|streaming| OLL & OAI & ANT & COP & KIRO SB --> LOCAL SB -->|SSH| REMOTE --> RTOOL ``` `olliesrv` is a single binary. Which surface it exposes is a flag: | Mode | Flags | Interface | Frontends | |------|-------|-----------|-----------| | +9p +dbus | (default) | 9P filesystem + D-Bus signals | All | | +9p -dbus | `-nodbus` | 9P filesystem only | Terminal, acme, Emacs, web | | -9p +dbus | `-no9p` | D-Bus only | KDE (plasmoid, GUI, Kate, KRunner, tray) | ## 9P: everything is a file The 9P server exposes the agent runtime as a synthetic filesystem. Every session is a directory; every operation is a read or write. There is no client library, no SDK, no protocol buffer — `echo`, `cat`, `tail`, and `rm` are the API. ```sh # Create a session echo "name=worker" > /mnt/ollie/session/new # Submit a prompt echo "fix the bug in main.go" > /mnt/ollie/session/worker/agent/0/prompt # Stream the response tail -f /mnt/ollie/session/worker/agent/0/chat # Check state cat /mnt/ollie/session/worker/agent/0/state # One-shot generation (no session needed) exec 3<>/mnt/ollie/generate; echo 'explain monads' >&3; cat <&3; exec 3>&- # Route a task to the best model exec 3<>/mnt/ollie/route; echo 'redesign the auth system' >&3; cat <&3; exec 3>&- # → backend=kiro model=claude-sonnet-4-20250514 ``` ### Network transparency 9P is a network protocol. Mount the agent from any machine: ```sh 9pfuse 'tcp!server:5640' /mnt/ollie ``` No SSH tunneling, no port forwarding, no API gateway. One mount and every session, every tool, every config value is accessible as if local. ### Shell composability Because operations are file I/O, they compose with the full Unix toolkit: ```sh # Fan out a prompt to all agents for s in /mnt/ollie/session/*/agent/*/prompt; do echo "run tests" > "$s"; done # Wait for all agents to finish for s in /mnt/ollie/session/*/agent/*/statewait; do cat "$s" > /dev/null; done # Grep all agent plans grep -r "TODO" /mnt/ollie/session/*/plan # Monitor costs paste /mnt/ollie/session/*/agent/*/cost ``` Pipe agents into `awk`. Filter with `grep`. Schedule with `cron`. Orchestrate with a 10-line shell script instead of a framework. ### Plan 9 patterns - **`/net/dns` pattern** — `/complete`, `/generate`, `/route` are stateless per-fid: write a request, read back the result - **`ctl` files** — control operations (stop, kill, rename, compact) are writes to a control file, not method calls - **Blocking reads** — `statewait` blocks until state changes, replacing event subscriptions with a simple `cat` - **Multiplexing** — multiple clients mount the same server simultaneously, each with an independent view through per-fid state ## D-Bus: desktop integration The D-Bus interface (`org.ollie.SessionManager`) is embedded in `olliesrv` (enabled by default, or exclusively via `-no9p`). It provides typed method calls and real-time signals. ```sh # Create a session dbus-send --session --dest=org.ollie.SessionManager --type=method_call --print-reply \ /org/ollie/SessionManager org.ollie.SessionManager.CreateSession \ string:"$PWD" string:"" string:"" string:"default" string:"" string:"" # Submit a prompt dbus-send --session --dest=org.ollie.SessionManager --type=method_call \ /org/ollie/SessionManager org.ollie.SessionManager.Submit \ string:"SESSION_ID" string:"fix the bug" # Read state dbus-send --session --dest=org.ollie.SessionManager --type=method_call --print-reply \ /org/ollie/SessionManager org.ollie.SessionManager.GetState string:"SESSION_ID" ``` ### Signals D-Bus signals push events without polling: - **`ChatUpdated`** — new chat output (session_id, offset, text) - **`StateChanged`** — transition notifications - **`SessionCreated` / `SessionKilled` / `SessionRenamed`** — lifecycle events - **`ProcessDetached` / `ProcessExited`** — background process events GUI frontends subscribe once and react — no timers, no file watches, no busy loops. ### KDE integration - **Plasmoid** — embed an agent chat widget in the Plasma panel - **Kate plugin** — inline AI assistance in the text editor - **KRunner** — launch prompts from the desktop search bar - **System tray** — status indicator and quick actions - **Standalone GUI** — full-featured Qt6 chat application ## Tool registry: dynamic native tools Tools are executables in `~/.config/ollie/tools/`. Each one has a `.meta` sidecar file declaring its JSON schema, documentation, concurrency class, and tier. No server restart needed. No MCP server. No protocol. Just a file with metadata. ```bash # Discover all available tools cat session/{id}/tools # Load one into your session — becomes a native callable function echo file_glob | 9p write session/{id}/tools # The model sees it as a first-class tool on the next turn. ``` The `.meta` file (`file_glob.meta`): ```json { "description": "Find files by glob pattern, sorted by mtime (newest first).", "args": {"type":"object","properties":{"pattern":{"type":"string"}},"required":["pattern"]}, "tier": "cold", "readOnly": true } ``` Everything is sandboxed by default via Landlock. Tools that need to escape request elevation explicitly (`"elevated": true`). ## What you can do | Capability | How | |---|---| | **Run an agent** | `olliesrv` → any frontend (ellie, KDE, acme) | | **Remote execution** | Set `remote=user@host` in session config | | **Multi-agent** | `subagent_spawn` from within a session, or shell scripts | | **Code completion** | `u/complete` from acme, or read/write `/complete` | | **One-shot LLM** | Write to `/generate`, read back the response | | **Task routing** | Write to `/route`, read back `backend=X model=Y` | | **Background jobs** | Detach via `shell({"elevated":true, "detach":true})` | | **Custom tools** | Drop an executable + `.meta` in `$OLLIE_TOOLS_PATH` | | **Custom agents** | Write a JSON config in `agents/` | | **Domain skills** | Write a markdown file in `skills/` | ## Credits - [Plan 9 from Bell Labs](https://9fans.net) — for an interesting system - [@9fans](https://github.com/9fans) — for the Plan 9 port - [Suckless](https://suckless.org) — for articulating good software development principles - [@simonfxr](https://github.com/simonfxr) — for a solid agent baseline to "borrow" from - [@aws](https://github.com/aws/amazon-q-developer-cli) — for a solid open-source agent implementation ## License GPLv3