agentleFS
steerlabssteerlabs/opensteer/AGENTS.md

opensteer

AGENTS.md204 starsChanged 6 days agoMITView on GitHub

Opensteer turns a person's computer into an agent workstation they steer from their phone. A Host (apps/host, with its own PostgreSQL) runs on their computer. Runners drive the coding agents they already pay for (Claude Code, Codex, Grok, Antigravity, Muse Code, Cursor, OpenCode, Pi), plus browsers, apps and shells. Web, desktop (Electron) and mobile (Expo) clients connect to it locally or from anywhere. It's an early alpha. 1. It runs on the person's computer. Their files, accounts, credentials and agent…

  • Reads credentials
  • Installs packages
  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository9 other files it gives its agents.

The file

Show its rules and text

We split this AGENTS.md into the rules it gives an agent

19 rules. About 0 are common, 12 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈12

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Leaving things running: Stop every server, database, emulator, adb server and capture loop you start, including after a failure.

    line 81
  2. Very specific:

    Agents: If a person can do it, decide whether agents should reach it through the tool catalog.

    line 97
  3. Distinctive:

    Reverse states: If you added a way in, add the way out and a way to see it.

    line 105
  4. Very specific:

    Use the Node and pnpm versions in package.json.

    line 112
  5. Very specific:

    Before pushing, run pnpm check:changed --base origin/main and the focused test or journey that proves the behavior.

    line 135
  6. Distinctive:

    Test what a person would notice breaking: access and authority rules, wire contracts, persistence and migrations, engine protocol …

    line 139
  7. Distinctive:

    Test at one layer: the cheapest one that fails without the fix, with real collaborators where they're cheap.

    line 146
  8. Distinctive:

    Every test guards something specific, runs quickly and isn't a duplicate.

    line 151
  9. Very specific:

    Never weaken an assertion or lengthen a timeout to get green.

    line 158
  10. Very specific:

    Wait on the thing itself: await the event or promise, use vi.waitFor with a condition, or use fake timers.

    line 161
  11. Distinctive:

    If one blocker has eaten about 15 minutes, report the evidence, your hypothesis and your next step instead of grinding.

    line 169
  12. Distinctive:

    When you split a request across agents, each works on its own branch in its own worktree and opens no PR.

    line 180
  13. Very specific:

    After pushing, call watch_pull_request and end your turn.

    line 188
  14. Distinctive:

    Don't narrate control flow, list fields, methods, flags or constants, keep file catalogs, or append history (PR summaries, evidence logs, …

    line 210
  15. Distinctive:

    Default to no comment. Write one only for a constraint, an external quirk or an invariant the code can't show: one line where you can, four …

    line 213
  16. Distinctive:

    Don't restate names or signatures, narrate steps, record history or explain the fix you just made.

    line 215
  17. Distinctive:

    When a documented decision changes, rewrite or delete the old text.

    line 217
  18. Distinctive:

    Don't commit implementation plans, research notes, reports or agent scratch files.

    line 226
  19. Distinctive:

    Keep this file short. Document a contract or non-obvious reason once, next to its owner, and link to it instead of repeating it.

    line 276

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Opensteer

Opensteer turns a person's computer into an agent workstation they steer from their phone. A Host (apps/host, with its own PostgreSQL) runs on their computer. Runners drive the coding agents they already pay for (Claude Code, Codex, Grok, Antigravity, Muse Code, Cursor, OpenCode, Pi), plus browsers, apps and shells. Web, desktop (Electron) and mobile (Expo) clients connect to it locally or from anywhere. It's an early alpha.

What we never compromise on

  1. It runs on the person's computer. Their files, accounts, credentials and agent sessions stay there. Hosted pieces (the Account service and Connect in apps/control-plane) only help devices find and reach that computer; they never hold the person's work. There is no cloud-hosted product.
  2. Fast on a phone, even on a weak connection. People attach over cellular data. Watch bytes on the wire, round trips before the first screen, and redraws while text streams. pnpm bench:mobile-network measures attach on slow links.
  3. Every surface. Web, desktop and mobile (iOS and Android), plus enrolled computers and Agent Phones. A feature that works on one surface and is missing on the others is unfinished.
  4. Secrets stay secret. Credentials, saved passwords, pairing codes, push tokens and signing material never reach logs, wire payloads they don't need to be in, or the repo.

