Skip to main content
Local Operator logo

Local Operator

An open-source AI agent that lives in your terminal and works on your machine

Plans, runs tools, browses, spawns subagents, and remembers — all from a fast terminal UI


Local Operator TUI running a real task: streamed response, an expanded tool card showing a command and its output, and a live status line

The Local Operator TUI mid-task: streamed responses, expandable tool cards, and one-line receipts for everything the agent does.


Local Operator is a terminal-native AI agent: describe what you want done and it does the work on your machine, asking before anything writes or executes. It is MIT-licensed and built to be lived in — sessions persist and resume, context compacts itself before it overflows, and the agent can schedule its own follow-ups.

📚 Table of Contents

✨ Why Local Operator

  • A real terminal UI, not a REPL. A full-screen Textual app with streamed responses, expandable tool cards, session resume, 20+ built-in themes with live preview, and a status line that tells you what the agent is doing and what it costs.
  • Sign in with the account you already have. OAuth login for OpenAI (ChatGPT), Anthropic (Claude), Kimi, xAI, Z.AI, and Qwen — or bring an API key, or run entirely offline with Ollama.
  • Approval-gated execution. Reads are automatic; writes and shell commands ask first. /approvals auto (or --yolo) opts out deliberately, per session or as a saved default.
  • An agent workforce, not just an agent. Fan work out to concurrent subagents with tool-restricted roles (a reviewer that cannot edit what it reviews), author reusable agent profiles, and save whole teams — a manager plus a roster — you launch by name with /team. Peek at, steer, pause, or cancel any worker mid-flight.
  • A session you can leave and come back to. Transcripts persist, /resume picks up where you left off, and context compaction runs itself before the window fills, so long sessions don't fall off a cliff.
  • Skills, MCP, scheduled wakes, web search, a browser tool — the agent's toolbox is broad, and everything it does leaves a visible receipt in the transcript.

🚀 Quickstart

Requires Python 3.12+.

pip install local-operator     # pipx install local-operator on Linux (PEP 668)

The install provides both local-operator and its short alias lop — the rest of this page uses lop.

