OneLoop

A local-first coding agent.
Runs on your own machine by default. One loop, five tools, zero config.

core idea

One Agent Loop

Think → call tools → feed results back → repeat.
No plugins, no hooks, no middleware.

User prompt
Model thinks
Tool calls
Model thinks
Response

Loops until the model stops calling tools. All calls in a single turn run in parallel.

models

Any Model

A local model by default — no key, no account, nothing leaving the box.
Reach a hosted one only when you ask for it.

A provider is an endpoint — one URL, one credential, one connection pool. Credentials may be absent, an API key, or a renewable subscription grant. Its models get short aliases: qwen, chatgpt, flash. /model switches which one answers for the session.

tools

Five tools

read File contents
write Create or overwrite
edit Search-and-replace
bash Shell commands
elisp Live Emacs state

elisp evaluates bounded expressions in a running Emacs server, exposing unsaved buffers, windows, diagnostics, and process output. Load the bundled emacs skill before use.

Reachable, but not tools: skill returns a playbook for the model to follow — prompt engineering, not an action. web is OpenRouter's, executed server-side.

skills

Skills

Markdown playbooks the model loads on demand.
Not in the system prompt — pulled in only when needed.

~/.oneloop/skills/code-review.md
.oneloop/skills/changelog.md
.oneloop/skills/migration.md

The model sees names + descriptions at startup.
It calls skill("name") when the task matches — no user action needed.

reliability

Append-only sessions

Every message, tool call, and result is appended to a JSONL file.
No mutation, no corruption.

.oneloop/sessions/2025-07-11.jsonl
.oneloop/sessions/2025-07-11-001.jsonl
reliability

No compaction

Nothing is summarized. Nothing is silently dropped.
A session is what was said, in order, until you clear it.

No context window is configured anywhere — the server is the
authority on what fits, and it says so by saying no.

When it stops fitting, OneLoop says so and names the fix:
/clear, or a model with a larger window.

Summarizing a thread to keep it alive trades accuracy for length
on your behalf. /clear is the same move, made deliberately.

reliability

Resilience

Retry with fallbackRetries 3× on transient failures, then offers another model; a rejected request fails at once
Bounded waitsConnections and finite responses time out; an active stream may run long, but a stalled one cannot
Parallel toolsMultiple calls execute concurrently
Output truncationLarge outputs trimmed before re-entering context
Stop anywhereCtrl+C stops cleanly; session preserved
AGENTS.mdLoaded as system prompt if present
skills/Playbooks loaded on demand via the skill tool
stats

Codebase

LanguageFilesLines
Rust245,645
HTML1439
Markdown81,022
Total337,106
get started

Quick start

# 1. Start the local model (no key, nothing leaves the box)
./ols

# 2. Interactive REPL
./ol

# Reach a hosted model only if you want one
./ol login openrouter
./ol login openai  # ChatGPT Plus/Pro

# One-shot
./ol "explain this codebase"

# Pipe into it
git diff | ./ol "summarise these changes"