A note from Tim

I like ambitious ideas, simple systems and software that feels obvious. Don't preserve complexity because it already exists, and don't add machinery because it looks architecturally impressive. Understand the real constraint, then find the smallest design that makes the correct behavior unsurprising. Measure twice, cut once, and don't build what isn't needed yet. Fight scope creep, and honor what the person asked for, minimally and realistically.

Most work here is done by agents, many at once on one shared Mac, often steered from a phone. Treat everything below as strong defaults, not law: the person you're working with can override any of it. If a rule fights the task in front of you, say so plainly and get sign-off before breaking it.

Words

  • you: the agent reading this. Tim: the founder, who approves the changes listed under Pull requests. person: someone using Opensteer.
  • Host: the server in apps/host. Deployment: one Host and everything it owns. A Personal Deployment is single-user and loopback-only, running on the person's own computer; an Account-attached Deployment is a server.
  • Runner: the process that runs agents, browsers, integrations, messaging and shells on a machine. Computer: one Runner identity enrolled in a Deployment, with a fixed grant of modules it may offer.
  • Workspace: a shared space of Threads and tabs with its own membership. Each person has a Main Workspace.
  • Thread: a durable conversation and its native agent history. Its role is conversation or work; the UI calls a work Thread a task. Chat is the Main Workspace's home Thread, still named home / homeThreadId in code and on the wire. Run: one turn of an agent on a Thread.
  • Request: something a Run needs from a person, such as an approval, an answer or a sign-in. The UI shows it as "Needs you".
  • Engine: an agent CLI a Runner drives, through packages/harness*.
  • Agent Phone: an Android phone that the apps/agent-phone app turns into a computer agents can use.
  • Stable and Beta: update channels of the one desktop app, chosen in its Settings. Beta gets every main build; Stable gets Beta builds Tim promotes.

Ways to hurt yourself

  1. Touching the live install. ~/Library/Application Support/Opensteer, ~/Opensteer and any older Opensteer Beta folders hold Tim's real installed app, with its databases and credentials. Never point dev, tests or scripts at them, and never migrate, repair or delete anything there.
  2. Killing by pattern. Many agents and dev stacks share this Mac. Never pkill -f, killall or kill a PID found by matching a name or path. Stop only processes you started, by the PID you captured.
  3. Driving the real screen. Anything that drives the screen, keyboard, windows or Electron runs in a disposable VM (pnpm test:vm), never on the host. Emulators and USB phones have one owner at a time.
  4. Handling key material. Signing certificates, notarization keys and release credentials are Tim's. Agents never read, export or rotate them.
  5. Leaving things running. Stop every server, database, emulator, adb server and capture loop you start, including after a failure. They take phones, ports and screen capture away from everyone else.

Hit every surface

The most common defect is a change that works on the path you tested and is missing everywhere else. Before calling a change done, walk this list and say which entries applied:

  • Clients. Web, desktop and mobile reach the Host through @opensteer/client (packages/client). It has no Node APIs; platform capabilities come in through ports.
  • Host API. A browser-facing capability goes in hostApi, with matching handlers, scope and mock behavior. Domain mutations use commands.dispatch.
  • Agents. If a person can do it, decide whether agents should reach it through the tool catalog. Model-facing text has behavioral evals in evals/agent-tools.
  • Deployments and channels. Personal and server Deployments; the Stable and Beta update channels (Releases).
  • Connections. Same computer, private network, Connect, and a weak cellular link. Several devices on one Deployment at once (Connections).
  • Reverse states. If you added a way in, add the way out and a way to see it. A one-way door is a bug.
  • Guidance. Does the change make a doc, skill or this file wrong? Apply Documentation.

