670 lines
22 KiB
Markdown
670 lines
22 KiB
Markdown
# Usage
|
|
|
|
## Server
|
|
|
|
### Start and stop
|
|
|
|
```sh
|
|
olliesrv start # start in background (daemonizes)
|
|
olliesrv fgstart # start in foreground
|
|
olliesrv stop # stop the daemon
|
|
olliesrv status # check if running
|
|
```
|
|
|
|
By default the server mounts at `$HOME/mnt/ollie`. Override with `-mount`:
|
|
|
|
```sh
|
|
olliesrv start -mount /tmp/ollie
|
|
```
|
|
|
|
### TCP listener
|
|
|
|
To also accept connections over TCP (e.g. for remote access):
|
|
|
|
```sh
|
|
olliesrv start -tcp :9564
|
|
```
|
|
|
|
### Debug logging
|
|
|
|
Log level is controlled by `OLLIE_LOG` (default: `warn`). Set to `debug` for verbose output:
|
|
|
|
```sh
|
|
OLLIE_LOG=debug olliesrv fgstart
|
|
```
|
|
|
|
Valid levels: `debug`, `info`, `warn`, `error`. Per-subsystem overrides follow the pattern
|
|
`OLLIE_<TAG>_LOG=debug` where `<TAG>` matches the logger's tag (e.g. `OLLIE_SESSION_LOG`).
|
|
|
|
The rendered context window for any session is readable at `s/{id}/context` — the exact message array sent to the backend on the last turn. Combined with `s/{id}/systemprompt`, this gives full visibility into what the model sees.
|
|
|
|
---
|
|
|
|
Examples below assume `$OLLIE` is set to the ollie mount point (default: `$HOME/mnt/ollie`).
|
|
Scripts under `s/` and `u/` are available directly via the mounted filesystem
|
|
after running `mk && mk scripts`.
|
|
|
|
## Interactive shell
|
|
|
|
`s/sh` is an interactive shell for prompting a session. It resumes the most recent
|
|
session for the current working directory by default, or creates a new one if none exists.
|
|
|
|
```sh
|
|
exec $OLLIE/s/sh # resume or create session for pwd
|
|
exec $OLLIE/s/sh -new # always start a fresh session
|
|
exec $OLLIE/s/sh -new -model qwen3:8b # fresh session with model override
|
|
exec $OLLIE/s/sh -session 1744276689123456789-2b986c # attach to a specific session
|
|
```
|
|
|
|
At the `> ` prompt:
|
|
|
|
| Input | Action |
|
|
|---|---|
|
|
| `<text>` | Submit prompt; response streams to terminal |
|
|
| `/stop` | Interrupt the current agent turn |
|
|
| `/kill` | Kill the session and exit |
|
|
| `/compact` | Compact conversation history |
|
|
| `/clear` | Clear conversation history |
|
|
| `/rn <name>` | Rename the session |
|
|
| `/cwd [path]` | Get or set working directory |
|
|
| `/agent [name]` | Get or set agent |
|
|
| `/model [name]` | Get or set model |
|
|
| `/backend [name]` | Get or set backend |
|
|
| `/models` | List available models |
|
|
| `/backends` | List available backends |
|
|
| `/usage` | Show token usage |
|
|
| `/ctxsz` | Show context size |
|
|
| `/q <text>` | Enqueue prompt for later |
|
|
| `! <cmd>` | Run shell command in session cwd |
|
|
| C-j | Insert newline (multi-line input) |
|
|
| Ctrl-C | Interrupt running turn (or exit if idle) |
|
|
|
|
`s/sh` tracks the last session per working directory in `~/.config/ollie/last-session`,
|
|
so switching directories and re-running `s/sh` resumes the right context automatically.
|
|
|
|
## One-shot queries
|
|
|
|
`s/bfg` and `s/bbg` submit a single prompt to a new session. The difference is only in
|
|
how the caller is treated: `s/bfg` blocks until the agent finishes and writes the result
|
|
to stdout; `s/bbg` returns immediately and prints the path of the session.
|
|
|
|
Both are thin wrappers around `s/b`, which is the core one-shot runner.
|
|
|
|
### s/bfg
|
|
|
|
Submit a prompt, wait for completion, print the result:
|
|
|
|
```sh
|
|
$OLLIE/s/bfg "Summarize this repo"
|
|
cat main.go | $OLLIE/s/bfg "explain this file"
|
|
$OLLIE/s/bfg -parallel 4 -keep "Write a haiku"
|
|
$OLLIE/s/bfg -backend ollama -model qwen3:8b "Explain this" < main.go
|
|
```
|
|
|
|
With `-parallel N`, N jobs run concurrently and results are printed as they complete.
|
|
|
|
### s/bbg
|
|
|
|
Submit a background job and return immediately; prints the `s/{id}` path:
|
|
|
|
```sh
|
|
$OLLIE/s/bbg "summarize the recent git log"
|
|
# /home/lkn/mnt/ollie/s/1744276689123456789-0
|
|
```
|
|
|
|
Poll for completion:
|
|
|
|
```sh
|
|
path=$($OLLIE/s/bbg "write a limerick about Go")
|
|
until [ "$(cat $path/statewait)" = "idle" ]; do :; done
|
|
tail -c +$(($(cat $path/offset) + 1)) $path/chat
|
|
```
|
|
|
|
Fan out with `-parallel N` and collect results:
|
|
|
|
```sh
|
|
paths=$($OLLIE/s/bbg -parallel 4 "draft a blog intro" < brief.txt)
|
|
for p in $paths; do
|
|
until [ "$(cat $p/statewait 2>/dev/null)" = "idle" ]; do :; done
|
|
tail -c +$(($(cat $p/offset) + 1)) $p/chat
|
|
rm -r $p
|
|
done
|
|
```
|
|
|
|
### s/cleanup
|
|
|
|
Remove all idle sessions:
|
|
|
|
```sh
|
|
$OLLIE/s/cleanup
|
|
```
|
|
|
|
Schedule regular cleanup with a cron job:
|
|
|
|
```
|
|
*/15 * * * * /path/to/mnt/ollie/s/cleanup
|
|
```
|
|
|
|
### Raw s/ access
|
|
|
|
```sh
|
|
cat $OLLIE/s/new # show the spec template
|
|
printf 'cwd=%s\n---\nSummarize this.\n' "$PWD" > $OLLIE/s/new
|
|
cat $OLLIE/s/<session-id>/cfg # state, backend, model, agent, cwd, params
|
|
cat $OLLIE/s/<session-id>/chat
|
|
rm -r $OLLIE/s/<session-id> # cancel and remove
|
|
```
|
|
|
|
Valid spec keys: `name` (auto-generated if omitted), `cwd` (required), `agent`,
|
|
`backend`, `model`.
|
|
|
|
### Generation parameters
|
|
|
|
Parameters are set in the agent config JSON and can be overridden at runtime by
|
|
writing `key=value` lines to `s/{id}/cfg`. Runtime writes take precedence over
|
|
the agent config. All are optional; omitted values use the backend's default.
|
|
|
|
| Key | Type | Description |
|
|
|---|---|---|
|
|
| `maxTokens` | int | Max output tokens (0 = no limit) |
|
|
| `maxCompletionTokens` | int | OpenAI o-series alternative to maxTokens |
|
|
| `temperature` | float | Sampling temperature |
|
|
| `topP` | float | Nucleus sampling threshold |
|
|
| `topK` | int | Top-K sampling (Anthropic, Ollama) |
|
|
| `minP` | float | Min-P sampling (Ollama) |
|
|
| `topA` | float | Top-A sampling (Ollama) |
|
|
| `frequencyPenalty` | float | Frequency penalty |
|
|
| `presencePenalty` | float | Presence penalty |
|
|
| `repetitionPenalty` | float | Repetition penalty (Ollama) |
|
|
| `reasoning` | int | Thinking budget in tokens (Anthropic); 0 = disabled |
|
|
| `reasoningEffort` | string | `low`, `medium`, `high` (OpenAI o-series) |
|
|
| `includeReasoning` | bool | Include reasoning in response (OpenRouter) |
|
|
| `responseFormat` | string | `json_object`, `text`, etc. (OpenAI) |
|
|
| `stop` | string | Comma-separated stop sequences |
|
|
| `verbosity` | string | Output detail level (internal, not sent to API) |
|
|
|
|
Example agent config:
|
|
|
|
```json
|
|
{
|
|
"prompt": "You are a helpful assistant.",
|
|
"temperature": 0.7,
|
|
"topP": 0.95,
|
|
"reasoning": 10000,
|
|
"stop": ["\n\n"]
|
|
}
|
|
```
|
|
|
|
Example runtime override:
|
|
|
|
```sh
|
|
echo "temperature=0.3" > $OLLIE/s/mysession/cfg
|
|
echo "topP=0.9" > $OLLIE/s/mysession/cfg
|
|
```
|
|
|
|
### Sandbox
|
|
|
|
Every `execute_code` invocation runs inside a Landlock sandbox configured by `~/.config/ollie/sandbox/<name>.yaml`. The sandbox wraps each invocation as a new command, so config changes (e.g. granting access to an additional directory) take effect on the next `execute_code` call without restarting the server or session.
|
|
|
|
## AI pipelines
|
|
|
|
`s/bfg` writes to stdout and composes naturally with Unix pipes. When both args
|
|
and stdin are present, args are treated as the instruction and stdin as the content:
|
|
|
|
```sh
|
|
echo "write a haiku about filesystems" | $OLLIE/s/bfg | wc -w
|
|
cat error.log | $OLLIE/s/bfg "what is causing this?" | $OLLIE/s/bfg "suggest a fix"
|
|
$OLLIE/s/bfg "list 5 blog post ideas" | grep -v "^$" | head -3 | $OLLIE/s/bfg "expand the best one"
|
|
```
|
|
|
|
`u/optimize` is a worked example — it generates N candidate prompts in parallel via
|
|
`s/bfg -parallel N`, then judges them with a second `s/bfg` call to return the best:
|
|
|
|
```sh
|
|
$OLLIE/u/optimize -n 3 -cm qwen/qwen3-8b -jm anthropic/claude-opus-4-6 "explain recursion"
|
|
```
|
|
|
|
Progress goes to stderr; pipe the optimized prompt with content into a subsequent call:
|
|
|
|
```sh
|
|
prompt=$($OLLIE/u/optimize "translate this to Spanish" 2>/dev/null)
|
|
cat document.txt | $OLLIE/s/bfg "$prompt"
|
|
```
|
|
|
|
## Code completion (acme)
|
|
|
|
`u/complete` provides AI ghost-text code completion for [acme](http://acme.cat-v.org)
|
|
windows. It reads the text before and after the cursor (dot), sends it to a lightweight
|
|
model, and opens the suggested insertion in a new window.
|
|
|
|
### Setup
|
|
|
|
Two environment variables are required (set them in `~/.config/ollie/env` or export
|
|
them in your shell):
|
|
|
|
```
|
|
OLLIE_COMPLETE_BACKEND=ollama
|
|
OLLIE_COMPLETE_MODEL=qwen3:4b
|
|
```
|
|
|
|
### Usage
|
|
|
|
From an acme window, middle-click `u/complete` in the tag (or add it to the global
|
|
tag). The script:
|
|
|
|
1. Reads up to 4000 characters before the cursor and 1000 after.
|
|
2. Finds or creates a persistent copilot session for the current working directory.
|
|
3. Submits a fill-in-the-middle prompt to the configured model.
|
|
4. Opens the completion in a new `ollie/complete` window.
|
|
|
|
Override model or backend per invocation with flags:
|
|
|
|
```sh
|
|
u/complete -model phi-4-mini -backend ollama
|
|
```
|
|
|
|
### Session reuse
|
|
|
|
One copilot session is maintained per working directory. The session ID is derived
|
|
deterministically from the cwd, so concurrent completions in the same directory share
|
|
a single session and never spawn duplicates. The conversation history is cleared after
|
|
each completion to keep context fresh.
|
|
|
|
If a session enters a failed state, it is automatically killed and recreated on the
|
|
next invocation.
|
|
|
|
### Model recommendations
|
|
|
|
Completion models should be small and fast — the goal is insertion text, not reasoning.
|
|
Good choices for `OLLIE_COMPLETE_MODEL`:
|
|
|
|
| Model | Backend | Notes |
|
|
|---|---|---|
|
|
| `qwen3:4b` | ollama | Use with `/no_think` or a `PARAMETER stop <think>` Modelfile to disable reasoning |
|
|
| `phi-4-mini` | ollama | ~3.8B, strong at code, no thinking mode |
|
|
| `llama3.1:8b` | ollama | Straightforward, no chain-of-thought overhead |
|
|
| `openai/gpt-4o-mini` | openai | Fast and cheap via OpenRouter |
|
|
|
|
Avoid "thinking" models (Qwen3 8B+ with default settings, DeepSeek-R1) — they burn
|
|
tokens on internal reasoning chains that add latency without improving completion
|
|
quality.
|
|
|
|
## Multi-agent workflows
|
|
|
|
Two patterns cover most multi-agent use cases: ephemeral subagent delegation for
|
|
independent parallel subtasks, and persistent concurrent sessions for workflows that
|
|
need coordination or long-lived state.
|
|
|
|
### Subagent delegation
|
|
|
|
`subagent_spawn` is a tool script that forks N ephemeral agents with a shared prompt,
|
|
waits for all to finish, and returns their results concatenated in submission order. It
|
|
is the right tool when work can be split into independent subtasks that don't need to
|
|
talk to each other.
|
|
|
|
The agent invokes it via `execute_code`:
|
|
|
|
```json
|
|
{
|
|
"steps": [{"tool": "subagent_spawn", "args": "-n 3 summarize this module"}]
|
|
}
|
|
```
|
|
|
|
Or from a shell step:
|
|
|
|
```sh
|
|
subagent_spawn -n 3 "review this diff for security issues"
|
|
subagent_spawn -n 1 -agent reviewer -cwd /path/to/repo "check for style violations"
|
|
```
|
|
|
|
**Flags**
|
|
|
|
| Flag | Description |
|
|
|---|---|
|
|
| `-n N` | Number of subagents to spawn (default: 1) |
|
|
| `-agent A` | Agent config for each subagent |
|
|
| `-backend B` | Backend override |
|
|
| `-model M` | Model override |
|
|
| `-cwd DIR` | Working directory for subagents (default: `pwd`) |
|
|
| `-keep` | Do not remove sessions after collecting results |
|
|
|
|
With `-n 1` (the default) the result is just the single agent's output. With `-n > 1`
|
|
results are separated by `=== {id} ===` headers.
|
|
|
|
### Concurrent sessions
|
|
|
|
For workflows where multiple long-lived agents work in parallel and hand off to each
|
|
other, the mechanism is direct prompt passing via the filesystem. Each agent has a
|
|
`prompt` file that accepts writes; writing to it queues a new turn, so a busy agent
|
|
will not drop a message.
|
|
|
|
**Create named sessions:**
|
|
|
|
```sh
|
|
printf 'name=writer\ncwd=%s\n' "$PWD" > $OLLIE/s/new
|
|
printf 'name=reviewer\ncwd=%s\n' "$PWD" > $OLLIE/s/new
|
|
```
|
|
|
|
**Send a prompt and read the response:**
|
|
|
|
```sh
|
|
# Queue a prompt on a named session
|
|
printf '%s\n' "Draft a design doc for the new cache layer." > $OLLIE/s/writer/prompt
|
|
|
|
# Wait for the turn to finish (statewait blocks until state changes)
|
|
until [ "$(cat $OLLIE/s/writer/statewait)" = "idle" ]; do :; done
|
|
|
|
# Read only the new output (offset marks the byte position after the user prompt)
|
|
tail -c +$(($(cat $OLLIE/s/writer/offset) + 1)) $OLLIE/s/writer/chat
|
|
```
|
|
|
|
**Key files per session:**
|
|
|
|
| File | Mode | Description |
|
|
|---|---|---|
|
|
| `prompt` | write | Queue a new turn; writes are enqueued if agent is busy |
|
|
| `statewait` | read (blocking) | Blocks until state changes; returns new state |
|
|
| `state` | read | Current state: `idle`, `running`, `failed: <reason>` |
|
|
| `chat` | read | Full conversation transcript |
|
|
| `context` | read | Full message history as JSONL |
|
|
| `offset` | read | Byte position in `chat` immediately after the last user prompt |
|
|
| `plan` | r/w | Scratch space for agent planning |
|
|
| `prompt.prev` | read | The last submitted prompt |
|
|
| `env` | read | Session environment variables |
|
|
| `cost` | read | Cumulative cost in USD (if reported by backend) |
|
|
|
|
Reading `offset` before writing `prompt`, then extracting `chat[offset:]` after the
|
|
turn completes, isolates exactly the model's response for that turn.
|
|
|
|
### Predefined workflows
|
|
|
|
When coordination logic is known in advance, a shell script can drive the entire
|
|
workflow. Named sessions make routing unambiguous; `statewait` eliminates polling
|
|
races. No external coordinator process is needed — the script is the coordinator.
|
|
|
|
The following example implements a write → review → test loop. The developer agent
|
|
revises until the reviewer approves, then the tester validates:
|
|
|
|
```sh
|
|
#!/bin/sh
|
|
cwd=${1:?usage: $0 <cwd>}
|
|
cd $OLLIE
|
|
|
|
printf 'name=developer\nagent=developer\ncwd=%s\n' "$cwd" > s/new
|
|
printf 'name=reviewer\nagent=reviewer\ncwd=%s\n' "$cwd" > s/new
|
|
printf 'name=tester\nagent=tester\ncwd=%s\n' "$cwd" > s/new
|
|
|
|
# Send a prompt to a named session and return the model's response.
|
|
# Opens statewait before writing the prompt so the idle baseline is captured
|
|
# before the agent starts processing. offset marks the byte position after the
|
|
# user prompt in chat; everything from that position to EOF is the model response.
|
|
send() {
|
|
sid=$1; shift
|
|
exec 3< s/$sid/statewait
|
|
printf '%s' "$*" > s/$sid/prompt
|
|
while true; do
|
|
read -r _ <&3 && { exec 3<&-; break; }
|
|
exec 3<&-
|
|
[ "$(awk -F= '/^state=/{print $2}' s/$sid/cfg)" != "idle" ] && break
|
|
exec 3< s/$sid/statewait
|
|
done
|
|
until [ "$(awk -F= '/^state=/{print $2}' s/$sid/cfg)" = "idle" ]; do sleep 0.5; done
|
|
tail -c +$(($(cat s/$sid/offset) + 1)) s/$sid/chat
|
|
}
|
|
|
|
reply=$(send developer "Implement a function that parses a JSON config file.")
|
|
|
|
while true; do
|
|
review=$(send reviewer "Review the following code. Reply LGTM if ready, or PTAL with feedback.
|
|
|
|
$reply")
|
|
|
|
if ! printf '%s' "$review" | grep -qi "LGTM"; then
|
|
reply=$(send developer "Revise based on this feedback:
|
|
|
|
$review")
|
|
continue
|
|
fi
|
|
|
|
result=$(send tester "Test the following code. Reply Approved if all tests pass, or Rejected with details.
|
|
|
|
$reply")
|
|
|
|
if printf '%s' "$result" | grep -qi "Approved"; then
|
|
printf '%s\n' "$reply"
|
|
break
|
|
fi
|
|
|
|
reply=$(send developer "Fix the following test failures:
|
|
|
|
$result")
|
|
done
|
|
|
|
rm -r s/developer s/reviewer s/tester
|
|
```
|
|
|
|
The agents have no knowledge of each other — the script holds all the routing logic.
|
|
A human can intervene at any time by writing directly to any session's `prompt`.
|
|
Each agent can use a different `agent=`, `backend=`, or `model=` — set them in the
|
|
`s/new` spec lines.
|
|
|
|
### Self-generating workflows
|
|
|
|
Because agents have access to `execute_code`, a session can write and run a workflow
|
|
script without any human involvement. Given a task description and knowledge of the
|
|
filesystem layout, an agent can decompose the work, create the named sessions, write
|
|
the coordination script to a temp file, and execute it — all in a single turn.
|
|
|
|
The architecture documents (`ARCHITECTURE.md`, `USAGE.md`) and tool descriptions
|
|
(available via `s/{id}/t/idx`) are the agent's reference. No additional scaffolding is needed.
|
|
|
|
## Store federation
|
|
|
|
`OLLIE_TOOLS_PATH` and `OLLIE_TRANSCRIPT_PATH` are ordinary filesystem paths. Because
|
|
`olliesrv` speaks 9P and any remote instance can be mounted locally via `9pfuse`, these
|
|
vars can point at remote directories with no code changes — the OS handles the proxying
|
|
transparently.
|
|
|
|
### Centralized tool distribution
|
|
|
|
Host one authoritative tool set and point all machines at it:
|
|
|
|
```sh
|
|
# On each client machine:
|
|
olliesrv mount toolserver:9564 ~/mnt/toolserver
|
|
export OLLIE_TOOLS_PATH=~/mnt/toolserver/t
|
|
```
|
|
|
|
Every agent on every host now uses the same tool scripts. Update tools in one place;
|
|
all clients pick up the change immediately.
|
|
|
|
### Centralized transcript archive
|
|
|
|
Collect transcripts from all hosts in one place:
|
|
|
|
```sh
|
|
olliesrv mount archivehost:9564 ~/mnt/archive
|
|
export OLLIE_TRANSCRIPT_PATH=~/mnt/archive/tr
|
|
```
|
|
|
|
Sessions started after this change write their transcripts to the remote host.
|
|
Existing sessions are unaffected.
|
|
|
|
Both vars can be combined. Set them in `~/.config/ollie/env` for persistence:
|
|
|
|
```
|
|
OLLIE_TOOLS_PATH=~/mnt/toolserver/t
|
|
OLLIE_TRANSCRIPT_PATH=~/mnt/archive/tr
|
|
```
|
|
|
|
## HTTP gateway
|
|
|
|
`ollie-httpgw` is an HTTP gateway that translates REST-style HTTP calls into 9P
|
|
filesystem operations. It lets any HTTP client — including the web UI, `curl`, or
|
|
custom scripts — interact with `olliesrv` without a 9P client library.
|
|
|
|
### Build
|
|
|
|
```sh
|
|
mk httpgw # from repo root
|
|
# or
|
|
cd httpgw && mk
|
|
```
|
|
|
|
Produces `~/bin/ollie-httpgw`.
|
|
|
|
### Start and stop
|
|
|
|
Like `olliesrv`, the gateway supports daemon management:
|
|
|
|
```sh
|
|
ollie-httpgw start # start in background (daemonizes)
|
|
ollie-httpgw fgstart # start in foreground
|
|
ollie-httpgw stop # stop the daemon
|
|
ollie-httpgw status # check if running
|
|
```
|
|
|
|
### Run (legacy)
|
|
|
|
For backwards compatibility, running without a subcommand starts in foreground:
|
|
|
|
```sh
|
|
ollie-httpgw # connect to local olliesrv via namespace; listen on :8080
|
|
ollie-httpgw -listen :9090 # different port
|
|
ollie-httpgw -net tcp -addr host:9564 # connect to remote olliesrv over TCP
|
|
```
|
|
|
|
**Flags**
|
|
|
|
| Flag | Default | Description |
|
|
|---|---|---|
|
|
| `-listen` | `:8080` | HTTP listen address |
|
|
| `-service` | `ollie` | 9P service name in the local namespace |
|
|
| `-net` | `` | Network type (`tcp`, `unix`); empty = use namespace |
|
|
| `-addr` | `` | 9P server address; required when `-net` is set |
|
|
|
|
The gateway must be able to reach `olliesrv`. For a local server started with
|
|
`olliesrv start`, the defaults work as-is. For a remote server started with
|
|
`olliesrv start -tcp :9564`, use `-net tcp -addr remotehost:9564`.
|
|
|
|
### HTTP → 9P mapping
|
|
|
|
Each HTTP method maps to a 9P operation:
|
|
|
|
| Method | 9P operation | Example |
|
|
|---|---|---|
|
|
| `GET` | read file / list dir | `GET /s/idx` |
|
|
| `POST` | write to file | `POST /s/new`, `POST /s/{id}/prompt` |
|
|
| `DELETE` | remove | `DELETE /s/{id}` |
|
|
| `PATCH` | rename (JSON `{"name":"..."}`) | `PATCH /s/{id}` |
|
|
| `HEAD` | stat (metadata in `X-9p-*` headers) | `HEAD /s/{id}` |
|
|
|
|
The full API is described in `httpgw/openapi.json` and served live at
|
|
`GET /openapi.json`.
|
|
|
|
### Key endpoints
|
|
|
|
```sh
|
|
GET /s/idx # list sessions (JSON array)
|
|
GET /s/{id}/cfg # session config (key-value JSON)
|
|
GET /s/{id}/chat # conversation transcript (plain text)
|
|
POST /s/new # create session (JSON: {cwd, backend, model, agent})
|
|
POST /s/{id}/prompt # submit prompt (JSON: {prompt: "..."})
|
|
POST /s/{id}/ctl # send control command (JSON: {ctl: "stop"})
|
|
DEL /s/{id} # kill and remove session
|
|
GET /backends # list available backends
|
|
GET /a/ # agent configs
|
|
GET /s/{id}/t/ # tool scripts
|
|
GET /m/ # memory files
|
|
GET /sk/ # skills
|
|
```
|
|
|
|
```sh
|
|
# Examples with curl:
|
|
curl http://localhost:8080/s/idx
|
|
curl -X POST http://localhost:8080/s/new \
|
|
-d '{"cwd":"/home/user/project","backend":"anthropic"}'
|
|
curl -X POST http://localhost:8080/s/mysession/prompt \
|
|
-d '{"prompt":"summarize the recent commits"}'
|
|
```
|
|
|
|
## Web UI
|
|
|
|
The web UI is a Preact single-page application that talks to `ollie-httpgw`. It
|
|
provides session management, a chat interface, and a basic 9P filesystem browser
|
|
in the browser.
|
|
|
|
### Build
|
|
|
|
```sh
|
|
mk webui # from repo root
|
|
# or
|
|
cd webui && npm run build
|
|
```
|
|
|
|
Requires Node.js and npm. Output lands in `webui/dist/`.
|
|
|
|
### Serve
|
|
|
|
The `dist/` folder is a static site. Serve it with any HTTP server and proxy the
|
|
API paths to `ollie-httpgw`:
|
|
|
|
**nginx example:**
|
|
|
|
```nginx
|
|
server {
|
|
listen 3000;
|
|
root /path/to/ollie/webui/dist;
|
|
index index.html;
|
|
|
|
location / { try_files $uri /index.html; }
|
|
|
|
location ~ ^/(s|a|m|t|sk|backends|openapi\.json)(/|$) {
|
|
proxy_pass http://localhost:8080;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Python one-liner (local testing only):**
|
|
|
|
```sh
|
|
cd webui/dist && python3 -m http.server 3000
|
|
# API calls will fail — use the Vite dev server instead for local testing
|
|
```
|
|
|
|
### Development
|
|
|
|
Vite's dev server proxies API paths to httpgw automatically:
|
|
|
|
```sh
|
|
# Terminal 1: gateway
|
|
ollie-httpgw -listen :8080
|
|
|
|
# Terminal 2: dev server (hot-reload, proxied API)
|
|
cd webui && npm run dev
|
|
# Open http://localhost:5173
|
|
```
|
|
|
|
The proxy configuration is in `webui/vite.config.ts` and targets `localhost:8080`
|
|
by default.
|
|
|
|
### Features
|
|
|
|
- Session list in a sidebar with state, model, backend, and cwd
|
|
- Create, rename, and kill sessions
|
|
- Send prompts; streaming via 2-second poll
|
|
- Stop a running agent
|
|
- Markdown rendering of assistant responses
|
|
- 9P filesystem browser (navigate `s/`, `a/`, `m/`, `sk/`)
|
|
- Two built-in themes: `midnight` (dark) and `acme` (Plan 9-inspired light); choice
|
|
persisted to `localStorage`
|
|
|
|
## Alternative front-ends
|
|
|
|
The 9P filesystem is the lowest level interface to ollie. All interfaces are simply wrappers around filesystem operations, and `s/sh` is the standard chat interface. Other front-ends:
|
|
|
|
- **[ellie](https://github.com/lneely/ollie-el)** — `ellie.el` is the Emacs front-end, just wire it into your `init.el` and `M-x ellie`
|
|
- **Web UI** — browser-based UI; requires `ollie-httpgw` (see above)
|
|
|
|
See each repo's README for installation and usage.
|