Sign in to a provider (or skip this — the app tells you what's missing on first run):

lop login           # lists login-capable providers
lop login anthropic # OAuth sign-in in your browser

Then start it:

lop

That's it. Type what you want done. esc stops the agent, /help lists commands, /exit quits.

The Local Operator welcome screen with rotating tips and the composer ready for a first prompt

Prefer a fully local model? Install Ollama, pull a model, and point the agent at it:

lop --hosting ollama --model qwen2.5:14b

🖥️ A Tour of the TUI

Everything the agent does shows up as a card or a one-line receipt. Tool cards expand (enter/space) to show the full command and output; the status line tracks the current step, token usage, and cost.

When a tool call needs your sign-off, the approval prompt shows exactly what is about to run before anything touches your system:

An approval prompt showing the exact shell command awaiting user confirmation

Switching models is a picker, not a config file — /model lists every model your signed-in providers offer, with fuzzy filtering:

The /model picker with a fuzzy filter applied, showing context length and pricing per model

Ask for parallel work and the agent delegates: the subagent dock shows each worker's status, spend, and progress live, and you can open any of them to watch its transcript. (This shot also shows one of the 20+ built-in themes — /theme previews them live as you arrow through the list.)

The subagent dock in an alternate built-in theme: three concurrent workers with elapsed time, context usage, and cost per worker, above the shared todo list

Coming back later is /resume — a picker over your recent sessions, each with its title and age:

The /resume session picker listing recent conversations with titles, ages, and short ids

And /usage answers the question every agent user has: how much provider quota is left, and what the account has spent (the status line tracks the current session's cost live).

The /usage panel showing per-provider quota windows and account spend

Slash commands

/help shows the full table in-app. The highlights:

Command What it does
/model Switch model for this session; /model default saves it for new ones
/effort Show or set reasoning effort (shift+tab cycles)
/approvals Set whether tools ask first (ask/auto; add default to keep it)
/resume Pick a past conversation and continue it
/new, /clear, /reload Fresh conversation · wipe the screen · reboot the session in place
/goal, /loop Set an objective, then iterate autonomously toward it
/btw Ask a side question off the record — it never joins the conversation
/compact Compact the context now (it also happens automatically)
/usage, /context Provider quota and account spend · what's occupying the context window
/provider, /login, /logout, /accounts, /credential Manage providers and stored credentials
/search Configure web-search providers and load balancing
/team Launch a saved team: /team <name> <request> puts a manager and roster on it
/skills, /mcp List loaded skills · MCP servers
/theme, /rename Pick from 20+ built-in themes (arrows preview live) · rename the session

Keys worth knowing

  • Type while the agent works — your message is delivered at the next step as steering, no need to wait.
  • esc — stop the agent without ending the session.
  • ctrl+b — open an aside (side question) without losing what you were typing; ctrl+f promotes the aside into the conversation.
  • shift+tab — cycle reasoning effort.
  • ctrl+l — clear the transcript (history is untouched).

🔌 Providers

One agent, your choice of brain. OAuth providers sign in through the browser and use your existing subscription; API-key providers prompt once and store the key locally; Ollama runs models on your own hardware.

Provider Access
OpenAI / ChatGPT OAuth (browser or device code) or OPENAI_API_KEY
Anthropic / Claude OAuth or ANTHROPIC_API_KEY
Kimi (Moonshot) OAuth or KIMI_API_KEY
xAI / Grok OAuth or XAI_API_KEY
Z.AI (GLM) OAuth or ZAI_API_KEY
Qwen (Alibaba) OAuth (token plan) or API key
Google Gemini GOOGLE_AI_STUDIO_API_KEY
DeepSeek DEEPSEEK_API_KEY
Mistral MISTRAL_API_KEY
OpenRouter OPENROUTER_API_KEY — one key, many models
Radient RADIENT_API_KEY — automatic per-step model selection
Ollama Local, no key, no network
lop login              # list login-capable providers
lop login openai       # OAuth flow
lop login-status       # what's signed in
lop logout kimi

Legacy --hosting <name> --model <name> flags keep working, and API keys can be stored with lop credential update <KEY_NAME> (a masked prompt).

🧰 What the Agent Can Do

The agent's built-in tools, each with its own card in the transcript:

  • Run thingsbash (shell commands), eval (a persistent Python kernel: variables survive across calls).
  • Work with filesread, write, edit (surgical search/replace), glob, grep, plus lsp for Jedi-backed Python code intelligence.
  • Reach the web — load-balanced web_search across seven providers and a browser tool for pages that need rendering or interaction.
  • Stay organized — a visible todo list for multi-step work, ask to put real decisions back to you as a picker instead of a wall of text.
  • Work in the backgroundtask spawns subagents, jobs/wait/hub manage and talk to them, and wake schedules future follow-ups ("check the build again in 30 minutes").

🔎 Web search

Search works out of the box — DuckDuckGo and Tavily's keyless endpoint are enabled by default, and requests rotate across providers with automatic fallback when one is rate-limited or down:

lop search list
lop search test "Python 3.13 release notes"
lop search enable perplexity
lop search setup brave --api-key
lop search setup tavily --oauth      # official Tavily MCP server
lop search setup searxng --endpoint https://search.example.com
Provider Access Default
DuckDuckGo Credential-free Enabled
Tavily Keyless, TAVILY_API_KEY, or OAuth MCP Enabled
Perplexity Anonymous or PERPLEXITY_API_KEY Disabled
Brave BRAVE_API_KEY Disabled
Exa EXA_API_KEY Disabled
SerpApi SERPAPI_API_KEY Disabled
SearXNG Self-hosted endpoint URL Disabled

The same controls are available in-app via /search.

🤝 Subagents, agent profiles, and teams

This is where Local Operator stops being a chatbot and starts being a staff.

Subagents. Ask for parallel work and the agent fans it out into concurrent background workers, then keeps working while they run. Each worker is addressable: peek at its transcript, send it a note, ask it a question, steer it onto a different course, pause it, or resume it later — all without burning its attention on status meetings.

Roles are capability boundaries, not just prompts. A subagent launched as reviewer carries vetted review guidance and loses the tools to edit code — it can read and run tests but cannot alter what it reviews, which is what keeps a review honest. Packaged starters ship for reviewer, coder, architect, manager, designer, and scout, and you can author your own agent profiles: reusable roles and named specialists with their own instruction sets, matched to tasks by semantic routing. When a profile gives bad guidance, you fix the profile once — not every prompt that uses it.

Teams. A saved roster — a manager plus members with counts — layered with two briefs the individual agents never hard-code: a collaboration brief (how this group works together, who blocks a release) and a project brief (what product this instance owns). Swap the project brief and the same roster staffs a different product. /team lists your saved teams:

The /team picker listing the saved lopdev team

The team picker. Launch one with /team <name> <request> — the current agent becomes that roster's manager and delegates from there:

Sending a real request to a team: /team lopdev Can you implement a mobile relay functionality in lop using tailwind, shadcn

Sending a request to a team is one line — the manager breaks it down and puts the right roles on it.

Agents can also be managed from the CLI:

lop agents create "My Agent"
lop agents list
lop teams list

🧠 Skills and guides

Drop a SKILL.md (with optional reference files) into ~/.local-operator/skills/<name>/ and the agent indexes it semantically — only the skills relevant to the current turn are surfaced, and their bodies load on demand via skill://<name> reads, so your context isn't taxed by knowledge you aren't using. /skills lists what's loaded.

🔗 MCP servers

Local Operator speaks MCP over the official SDK, with lazy tool loading: servers advertise a bounded summary, and individual tool schemas enter the context only when the agent actually enables them.

lop mcp add linear --url https://mcp.linear.app/mcp --oauth
lop mcp login linear     # complete the OAuth flow
lop mcp list

Server configs are discovered from the project (.local-operator/mcp.json, .mcp.json), your home directory, and best-effort imports of Claude Code, Cursor, and VS Code configs — so servers you already configured elsewhere just show up. See docs/mcp.md for the trust model before enabling project-supplied servers.

⚙️ Headless & Server Modes

One-shot execution for scripts and automation:

lop exec "summarize the failures in ./test.log"
lop exec "long migration" --background   # detach with a log file
lop exec "audit deps" --json             # one JSON line per event

Exit code 0 on success — pipeline-friendly.

Server mode exposes the agent as a FastAPI service (used by the optional desktop UI):

pip install "local-operator[server]"
lop serve                 # http://localhost:1111, docs at /docs

Phone access — an optional mobile portal daemon lets you check on and steer sessions from your phone:

lop mobile install
lop mobile status

📦 Installation Options

The default install is deliberately small. Optional features live behind extras:

Extra Adds
server The HTTP API server (lop serve) and background scheduler
mcp Model Context Protocol client support
images HEIC/HEIF image attachment decoding
tokenizer Exact BPE token counting (estimated otherwise)
lsp Jedi-backed symbol-aware Python navigation for the lsp tool
all Everything above except lsp
pip install "local-operator[all]"    # quote it — shells glob the brackets

If you hit a feature whose extra is missing, the agent tells you which one to install instead of failing with an import error.

Nix: nix develop drops you into a reproducible dev shell via the provided flake.nix.

Docker: docker compose up -d with the provided compose file.

🔧 Configuration & Credentials

Configuration lives at ~/.local-operator/config.yml:

lop config create      # scaffold it
lop config list        # every option, with descriptions
lop config edit <key> <value>
lop config open        # open it in your editor

Commonly set values: hosting and model_name (skip the CLI flags), conversation_length / detail_length (history kept verbatim vs summarized), and tui.theme (any registered theme name — easier to set with /theme, which previews live).

Credentials are stored in ~/.local-operator/credentials.env and never echoed:

lop credential update TAVILY_API_KEY
lop credential delete TAVILY_API_KEY

OAuth tokens from lop login are stored separately and refresh themselves.

🌟 Radient Agent Hub

Radient adds two optional capabilities:

  • Automatic model selectionlop --hosting radient picks the best model per step to balance quality and cost, no --model needed.
  • Agent sharing — push your agents to the public hub, pull agents others published:
lop credential update RADIENT_API_KEY
lop agents push --name "My Agent"
lop agents pull --id "<agent_id>"     # no key needed to pull

🔒 Safety Model

  • Approval tiers. Read-only tools run automatically; anything that writes files or executes commands prompts first, showing the exact command. /approvals auto or --yolo disables prompts only when you say so.
  • Visible receipts. Every tool call leaves a card or one-line receipt in the transcript — there is no invisible action.
  • Local-first options. Run Ollama models for closed-circuit operation where nothing leaves your machine.
  • MCP trust model. Project-supplied MCP configs are treated as trusted input and warned about on first connect — see docs/mcp.md.
  • Credential hygiene. Keys live in a local credential store, are entered through hidden prompts, and are kept out of transcripts.

📝 Examples

👉 The example notebooks show real tasks completed with Local Operator, saved from live sessions:

👥 Contributing

We welcome contributions! See CONTRIBUTING.md for how to submit bug reports and feature requests, set up a development environment, and open pull requests. docs/ covers the architecture (REWRITE.md), benchmarks, and verification evidence.

📜 License

MIT — see LICENSE for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

local_operator-0.20.0.tar.gz (2.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

local_operator-0.20.0-py3-none-any.whl (2.2 MB view details)

Uploaded Python 3

File details

Details for the file local_operator-0.20.0.tar.gz.

File metadata

  • Download URL: local_operator-0.20.0.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for local_operator-0.20.0.tar.gz
Algorithm Hash digest
SHA256 ee8c0b319fa0a84d1eea5b7da0fd4471e126729ab01478f304ee367781d4e160
MD5 780da7e50ed2a149d5a542b4dd8d093a
BLAKE2b-256 05638dd9c320ebff5faad627cbd3c3f47ae48c2fdeae6b1a52fd9a7005d6a8d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for local_operator-0.20.0.tar.gz:

Publisher: publish.yml on damianvtran/local-operator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file local_operator-0.20.0-py3-none-any.whl.

File metadata

File hashes

Hashes for local_operator-0.20.0-py3-none-any.whl
Algorithm Hash digest
SHA256 86b47a8a47f048f03e1c50ebfb85cc783e97afbc1cbb0850794848a9f8a0030b
MD5 fc7215249b491d084a4fd90b36b89032
BLAKE2b-256 36b477671a95c02cc97e721ddd9a9ea33d6aa2c36530954d5f31109cf8533d64

See more details on using hashes here.

Provenance

The following attestation bundles were made for local_operator-0.20.0-py3-none-any.whl:

Publisher: publish.yml on damianvtran/local-operator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.31.0

2 files

0.30.0

2 files

0.29.0

2 files

0.28.1

2 files

0.28.0

2 files

0.27.3

2 files

0.27.2

2 files

0.27.1

2 files

0.27.0

2 files

0.26.0

2 files

0.25.4

2 files

0.25.3

2 files

0.25.2

2 files

0.25.1

2 files

0.25.0

2 files

0.24.7

2 files

0.24.6

2 files

0.24.5

2 files

0.24.4

2 files

0.24.3

2 files

0.24.2

2 files

0.24.1

2 files

0.24.0

2 files

0.23.1

2 files

0.23.0

2 files

0.22.0

2 files

0.21.0

2 files

0.20.1

2 files

This release

0.20.0 This release

2 files

0.19.2

2 files

0.19.1

2 files

0.19.0

2 files

0.18.1

2 files

0.18.0

2 files

0.17.5

2 files

0.17.3

2 files

0.17.1

2 files

0.17.0

2 files

0.16.1

2 files

0.16.0

2 files

0.15.10

2 files

0.15.9

2 files

0.15.8

2 files

0.15.7

2 files

0.15.6

2 files

0.15.5

2 files

0.15.4

2 files

0.15.3

2 files

0.15.2

2 files

0.15.1

2 files

0.15.0

2 files

0.14.2

2 files

0.14.1

2 files

0.14.0

2 files

0.13.0

2 files

0.12.1

2 files

0.12.0

2 files

0.11.4

2 files

0.11.3

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.0

2 files

0.4.9

2 files

0.4.8

2 files

0.4.7

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.8

2 files

0.3.7

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.18

2 files

0.2.17

2 files

0.2.16

2 files

0.2.15

2 files

0.2.14

2 files

0.2.13

2 files

0.2.12

2 files

0.2.11

2 files

0.2.10

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

0.0.29

2 files

0.0.28

2 files

0.0.27

2 files

0.0.26

2 files

0.0.25

2 files

0.0.24

2 files

0.0.23

2 files

0.0.22

2 files

0.0.21

2 files

0.0.20

2 files

0.0.19

2 files

0.0.18

2 files

0.0.17

2 files

0.0.16

2 files

0.0.15

2 files

0.0.14

2 files

0.0.13

2 files

0.0.12

2 files

0.0.11

2 files

0.0.10

2 files

0.0.9

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page