Developing

Use the Node and pnpm versions in package.json. Local setup also needs Go and a running Docker daemon.

pnpm install --frozen-lockfile
pnpm setup:local          # check prerequisites, start local services, write .env
pnpm dev                  # start the development stack
pnpm exec vitest run <files>            # inner loop; skips native helper builds
pnpm test:integration -- <file>         # one real-PostgreSQL integration file
pnpm test:vm -- --mobile bash scripts/test-macos-journeys.sh  # macOS GUI journeys in a VM
pnpm engines              # shipped engine pins against their latest releases
pnpm test:engines         # drive the shipped engines on real accounts (costs money)
pnpm build:agent-phone    # build the Agent Phone APK into the web and desktop builds
pnpm test:agent-phone     # Agent Phone setup and use on an Android emulator
pnpm desktop:install-local  # signed local Mac build for feedback

Step-by-step procedures (running journeys, testing on devices, releases, debugging infrastructure) live as skills in .agents/skills/, also reachable as .claude/skills/.

Verifying

  • Before pushing, run pnpm check:changed --base origin/main and the focused test or journey that proves the behavior. Do not run repo-wide checks: no pnpm check, pnpm test or full pnpm test:integration unless Tim asks. CI owns the full suite.
  • Test what a person would notice breaking: access and authority rules, wire contracts, persistence and migrations, engine protocol translation, races, and the logic a fix changed. Leave out tests for what types already guarantee, trivial logic, copy text, smoke runs, tests that only mirror a mock's calls, callback wiring, and markup rendered from props. Purely visual bugs (spacing, color, alignment, a layout shift) get before/after captures as their proof, not a UI test.
  • Test at one layer: the cheapest one that fails without the fix, with real collaborators where they're cheap. Don't repeat the case in a wrapper, at each call site, or in web and mobile copies of the same logic. Add an end-to-end journey only when the bug only shows end to end: one per user-facing flow, not per edge case.
  • Every test guards something specific, runs quickly and isn't a duplicate. Extend an existing case before adding one. Deleting duplicate or useless tests is maintenance, but never drop the only coverage of a past real bug or a security property without moving it somewhere cheaper.
  • Fix bugs at the root, with a regression test that fails first. Before changing ownership, wire contracts or cross-process architecture, get one review of the smallest design, then build it.
  • Never weaken an assertion or lengthen a timeout to get green. Skipped is not passed. Fix a flaky test at the root, or quarantine it in tests/quarantine.json with a reason (flaky tests).
  • Wait on the thing itself: await the event or promise, use vi.waitFor with a condition, or use fake timers. No sleeps, polling loops or retry. Every wait on something the test set up gets a deadline well inside the test timeout and a message saying what never happened. An unbounded wait burns the whole timeout, and in integration files a timeout fails every later test in the file.
  • Pure-logic Swift runs on the host with swift test. VM journeys run after merge or on request, never as a pre-merge gate. Engine bumps need pnpm test:engines (AI engines).
  • If one blocker has eaten about 15 minutes, report the evidence, your hypothesis and your next step instead of grinding.

Pull requests

  • Work in your own worktree. One request is one PR on steerlabs/opensteer, with a conventional title (fix:, feat:, docs:, refactor:, test:, chore:). It includes whatever it takes to land: a bug the change exposes, a flaky test blocking its CI, a tooling problem in the way. Say so in the body. Split only when Tim asks or part of it needs his approval.
  • When you split a request across agents, each works on its own branch in its own worktree and opens no PR. You merge their branches into one PR branch and open one PR.
  • Push when the change is ready for review, not after every edit. Every PR and every push runs CI on one shared queue of 60 jobs, so a dozen small PRs or pushes block everyone's checks for hours.
  • The body says what changed and why, the evidence, and any checks you couldn't run.
  • After pushing, call watch_pull_request and end your turn; you're woken on checks, comments and conflicts. Don't poll. Verify each bot finding against the source: fix real ones, and dismiss false positives with a written reason.
  • Fix failing checks on the branch, never by weakening a test. There's no batching and no up-to-date requirement. Main runs the full CI suite; fix forward or revert a red main immediately.
  • You may squash-merge your own PR once the required Check is green and Greptile has no unresolved P0 or P1 finding. PRs that touch security, signing, release workflows or credentials wait for Tim's approval.

