UNOUNOCODE

CODING AGENT FOR THE TERMINAL

Hey Uno.

Uno reads your project, edits files and runs commands. It asks before it changes anything, runs shell commands in a sandbox, can undo every file change, and stops at a hard spending cap. It starts in milliseconds and is about 3 MB.

curl -fsSL https://unocode.motiontic.com/install.sh | sh

macOS and Linux, arm64 and x86_64. Then run uno in a project folder.

01

ASKS FIRST

Edits and shell commands wait for your say-so, unless a rule or mode allows them.

02

SANDBOXED

Shell commands cannot write outside the project, read your secrets or reach the network.

03

UNDOABLE

Every file change is recorded, so uno undo puts it back.

04

CAPPED

Spending on model calls stops at a cap you set, $5.00 unless you change it.

01 Install

Pick one. All three install the same program.

# the installer: puts uno in ~/.local/bin
curl -fsSL https://unocode.motiontic.com/install.sh | sh

# Homebrew
brew install motiontic/tap/uno

# npm (Node 18 or later)
npm i -g @motiontic/uno
  • The installer checks the download against the release's checksums, and against its signature when minisign is installed. Set UNO_VERSION=0.2.0 to install a particular version, or UNO_INSTALL_DIR to install somewhere other than ~/.local/bin. If that folder is not on your PATH, it tells you the line to add.
  • Works on macOS and Linux, on Apple Silicon, Intel, arm64 and x86_64 machines. The Linux build runs on any distribution. Windows is not supported yet.
  • On Linux the sandbox needs bubblewrap from your package manager (sudo apt install bubblewrap, sudo dnf install bubblewrap). Without it, shell commands ask before they run.

02 First run

Uno talks to the model provider with your own API key. Put the key in ~/.config/uno/.env so it works in any folder:

mkdir -p ~/.config/uno
echo 'ANTHROPIC_API_KEY=sk-ant-...' >> ~/.config/uno/.env
chmod 600 ~/.config/uno/.env

Keys are read from the environment first, then from a .env file in the folder you run uno in, then from ~/.config/uno/.env. The names are ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, and OPENAI_COMPAT_API_KEY for other servers.

cd your-project
uno                                           # open a chat
uno -p "add a test for parse_date"             # run one task and print the answer
uno --model gpt-6-luna                        # another model
uno --provider openai-compat --base-url http://localhost:11434/v1 --model qwen3

The default model is claude-sonnet-5. The provider is worked out from the model's name: Anthropic, OpenAI, Gemini, or any OpenAI-compatible server with --provider openai-compat and --base-url.

03 Commands

CommandWhat it does
unoOpen a chat. Type /help inside it for commands and keys
uno -p "<prompt>"Run one task and print the answer. A prompt piped in works too
uno --resume [id] -p "…"Continue a session; the newest one if no id is given
uno --fork <id> -p "…"Copy a session and continue the copy
uno sessionsList this folder's sessions
uno undo [--all] [--force]Put back files the model changed
uno trust [--status|--remove]Let this folder's own settings, hooks and MCP servers take effect
uno settingsShow the settings in effect and where each came from
uno mcp login|logout <name>Sign in to an HTTP MCP server in the browser, or forget the sign-in
uno mcp statusShow each MCP server and how it signs in
uno spendShow spending against the cap
uno updateInstall the newest release, when uno came from the installer
uno --version, --helpThe version, or every option

Useful options: --model, --mode (see Permissions), --allow "bash(cargo test)", --max-cost 0.50 for one run, --max-turns, --no-search, --no-memory, --image <path>, --output json and --screen dot|chat. uno --help lists them all.

04 In the chat

