After Write(), the file offset is at the end of the written data. For request-response files (like proc/new), we need to read the result from offset 0, not from the current offset. Changed CallTool() to use ReadAt(buf, 0) instead of io.ReadAll() which uses Read() and inherits the wrong offset. Same fix was already applied to token reading in Dial(). Added TestIntegration_ToolExecution to verify the full tool execution path works end-to-end. |
||
|---|---|---|
| agent | ||
| backend | ||
| bypass | ||
| cmd | ||
| contrib/elisp | ||
| data | ||
| doc | ||
| env | ||
| format | ||
| fs | ||
| fsedsl | ||
| kde@b6a7d93d0e | ||
| lib9p | ||
| log | ||
| paths | ||
| prompts | ||
| sandbox | ||
| session | ||
| 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 |
| 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, dynamic tool dispatch, sandboxed execution, remote 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 binary |
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]
TOOLS[toolsrv.Server<br>dynamic dispatch · sandbox]
end
subgraph "LLM Backends"
OLL[Ollama]
OAI[OpenAI / OpenRouter]
ANT[Anthropic]
COP[Copilot]
KIRO[Kiro]
end
subgraph Execution
EXEC[Tool Scripts<br>loaded via ctl<br>· shell, reasoning_think<br>· file_*, lsp_*, memory_*<br>· gui_*, subagent_*]
end
TUI & SCRIPTS & ACME --> O
O --> P9
KDE & KATE & EMACS --> P9
P9 --> SESS
SESS --> AG
SESS -->|shared RPC conn| 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