# Rules for agents

Rules are standing instructions for the AI agents that work on your machines, like a repo's
`CLAUDE.md` or `AGENTS.md`: "never restart postgres", "this is production: ask before changing
anything", "use uv, not pip". You write them once; every agent that touches the machine gets them.

There are two kinds, and an agent gets both:

- **Account rules** apply to every machine in your account.
- **Machine rules** apply to one machine, after the account's.

## Where they apply

| Where | What happens |
|---|---|
| **MCP** (`ssh mcp@`, HTTPS MCP) | the agent gets the rules; with `required`, its first change is refused until it calls `ack_rules` |
| **API keys and SDKs** | the same: with `required`, a change answers `409 rules_unread` until the key acknowledges |
| **SSH commands and file transfers** (`ssh web-1@… 'cmd'`, scp, sftp: how agents on your computer use a machine) | the same, per SSH key: with `required`, the first command or transfer is refused (exit 77, the rules on stderr) until the key runs `ssh rules@… ack web-1 <version>`; advisory rules are printed once per version |
| **Agents inside the machine** (Claude Code, Codex in a shell there) | they read `/root/AGENTS.md`, which 639 keeps up to date (see *Inside the machine*) |
| **Interactive shells** (`ssh web-1@…` at a terminal, the app) | a person at a keyboard: shown the rules when the shell opens, never refused |

Only people in your account write rules (viewers can read them, not change them). Agents over MCP
and API keys can read them (`get_rules`) and acknowledge them, never change them.

**The rules lock.** An agent on your computer has your SSH key, so it can do what `ssh rules@` can.
Over `ssh rules@` rules can be made, made stricter, or reworded at the same level, but lowering
them, turning them off or deleting them is done in the app only (like turning delete protection
off). Owners and admins get a warning whenever rules change outside the app (rewording can still
weaken them, so read it), when an attempt to loosen them there is refused, and when rules are
loosened in the app.

**What rules can't do.** They're instructions, checked at the door: an agent that has acknowledged
them can still ignore them, and `ssh -tt` with commands piped into the shell looks like a person
at a terminal (it gets the rules, but isn't stopped). For anything that must hold, use the
controls that enforce it: delete protection, internet off or sites by name, team roles.

## How strictly

Each set of rules has an enforcement level:

| Level | What agents get |
|---|---|
| `advisory` | the rules, with their first response about the machine (once per MCP session, once per SSH key and version); nothing is refused |
| `required` | the first change to the machine is refused until the agent acknowledges the rules, naming the version it read: once per MCP session, once per API key or SSH key. Over MCP and the API reading is never refused; over SSH every command and transfer waits for the acknowledgement, reads included |
| `off` | nothing: the rules are kept, but not shown |

Account rules also go into the agent's instructions when it connects, so it has them from the start.

When you edit rules, agents get the new version: with `required`, every agent acknowledges again.
An acknowledgement by an API key or SSH key also lapses after 30 days.

## What it costs

Rules go into the agent's context, so they cost tokens and time:

- Each session reads the rules once per machine it touches: about 1 token per 4 bytes. 2 KB of
  rules is about 500 tokens a session.
- `required` adds one extra call per machine per session.

Keep them short and specific. The app shows each set's size and token estimate as you type.

## Inside the machine

Agents that run *inside* a machine (Claude Code, Codex and others in a shell there) read
`/root/AGENTS.md`. 639 keeps that file in step with the machine's rules:

- If there's no `/root/AGENTS.md`, or it's the one 639 wrote, it's replaced with the current rules,
  and `/root/CLAUDE.md` links to it. If you have your own `CLAUDE.md`, a line pointing to the
  rules is added to the end of it, once.
- If you have your own `/root/AGENTS.md`, it's never overwritten. The rules go to
  `/root/.639/AGENTS.md`, and one line pointing there is added to the end of yours (and of your
  `CLAUDE.md`), once.
- The file is brought up to date whenever the machine wakes, and at once when you edit the rules
  of an awake machine. A sleeping machine isn't woken for it. New and forked machines get theirs
  when they first start.
- Delete the rules and 639's file and pointer lines are removed; your own text stays.
- Edit the rules in the app or with `ssh rules@`. Changes made to the file inside the machine are
  overwritten.

## Setting rules

- **In the app:** a machine's page has **Rules…**; account rules are under **Settings** (`r`).
  `e` edits, `tab` changes the level, `ctrl+s` saves.
- **From a terminal**, from a file:

  ```sh
  ssh rules@shell.639cloud.com set web-1 --required < rules.md
  ssh rules@shell.639cloud.com set account --advisory < team-rules.md
  ssh rules@shell.639cloud.com show web-1        # what agents get: account + machine
  ssh rules@shell.639cloud.com history web-1     # earlier versions, who wrote them
  ssh rules@shell.639cloud.com ack web-1 <version>  # what an agent runs after reading them
  ```

  Lowering, turning off and deleting rules is done in the app.

- **Not through the API.** API keys are what agents and scripts use, so they can read rules
  (`GET /v1/machines/{name}/rules`) and acknowledge them, but never change them. With `required`
  rules, a change through an API key is refused with `409 rules_unread` until that key
  acknowledges them (`POST /v1/machines/{name}/rules/ack` with the `version` it read). The SDKs
  raise `RulesUnread`, with the text in `.rules` and its `.version`, and have `ack_rules(version)`.

Up to 8 KB of Markdown per set, and the 20 latest versions are kept for 30 days. Deleting a machine
deletes its rules; account rules stay.

## An example

```md
# web-1: production API

- This is production. Don't restart services or reboot between 08:00 and 20:00 UTC.
- Never run database migrations here; they go through CI.
- Logs are in /var/log/api/. Read them before changing anything.
- Leave a note (add_note) saying what you changed and why.
```