CommandWhat it does
/helpCommands and keys
/mode [name]Show or set the mode
/model [name]Show or set the model for the next turn
/undo [all]Put back the last file change, or all of them
/sessions, /resume, /forkEarlier conversations
/compactShorten the conversation now, keeping a summary
/costSpending in this chat and in total
/status, /context, /budgetThe agent's state, the context window, the spending
/trust, /mcp, /skills, /memoryTrust, MCP servers, skills, long-term memory
/reloadRead settings, skills, MCP servers and instructions again
/quitLeave
KeyWhat it does
EnterSend
\ then EnterA new line
Esc or Ctrl-CStop the turn
Ctrl-DLeave
↑ ↓Earlier prompts
PgUp PgDnScroll back
Ctrl-VPaste a picture from the clipboard
@path, or drag a file inAttach an image

To start a prompt with a slash, write two: //etc/hosts.

05 The screen

The chat fills the window: the conversation on the left, and on the right three cards showing what Uno is doing, how full the context window is, and what has been spent. A permission question opens at the bottom of the conversation. Choose with ← → and Enter, or press y, a or n. When you leave, the conversation is printed into the terminal, so its scrollback keeps it.

If you prefer the terminal's own scrollback, selection and search while you work, use the scrolling chat. It has the same look, and /status, /context and /budget print the cards into it. Choose it with --screen chat, UNO_SCREEN=chat, or in settings:

{ "ui": { "screen": "chat", "accent": "yellow" } }

accent is red (the default) or yellow. Windows smaller than 100 × 32 get the scrolling chat. NO_COLOR turns colour off.

06 Permissions

When a tool call needs your say-so, the chat asks. y allows it once, a for the rest of the session, n refuses. a on a file change covers every file change in the project for the session; on a shell command, it covers commands that start the same way.

ModeEditsShell commandsMeant for
defaultaskaskeveryday work; the chat starts here
accept-editsgo ahead inside the projectaskwhen you will review and undo if needed; -p starts here
planrefused, except the plan filerefusedreading and thinking only
bypassgo aheadgo aheadfolders you trust completely; deny rules still hold

Set the mode with --mode or /mode. --dangerously-skip-permissions is the same as --mode bypass. With -p there is no one to ask, so anything that needs a say-so is refused, and the run exits with code 2.

Rules are tool or tool(pattern), in allow, ask and deny lists. deny beats ask, which beats allow:

{
  "permissions": {
    "allow": ["bash(cargo test)", "bash(npm run lint)", "web_fetch(docs.rs)"],
    "deny":  ["bash(git push)"]
  }
}

The tools are read, write, edit (apply_patch on OpenAI models), grep, glob, bash, web_fetch, and MCP tools as mcp__<server>__<tool>. Files under .git/, .uno/ and .claude/ are never changed, and .env and key files are never read.

07 The sandbox

Shell commands run in the operating system's sandbox: Seatbelt on macOS, bubblewrap on Linux. Inside it, a command can write to the project and temporary folders only. It cannot read .env files or credential folders such as ~/.ssh and ~/.aws, and it has no network.

  • A command that needs more, such as installing packages, can ask to run outside the sandbox. That always asks you first.
  • An allowed command (--allow "bash(cargo test)", or a rule) runs unconfined on your machine, so keep rules narrow.
  • --no-sandbox turns the sandbox off for a run; every command then asks.

08 Spending

Every model call is priced and recorded before it can push spending past the cap. The cap is $5.00 in total unless you set another with UNO_SPEND_CAP_USD, for example export UNO_SPEND_CAP_USD=50. uno spend and /cost show where you are, and --max-cost 0.50 limits a single run.

A model missing from the price table is charged at a deliberately high rate, so the total can overstate what you really spent. Your provider's own dashboard has the real figures.

09 Sessions and undo

Every conversation is saved per folder. uno sessions lists them, uno --resume continues the newest, and uno --fork <id> continues a copy. Long conversations are shortened before they outgrow the model's window, keeping a summary.

Every file change the model makes is recorded. uno undo (or /undo) puts back the newest change, and --all puts back the whole session's. If something else changed the file since, undo stops and says so; --force puts it back anyway.

10 Settings

