Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mote

a very small agent

mote is a terminal agent in one file of stdlib Python. No SDK, no pip, no wheels, no Node — just mote.py, an API key, and any machine with Python ≥ 3.7 on it.

It was born on a revived 2009 Dell Inspiron Mini 1012 (Intel Atom N450, 1GB RAM, 32-bit antiX Linux). Current agentic CLI tools ship as x64/arm64 native binaries on top of heavyweight runtimes — that netbook can run none of them. It turns out the agent itself doesn't need any of that: the wire protocol is just HTTPS and server-sent events, and the whole loop fits in ~900 lines of urllib. If a machine can open a TLS connection, it can host an agent.

The model backend is the Anthropic Messages API — bring your own key.

$ python3 mote.py
mote · claude-opus-4-8 · /home/user
a very small agent. /help for commands. acting without approval prompts (--safe to change).

❯ why does wifi drop after suspend?
· thinking
· tool: bash (dmesg | grep -i -E 'wlan|brcm' | tail -20)
· tool: web_search (brcmsmac suspend resume wifi drop)
· 6 results
Your Broadcom BCM4313 uses brcmsmac, which is known to lose
firmware state on resume. Quick fix now:  sudo modprobe -r brcmsmac
&& sudo modprobe brcmsmac.  Permanent fix: add a systemd
suspend hook — want me to write it?

❯ yes
· tool: write_file (/etc/systemd/system/wifi-resume.service)
· tool: bash (systemctl enable wifi-resume.service)
Done — the module now reloads automatically after every resume.

What you get

  • The agent loop: streaming responses, model reasoning rendered dim as it arrives, tool use, retries with backoff on 429/5xx/529, broken-stream recovery.
  • Client tools that act on your machine: bash, glob, grep, read_file, edit_file (exact-string replace), write_file.
  • Server-side web tools: web_search and web_fetch execute on the API provider's infrastructure — web lookup with zero local code and zero RAM cost, which matters when you have 1GB of it.
  • Prompt caching wired in properly: a stable cache breakpoint over tools+system and moving breakpoints over recent turns, so long sessions mostly bill at the ~0.1× cached-input rate.
  • Context management: past ~150k input tokens, old tool outputs are automatically elided (also /trim on demand).
  • Cost visibility: /usage shows tokens, cache hit rate, web searches, and an estimated dollar total, live.
  • Hardware-aware by default: at startup mote detects cores, RAM, arch, and terminal width and tells the model what it's living in, so it prefers head/grep over dumping files, distrusts fat install paths on 32-bit userlands, and keeps output narrow.

Quickstart

curl -O https://raw.githubusercontent.com/asystemoffields/mote/main/mote.py

mkdir -p ~/.config/mote
echo 'sk-ant-...' > ~/.config/mote/key      # key from platform.claude.com
chmod 600 ~/.config/mote/key

python3 mote.py

export ANTHROPIC_API_KEY=... works instead of the key file. Note this must be a pay-per-token API key from the developer console — a chat-app subscription login can't authenticate against the raw API.

On a very old install, if you hit a TLS certificate error: sudo apt-get install --reinstall ca-certificates.

Usage

python3 mote.py                            # interactive, acts freely
python3 mote.py --safe                     # ask before mutating anything
python3 mote.py -p "why is the fan on?"    # one-shot prompt, then exit
python3 mote.py --model claude-haiku-4-5   # cheaper/faster model
python3 mote.py --no-web                   # disable web tools
command effect
/help command list
/auto toggle approval prompts (default: off)
/web toggle web_search / web_fetch
/model show or switch model (drops the prompt cache)
/usage token + cost totals for the session
/trim elide old tool outputs from context now
/clear forget the conversation
/quit exit (also ctrl-d)

ctrl-c interrupts a running turn and rolls the conversation back to a consistent state (no dangling tool calls).

Default model is claude-opus-4-8; claude-haiku-4-5 is the budget choice for quick sysadmin questions (mote automatically selects the older web-search variant it supports).

⚠️ Safety model

mote runs in yolo mode by default: every tool call — including rm, package installs, config edits — executes immediately, as your user, with no sandbox and no confirmation. The only guardrail is the system prompt, which instructs the model to double-check destructive commands and prefer reversible alternatives. That is a real mitigation but not a boundary.

If you want a boundary:

  • --safe (or /auto in-session) restores y/n approval prompts: read-only commands (ls, grep, df, …) run freely; anything mutating asks first. Answering with a sentence instead of y/n declines with feedback the model acts on. a = approve everything from here on.
  • Run mote as a dedicated low-privilege user, or in a container/VM, if you're pointing it at anything you care about.

Choose your own adventure — it's your machine.

Cost

You pay per token at standard API rates. The caching setup keeps long sessions cheap (a mostly-cached turn costs cents); web search bills ~$10 per 1,000 searches on top. /usage keeps a running estimate.

How it works

One file, four moving parts:

  1. SSE streaming — a hand-rolled ~80-line parser over urllib handles content_block_start/delta/stop, accumulates split tool-input JSON, and captures reasoning blocks with their signatures so they replay correctly on later turns (required by the API).
  2. The loop — send messages → if stop_reason == "tool_use", execute the tool blocks locally, append results, repeat. pause_turn, refusal, and max_tokens are handled; server-tool blocks pass through untouched.
  3. Cachingcache_control breakpoints placed on the system prompt and the last two user turns, moved each request.
  4. Tools — client tools are plain functions dispatched by name; web_search/web_fetch are declared in the request and run entirely server-side.

test/mock_api.py is a mock API server speaking the real wire format — python3 test/mock_api.py in one terminal, point mote at it with ANTHROPIC_BASE_URL=http://127.0.0.1:8399, and you can hack on the harness without spending a token. It asserts the tricky invariants (reasoning-block replay, tool-result pairing, cache-marker placement).

Compatibility

  • Python ≥ 3.7, stdlib only. Developed against 3.7-era syntax on purpose.
  • Any POSIX-ish OS with bash and grep (the bash/grep tools shell out). Linux, BSD, macOS should all work; the target audience is old and odd Linux boxes.
  • 32-bit x86, ARM, whatever — if CPython runs and TLS works, mote runs.

License

MIT

About

an agentic harness for extremely resource-constrained machines

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages