ollie is a 9p-based generative agent surface
Go to file
Ollie Agent bcfdda26b4 remove dead mount/ package and olliesrv mount subcommand
The FUSE-based 9P mount (mount/) was unused — all actual mounting
uses 9pfuse via ollie-remount. Remove the package, the olliesrv mount
subcommand, and the go-fuse dependency.
2026-07-30 21:18:52 +02:00
agent agent: refresh tool definitions from server on every turn 2026-07-30 20:37:35 +02:00
backend flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
cmd remove dead mount/ package and olliesrv mount subcommand 2026-07-30 21:18:52 +02:00
contrib flatten: fix stragglers — remote server, _lib, stray go.mod files 2026-07-30 19:01:36 +02:00
dbus main.go for olliesrv 2026-07-30 21:14:26 +02:00
detach flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
doc remove remaining webui/httpgw references in docs 2026-07-30 20:22:49 +02:00
elevate flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
env flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
fs/session flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
kde@d473fb4e4c update kde submodule: fix justfile paths 2026-07-30 20:51:32 +02:00
log flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
paths flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
prompts flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
sandbox flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
session flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
skills flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
tools flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
toolsrv flatten: absorb submodules into single Go module 2026-07-30 18:57:51 +02:00
.gitignore gitignore: add __pycache__ 2026-04-29 10:17:28 +02:00
.gitmodules remove httpgw and webui; update AGENTS.md to reflect current structure 2026-07-30 20:19:32 +02:00
.gitmodules~ kf5 corrections, remote is broken 2026-07-20 10:25:43 +02:00
.plan.md agent: refresh tool definitions from server on every turn 2026-07-30 20:37:35 +02:00
AGENTS.md remove remaining webui/httpgw references in docs 2026-07-30 20:22:49 +02:00
Containerfile add remote access via TCP: Containerfile, mount subcommand, docs 2026-04-16 23:32:37 +02:00
README.md remove httpgw and webui; update AGENTS.md to reflect current structure 2026-07-30 20:19:32 +02:00
go.mod remove dead mount/ package and olliesrv mount subcommand 2026-07-30 21:18:52 +02:00
go.sum remove dead mount/ package and olliesrv mount subcommand 2026-07-30 21:18:52 +02:00
justfile main.go for olliesrv 2026-07-30 21:14:26 +02:00
pull.sh pull.sh: update for flattened repo (only . kde webui remain) 2026-07-30 19:42:21 +02:00

README.md

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 — shell scripts, tool scripts, skill files — rather than building a monolithic framework.

Getting started

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

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 scripts
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 u/complete
OLLIE_COMPLETE_MODEL=qwen3:latest         # model for u/complete
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 two Git submodules for frontends.

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
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)
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)
agents/ JSON Agent configs
prompts/ Markdown System prompt templates
tools/ Python/Bash Tool scripts (file_read, lsp_, memory_, etc.)
scripts/ Shell Session management, utilities, plumbing
doc/ Markdown Architecture docs, usage guide

Architecture

graph TB
    subgraph Frontends
        TER[Terminal<br>b / bfg / sh]
        ACME[Plan 9 acme]
        EMACS[Emacs<br>ellie.el]
        KDE[KDE<br>plasmoid / GUI / Kate<br>KRunner / tray]
    end

    subgraph "olliesrv"
        P9[9P Filesystem<br>session/ namespace]
        DBUS[D-Bus Adapter<br>org.ollie.SessionManager]
        SM[Session Manager]
        AG[agent.Agent<br>loop · compaction<br>prompt templates]
        ROUTE[Router<br>complete · generate · route]
        TOOLS[toolsrv.Server<br>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<br>file_* · lsp_* · memory_*<br>gui_* · subagent_*]
        REMOTE[ollie-remote<br>via SSH]
        RTOOL[Remote Tools]
    end

    TER & 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.

# 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:

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:

# 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.

# 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 executable scripts in ~/.config/ollie/tools/. Each one declares its metadata — JSON schema, documentation, concurrency class — in header comments. No server restart needed. No MCP server. No protocol. Just a file with a header.

# 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 header:

#!/usr/bin/env bash
# args_json: {"type":"object","properties":{"pattern":{"type":"string"}},"required":["pattern"]}
# ollie:prompt
# ## file_glob
# Find files by glob pattern.
# ollie:end

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 → s/sh or any frontend
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 a script 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 — 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