Documentation

Most code changes need no documentation change: agents can read the code.

  • docs/ holds what an agent would get wrong, or couldn't cheaply find, by reading the code and tests: decisions and their reasons, constraints that span components, processes or releases, security and privacy properties, traps, and facts that live outside the repo. Before adding a paragraph, ask what someone would get wrong without it. If the code answers it, leave it out.
  • Each area's notes are one file in docs/, named for the area. Open the one your change crosses when you reach it; there is no reading list to finish before you start.
  • Don't narrate control flow, list fields, methods, flags or constants, keep file catalogs, or append history (PR summaries, evidence logs, dates, commit hashes). Link to the source instead of describing or copying it.
  • Default to no comment. Write one only for a constraint, an external quirk or an invariant the code can't show: one line where you can, four at most. Don't restate names or signatures, narrate steps, record history or explain the fix you just made; the PR carries that. Finish changes without TODOs.
  • When a documented decision changes, rewrite or delete the old text. Don't append a second account.
  • Procedures for running, testing, debugging or releasing are skills in .agents/skills/<name>/SKILL.md, not docs.
  • Guidance that disagrees with the code is a bug: fix it or remove it in the same change.

Plans and work artifacts

  • Don't commit implementation plans, research notes, reports or agent scratch files. Keep working material outside the checkout.
  • A merged PR is the implementation record. Don't keep a second plan, checklist or status file in the repository.

How it works

Clients call the Host over typed RPC (packages/protocol) and follow a Workspace channel of durable events, resuming from their last position after a reconnect. The Host owns application records in PostgreSQL (packages/database): authentication, Workspaces, Threads, Requests and the Thread Inbox, which queues, steers or records messages between Threads. It assigns Runs to Runners. Native browser data stays on its owning computer (profile authority). A Runner connects to its Host, advertises the modules its grant allows, and runs engines through harnesses, plus browser sessions (apps/browser-runtime) and messaging channels (apps/channel-runtime). The desktop app bundles a Personal Host with PostgreSQL, Node and cloudflared, a Runner, and signed native helpers for macOS app control and Passwords.

Where code lives

AreaEntry points
Deployment server and hosted Account serviceapps/host, apps/control-plane
Web, Electron and Expo clientsapps/web, apps/desktop, apps/mobile
Agent execution and auxiliary servicesapps/runner, apps/browser-runtime, apps/channel-runtime
Android app that makes a phone a computerapps/agent-phone (Kotlin), packages/agent-phone-setup
Domain types, wire contracts and persistencepackages/core, packages/protocol, packages/database
Shared client, scheduling and engine contractspackages/client, packages/orchestration, packages/harness
Agent tool-use behavioral evalsevals/agent-tools
Repository tooling and cross-package guardsscripts, tests

Taste

  • The Host is authoritative. It decides access, ownership and grants when it acts. Clients derive what to show from what the Host returns and never add an access rule of their own; a client check that can disagree with the Host is a bug.
  • TypeScript and Zod. Parse untrusted data at boundaries, and avoid framework abstractions over them. Named exports, except where a framework requires a default. No any. Production as unknown as casts belong only at third-party SDK boundaries; tests may use them for partial fakes.
  • Cross-cutting utilities go in packages/shared, under concern-specific subpaths; engine lifecycle helpers go in packages/harness. The duplicate-helper guard catches copies.
  • Build Node apps through nodeApp; see its packaging contract. Keep library entry points in package.json exports, and expose an app barrel only when another app embeds it.
  • Keep this file short. Document a contract or non-obvious reason once, next to its owner, and link to it instead of repeating it.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.