BlockingReadMode had the same 512-byte truncation bug: it returned EOF on offset>0 before the full content was delivered. Now caches content on the fid like normal reads. StreamMode is separated into its own path since it has fundamentally different semantics (each Tread blocks for the next chunk, no caching). |
||
|---|---|---|
| cmd | ||
| contrib/elisp | ||
| data | ||
| doc | ||
| env | ||
| format | ||
| fsedsl | ||
| kde@b6a7d93d0e | ||
| lib9p | ||
| log | ||
| paths | ||
| tools/lsp | ||
| toolsrv | ||
| .gitignore | ||
| .gitmodules | ||
| .plan.md | ||
| AGENTS.md | ||
| Containerfile | ||
| README.md | ||
| go.mod | ||
| go.sum | ||
| justfile | ||
| pull.sh | ||
README.md
ollie
Ollie is an AI agent runtime. A single binary (olliesrv) exposes agent sessions
over a single surface: a 9P2000 filesystem. The core is deliberately minimal;
capabilities come from composing small pieces — tool executables, skill files,
metadata sidecars — rather than building a monolithic framework.
Building
git clone --recurse-submodules https://git.lneely.de/lkn/ollie.git
cd ollie
just
Requires just:
cargo install just
See doc/usage.md for usage instructions.
Configuration
Backends: ~/.config/ollie/backends.conf
# Default backend for new sessions
backend = openrouter
[openrouter]
key = sk-or-v1-...
model = qwen/qwen3-235b-a22b
[anthropic]
key = sk-ant-...
model = claude-sonnet-4-20250514
[ollama]
host = http://localhost:11434
model = qwen3:latest
[kiro]
# key auto-detected from Kiro CLI if unset
Each section configures a backend. The session selects which backend to use via the backend top-level setting or per-agent backend= in cfg. See data/backends.conf for the full template.
Everything lives under $XDG_CONFIG_HOME/ollie/ (default: ~/.config/ollie/) — tools in tools/, memory in memory/, agents in agents/, prompts in prompts/, skills in skills/.
What you can do
| Capability | How |
|---|---|
| CLI | o — unified namespace CLI: read, write, ls, ctl, prompt, tui, env, generate |
| Terminal TUI | o tui — tmux layout, no widgets |
| One-shot LLM | o generate "explain monads" or echo "prompt" | o generate |
| Run an agent | Create a session + agent via 9P — then connect with any frontend (ellie, KDE (GUI/KRunner/Kate), o tui) |
| Remote execution | Set remote=user@host in session config |
| Background processes | Pass "background": true to any tool — runs with no timeout, output auto-injected, lifecycle tied to session |
| Parallel execution | Non-conflicting tool calls within a turn run in parallel (scope-based conflict scheduling) |
| Agents | Write a JSON config in data/agents/ with agent prompt in data/prompts/ |
| Tools | Drop an executable + .meta in ~/.config/ollie/tools/ — load at runtime via /tool_load |
| Domain skills | Load markdown skill modules at runtime |
Repository layout
Single Go module with one Git submodule (kde).
| Directory | Language | Description |
|---|---|---|
agent/ |
Go | Agent loop, history, prompt resolution, context compaction |
backend/ |
Go | LLM providers (Anthropic, OpenAI, Ollama, Gemini, Copilot, CodeWhisperer) |
toolsrv/ |
Go | Tool server client library (9P client for toolsrv) |
cmd/toolsrv/ |
Go | Tool execution server (separate 9P server, sandboxed execution) |
tools/lsp/ |
Go | LSP bridge daemon + client library (gopls, clangd, intelephense) |
session/ |
Go | Session lifecycle, config, persistence |
fs/ |
Go | 9P filesystem tree (EDSL-declared namespace, ctl dispatch) |
fsedsl/ |
Go | Filesystem declaration EDSL (generic, reusable) |
bypass/ |
Go | Bypass broker (sandbox escape approval) |
sandbox/ |
Go | Landlock sandbox config |
lib9p/ |
Go | 9P protocol library + native C client |
cmd/olliesrv/ |
Go | The main server binary (session/agent 9P namespace) |
cmd/toolsrv/ |
Go | Tool execution server (spawned by olliesrv, separate 9P server) |
cmd/ollie-9p/ |
Go | 9P client CLI |
cmd/ollie-remote/ |
Go | Remote execution binary |
kde/ |
C++/Qt6 | KDE plasmoid, GUI, Kate plugin, KRunner (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
graph TB
subgraph "Frontends (all use o / ollie-9p)"
TUI["o tui<br>(tmux + o read/ctl)"]
KDE[KDE GUI<br>ollie-9p native client]
KATE[Kate plugin]
EMACS[Emacs<br>ellie.el · ollie-9p]
ACME[Plan 9 acme]
SCRIPTS[Shell scripts<br>o read · o ctl · o write]
end
subgraph "o CLI"
O["o<br>path resolution · ctl dispatch<br>prompt REPL · TUI composition"]
end
subgraph "olliesrv"
P9[9P Filesystem<br>session/ namespace]
SESS[session.Session<br>tool server conn · persistence]
AG[agent.Agent<br>loop · compaction<br>prompt assembly]
end
subgraph "toolsrv (separate process)"
TOOLS[9P Filesystem<br>ctl · tools · proc/]
EXEC[Tool Scripts]
end
subgraph "LLM Backends"
OLL[Ollama]
OAI[OpenAI / OpenRouter]
ANT[Anthropic]
COP[Copilot]
KIRO[Kiro]
end
TUI & SCRIPTS & ACME --> O
O --> P9
KDE & KATE & EMACS --> P9
P9 --> SESS
SESS --> AG
SESS -->|9P over Unix socket| TOOLS
AG -->|streaming| OLL & OAI & ANT & COP & KIRO
TOOLS --> EXEC
olliesrv exposes the agent runtime over a single surface: a 9P2000 filesystem.
o is the CLI layer that all text-based frontends build on — it handles path
resolution, context, and ctl dispatch. The KDE GUI and Kate plugin use ollie-9p
(the native 9P client) directly for performance. For a deep dive into the
filesystem, see doc/9p.md.
Credits
- Plan 9 from Bell Labs — for an interesting system
- @9fans — for the Plan 9 port
- Suckless — for articulating good software development principles
- @simonfxr — for a solid agent baseline to "borrow" from
- @aws — for a solid open-source agent implementation
License
GPLv3