Skip to main content

neo

PyPI Python Tests License Providers

neo is a lightweight, autonomous terminal coding agent. Describe a task in plain language — neo plans the work, executes it with sandboxed tools, verifies the result, and streams everything live in your terminal.

you:  neo -p "add rate limiting to the API"
neo:  planning… wrote .neo/plans/rate-limit.md
      ✓ read src/api.py (212 lines)
      ✓ edited src/api.py (+38 −4) · ruff clean · pyright: 0 new errors
      ✓ bash: pytest -x -q → 41 passed
      done in 34s · 12 steps · $0.021

Lightweight means: one install command, no daemon, no browser, no IDE extension, no account. Plain terminal, plain JSON config.

Capabilities

Area What you get
Agent loop plan → act → verify; parallel tool calls, retries with backoff, doom-loop guard, transcript repair, auto-compaction
Tools (18) read write edit apply_patch glob grep list_dir bash (+pty) webfetch websearch todo_write todo_read task question skill plan_enter plan_exit undo
Sandbox every bash call can run in bubblewrap: user/IPC/PID/net namespaces, read-only root, hidden secrets, domain-filtered network
Providers 228 in the catalog (OpenAI / Anthropic / Gemini protocols); any OpenAI-compatible endpoint works with just a base_url
Plan mode changes are drafted to .neo/plans/, edits locked to the plan until you approve via plan_exit
Safety net permission rules (allow/ask/deny), git snapshots before risky batches, undo, session forks, worktrees
Code intelligence LSP diagnostics (pyright, tsserver, gopls, rust-analyzer, eslint) + formatters run after every edit
Extensibility MCP servers, Python plugins with hooks, .neo/commands/*.md slash commands, .neo/tools/*.py custom tools, skills

Install

Requires Python 3.10+.

Recommended — pipx (isolated, neo lands on your PATH):

sudo apt install pipx          # debian / ubuntu
pipx ensurepath
pipx install neo-agnt

Log out and back in once (or source ~/.bashrc), then verify:

neo --version

Alternative — virtualenv:

python3 -m venv ~/.neo-venv
~/.neo-venv/bin/pip install neo-agnt
ln -s ~/.neo-venv/bin/neo ~/.local/bin/neo

For the sandboxed bash tool on Linux, also install:

sudo apt install bubblewrap socat

Then set an API key — environment variable, auth.json, or neo.json (first match wins):

export ANTHROPIC_API_KEY="sk-..."
# ~/.config/neo/auth.json  (created with 0600 permissions)
{ "anthropic": "sk-..." }

Troubleshooting

error: externally-managed-environment on pip install neo-agnt

Ubuntu 24.04+ blocks system-wide pip install (PEP 668). Do not fight it — use one of the methods above:

# option 1: pipx (recommended for CLI apps)
sudo apt install pipx && pipx ensurepath && pipx install neo-agnt

# option 2: virtualenv
python3 -m venv ~/.neo-venv && ~/.neo-venv/bin/pip install neo-agnt

# option 3 (not recommended): override the guard
pip install --break-system-packages neo-agnt

neo: command not found after pipx install

pipx ensurepath adds ~/.local/bin to PATH — it takes effect on next login. Either re-login or run source ~/.bashrc, then check echo $PATH contains ~/.local/bin.

bubblewrap: command not found when running bash

The sandbox needs bubblewrap on PATH. Install it (sudo apt install bubblewrap), or set "sandbox": {"mode": "off"} in neo.json to run bash directly (you lose isolation).

No provider configured / auth errors

neo resolves keys in this order: environment variable → ~/.config/neo/auth.json → neo.json. Run neo config to see the resolved configuration and which provider it will use.

Quickstart

neo                                          # interactive TUI
neo -p "fix the failing test in test_loop"   # headless, print reply and exit
neo -p "..." --allow-all                     # headless, skip permission prompts
neo --resume                                 # continue the last session
neo init                                     # scaffold .neo/ (AGENTS.md, skills, commands, agents)
neo models                                   # list providers and models
neo config                                   # show resolved configuration
neo snapshot | neo restore | neo fork        # git snapshots and session forks

Inside the TUI, / opens the command palette, @ completes file paths, Ctrl+C cancels the running turn, and typing while the agent works queues your message for the next turn. /login stores a provider API key, /logout removes it, and /model switches models within the active provider.

Configuration

neo.json — global at ~/.config/neo/neo.json, per-project at ./neo.json or ./.neo/neo.json (project overrides global):

{
  "model": "anthropic/claude-sonnet-4-6",
  "small_model": "anthropic/claude-haiku-4-5",
  "max_steps": 40,
  "theme": "neo-dark",
  "verify_commands": ["ruff check .", "pytest -x -q"],
  "permissions": {
    "bash": { "git *": "allow", "rm -rf *": "deny", "*": "ask" },
    "edit": { "*": "ask" },
    "webfetch": { "*": "allow" }
  },
  "providers": {
    "my-proxy": { "base_url": "https://proxy.internal/v1", "api_key_env": "PROXY_KEY" }
  },
  "sandbox": { "mode": "auto", "network": "filtered" },
  "mcp": {
    "servers": {
      "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"] }
    }
  }
}

Permission rules are {tool: {pattern: allow|ask|deny}}, last match wins. neo config prints the fully resolved configuration.

Sandbox

On Linux, bash runs inside bubblewrap — the same primitive OpenAI Codex and Anthropic's sandbox runtime build on. The model sees a normal shell; underneath it gets namespaces, a read-only root, and filtered egress.

{
  "sandbox": {
    "mode": "auto",
    "network": "filtered",
    "allowedDomains": ["github.com", "*.github.com", "pypi.org", "*.pypi.org"],
    "deniedDomains": [],
    "allowWrite": ["."],
    "denyRead": ["~/.ssh", "~/.aws", "~/.gnupg"],
    "denyWrite": [".env"],
    "passEnv": ["PATH", "HOME", "LANG"],
    "allowSecrets": [],
    "privateTmp": true
  }
}
  • mode: auto (warn once, run unsandboxed if bubblewrap is missing), strict (fail loudly instead of running unsandboxed), off.
  • network: none (fully offline), filtered (isolated net namespace + domain-allowlist proxy), full.
  • Environment is cleared; only passEnv survives, and secret-looking variables are stripped unless listed in allowSecrets.

Every bash result is tagged — [sandbox] active (network=filtered) — so you always know what isolation was in effect.

Plan mode

For non-trivial work, neo drafts a plan first and locks edits to it:

you:  /plan add oauth login
neo:  wrote .neo/plans/oauth-login.md — 5 steps, 3 files
      [plan_enter] edits restricted to the plan. review, then approve.
you:  looks good, proceed
neo:  [plan_exit] approved — executing as build turn…
      ✓ edited src/auth.py …  ✓ bash: pytest → 58 passed

Plans live in .neo/plans/ as Markdown. Nothing outside the plan is touched until you approve.

Safety net

neo snapshot                  # snapshot the worktree (git tree-hash handle)
neo snapshot --list           # list snapshots
neo restore <id> --dry-run    # preview what a restore would change
neo restore <id>              # restore files from a snapshot
neo fork                      # fork the session (copy-on-write)

Snapshots are also taken automatically before risky tool batches, and the undo tool (approval-gated) rolls back the last mutation.

MCP

Add any MCP server in neo.json; its tools appear as server_tool, its prompts become slash commands:

{ "mcp": { "servers": {
  "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
  "remote": { "url": "https://mcp.internal/v1", "headers": { "Authorization": "Bearer ${MCP_TOKEN}" } }
} } }

Each server is isolated — one failing server never takes down the rest.

Plugins

Python plugins live in ~/.neo/plugins/ or <project>/.neo/plugins/. A plugin is a module exposing hooks:

# ~/.neo/plugins/notify.py
def on_tool_after(event):
    if event.tool == "bash" and event.result.is_error:
        desktop_notify("neo", f"bash failed: {event.result.output[:120]}")

hooks = {"tool.execute.after": on_tool_after}

Available hooks: tool.execute.before/after, permission.ask, chat.params, session.end. Plugins can also register their own tools.

Custom commands and tools

<!-- .neo/commands/review.md -->
---
description: review the current diff
agent: reviewer
---
Review `!git diff --stat` and leave findings on @src/.

$1/$ARGUMENTS interpolate arguments, !cmd runs shell upfront, @path injects file contents. Python tools go in .neo/tools/*.py and are loaded automatically.

Project layout

src/neo/
  agent/        autonomous loop, permissions, sessions, plans, compaction
  tools/        18 built-in tools (files, shell+sandbox, web, todos, subagents…)
  providers/    streaming clients + 228-entry provider catalog (JSON)
  sandbox/      bubblewrap argv builder, capability detection, filtering proxy
  mcp/          MCP clients (stdio, StreamableHTTP), tool/prompt discovery
  lsp/  format/ language servers + formatters wired into every edit
  vcs/          git snapshots, selective restore, forks, worktrees
  plugins/      plugin loader and hook dispatch
  commands/     .neo/commands/*.md slash-command engine
  custom_tools/ .neo/tools/*.py loader
  agents/  plan/  agent roster, per-agent toolsets, plan-mode enforcement
  tui/          Textual interface: palette, dialogs, themes, session list
  auth.py       ~/.config/neo/auth.json key store (0600)

Tests

python -m pytest          # 339 passed, 4 skipped

License

MIT. See LICENSE.

Release files for neo-agnt 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neo-agnt 0.1.2
File Size Uploaded
neo_agnt-0.1.2.tar.gz 242.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for neo-agnt 0.1.2
File Interpreter ABI Platform
neo_agnt-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 460.7 kB

Release files / neo_agnt-0.1.2.tar.gz

Download URL neo_agnt-0.1.2.tar.gz
Size 242.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c60cf33cf1510f75227ca924872f77c8e9ef6f4249f413e90881c5450f9bafdd
BLAKE2b-256 checksum
How to use checksums
2af1af071764d0adbdee45c92e9401daecaa9bfb01bdf662fc54d355f1c3bb18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / neo_agnt-0.1.2-py3-none-any.whl

Download URL neo_agnt-0.1.2-py3-none-any.whl
Size 218.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ed93ff58f00474d1f1965ad75a5902f3c777a0a67030a17ef0d4d8429cedefd
BLAKE2b-256 checksum
How to use checksums
130ade5be58a77ae5fb05991fe317a38b822fcc7c4ac4c59cc42fad4a6829502
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page