Settings are JSON, read from:

  • ~/.config/uno/settings.json: yours, for every project;
  • .uno/settings.json and .claude/settings.json in the project, which count only after uno trust, and stop counting when they change until you trust the folder again.
{
  "model": "claude-sonnet-5",
  "mode": "default",
  "permissions": { "allow": [], "ask": [], "deny": [] },
  "sandbox": { "enabled": true },
  "web": { "search": true },
  "memory": { "enabled": true },
  "skills": { "claude_home": false },
  "ui": { "screen": "dot", "accent": "red" },
  "hooks": {},
  "mcpServers": {}
}

uno settings prints what is in effect and which file each value came from. Data such as sessions, memory and the spend record live in ~/.local/share/uno.

11 Instructions, memory, skills

  • Instructions. AGENTS.md in the project (or CLAUDE.md where there is none) is read at the start of every session.
  • Long-term memory. Markdown notes Uno keeps between sessions, one set for all projects and one for each project, read at the start and updated as it learns. /memory shows them; --no-memory or "memory": {"enabled": false} turns memory off.
  • Skills. Folders with a SKILL.md (a name and description up top, then instructions) in .agents/skills or .claude/skills, in the project or your home folder. The model sees each skill's name and description, and reads the whole file when a task matches. /skills lists them. ~/.claude/skills is used only with "skills": {"claude_home": true}.

12 Web and images

  • Search. On Anthropic, OpenAI and Gemini models, the model can use the provider's own web search, which the provider bills at about a cent a search. The pages an answer cites are listed after it. Turn it off with --no-search or "web": {"search": false}.
  • Reading pages. web_fetch reads one public page as text. It refuses private and local addresses, and asks unless a rule covers the site: web_fetch(docs.rs), web_fetch(*.github.com).
  • Images. Attach PNG, JPEG, GIF or WebP files: drag them in, type @path, press Ctrl-V for the clipboard, or pass --image with -p. Large images are shrunk, and location data is removed before sending. The model can also read images in the project.

13 MCP servers

Declare servers under mcpServers, in the same shape as Claude Code, in your settings, the project's .mcp.json or .uno/settings.json:

{
  "mcpServers": {
    "files":  { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] },
    "github": { "type": "http", "url": "https://api.githubcopilot.com/mcp/" }
  }
}
  • However many servers you add, the model sees two small tools, one to find an MCP tool and one to call it. So adding servers costs almost nothing, and nothing starts until the model first uses one.
  • Each call asks. In the chat you can allow it once, the tool, the whole server, or every MCP tool for the session. As rules: mcp__github__create_issue, mcp__github, or mcp.
  • A project's servers load only after uno trust. Your API keys are never passed to a server.
  • Servers that sign in through the browser need uno mcp login <name> once (--no-browser prints the address instead). A browser never opens by itself during a run. Tokens are kept in ~/.config/uno/mcp-tokens.json, readable by you only, and never shown to the model.

14 Hooks

Your own commands, run at five points, on Claude Code's contract: PreToolUse, PostToolUse, UserPromptSubmit, Stop and SessionStart.

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "~/bin/no-rm.sh", "timeout": 10 }] }
    ]
  }
}
  • The hook gets the event as JSON on standard input, and runs in the project folder without your API keys.
  • Exit code 2, or "decision": "block", blocks: the tool call is not run, the prompt is not sent, or the model keeps going instead of stopping.
  • A hook can only make things stricter. A PreToolUse hook that times out or cannot start blocks the call.
  • Project hooks count only after uno trust.

15 Update and uninstall

Installed withUpdateUninstall
the installeruno updaterm ~/.local/bin/uno ~/.local/bin/.uno-installed
Homebrewbrew upgrade unobrew uninstall uno
npmnpm i -g @motiontic/unonpm rm -g @motiontic/uno

uno update checks the new release's signature with the key built into uno, and makes sure it starts before replacing the old one. Your settings and data are in ~/.config/uno and ~/.local/share/uno; delete those too to remove everything.

16 Check a download

Every release file on GitHub has a minisign signature beside it, and the public key is in minisign.pub:

minisign -V -p minisign.pub -m uno-aarch64-apple-darwin

The signed comment names the version and the machine type, for example uno 0.2.0 aarch64-apple-darwin.

uno is free to use; see the licence.