agentleFS
agentlab-inagentlab-in/hosted-ao/AGENTS.md

hosted-ao

AGENTS.md2 starsChanged 3 months agoApache-2.0View on GitHub

Operational guidance for coding agents working in this repository. Keep changes small, match the current rewrite architecture, and prefer the documented daemon/API boundaries over behavior from the old TypeScript implementation. From the repo root unless noted: Backend-specific checks: Frontend-specific checks: When showing or demoing frontend changes, run ao preview [url] from inside the session so the change renders in the desktop browser panel (the inspector rail's Browser tab); do not just describe it. For code entry points:

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

20 rules. About 1 is common, 9 are distinctive, and 10 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 10

    Very specific

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

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

    When showing or demoing frontend changes, run ao preview [url] from inside the session so the change renders in the desktop browser panel …

    line 44
  2. Distinctive:

    Exactly one publisher: Only the designated release conductor runs a real publish, on any channel.

    line 69
  3. Distinctive:

    Keep every change surgical and directly tied to the task.

    line 75
  4. Distinctive:

    Follow existing Go package boundaries.

    line 76
  5. Very specific:

    Keep Cobra commands in the relevant command file and table-test them in the style of backend/internal/cli/*_test.go.

    line 77
  6. Very specific:

    Use context.Context as the first argument for functions that do I/O or blocking work.

    line 81
  7. Distinctive:

    Do not add abstractions for one-off use cases.

    line 82
  8. Very specific:

    Do not store derived/display session status.

    line 92
  9. Distinctive:

    Do not treat failed/unknown runtime probes as proof a session is dead.

    line 93
  10. Distinctive:

    Do not force-delete dirty registered worktrees.

    line 94
  11. Distinctive:

    Do not modify already-merged SQLite migrations.

    line 95
  12. Very specific:

    Do not hand-edit backend/internal/storage/sqlite/gen/*.

    line 96
  13. Very specific:

    Keep generated OpenAPI/API DTO drift in mind: controller response shapes live in backend/internal/httpd/controllers/dto.go and tests may …

    line 98
  14. Very specific:

    Do not add network calls to tests unless the package already has an integration/e2e pattern for them.

    line 99
  15. Common:

    Do not commit local run state, daemon data, temporary worktrees, build outputs, or credentials.

    line 100
  16. Very specific:

    Commit openapi.yaml and frontend/src/api/schema.ts together with the Go changes.

    line 131
  17. Distinctive:

    Keep one issue per PR. If asked for separate work, create a separate branch and PR.

    line 136
  18. Very specific:

    Use conventional commit messages (feat:, fix:, docs:, test:, chore:).

    line 137
  19. Very specific:

    No AI attribution in commits or PR bodies: no Co-Authored-By: Claude...

    line 138
  20. Distinctive:

    Run the narrowest relevant tests first, then the repo/CI commands that match the touched area.

    line 140

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 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

AGENTS.md

Operational guidance for coding agents working in this repository. Keep changes small, match the current rewrite architecture, and prefer the documented daemon/API boundaries over behavior from the old TypeScript implementation.

Repo layout

  • backend/: Go rewrite of Agent Orchestrator: Cobra ao CLI, loopback HTTP daemon, services, SQLite storage, lifecycle/reaper, runtime/workspace/agent/tracker adapters, terminal mux, and tests.
  • frontend/: Electron + React supervisor wired to the daemon via the generated typed client. Treat it as a thin supervisor/UI surface; do not move daemon logic into it.
  • docs/: current architecture/status notes. Start here before changing lifecycle, CLI, agents, storage, or daemon behavior.
  • test/: external smoke/e2e assets, including the CLI fresh-install container check.
  • .github/workflows/: CI definitions. Mirror these commands locally when possible.

Commands

From the repo root unless noted:

npm run lint                         # backend go test ./... + golangci-lint v2.12.2
npm run frontend:typecheck           # frontend TypeScript check
npm run sqlc                         # regenerate backend/internal/storage/sqlite/gen from queries/schema
npm run api                          # regenerate OpenAPI spec + frontend TS types (see API contract changes below)
npx @redwoodjs/agent-ci run --all    # local workflow validation; requires Docker socket

Backend-specific checks:

cd backend
go build ./...
go test ./...
go test -race ./...
go vet ./...
go run ./cmd/ao start

Frontend-specific checks:

cd frontend
npm run typecheck
npm run build

When showing or demoing frontend changes, run ao preview [url] from inside the session so the change renders in the desktop browser panel (the inspector rail's Browser tab); do not just describe it.

Where to look first

  • README.md: current run/config/test quickstart.
  • docs/README.md: docs index.
  • docs/architecture.md: backend mental model, package layout, lifecycle/session/service boundaries, and load-bearing rules.
  • docs/STATUS.md: what is shipped on main today and what is still in flight.
  • docs/cli/README.md: intended CLI shape: thin Cobra client over daemon HTTP, never direct storage/runtime access.
  • CLAUDE.md: compatibility pointer for Claude Code; it directs agents back to AGENTS.md.

For code entry points:

  • CLI commands: backend/internal/cli/*.go; follow nearby command/test patterns before adding a new style.
  • HTTP controllers and DTOs: backend/internal/httpd/controllers/.
  • Service read/write boundaries: backend/internal/service/.
  • Domain vocabulary: backend/internal/domain/.
  • Port contracts: backend/internal/ports/.
  • SQLite queries/migrations/store: backend/internal/storage/sqlite/.
  • Generated sqlc code: backend/internal/storage/sqlite/gen/.

Distribution

  • The desktop app (GitHub Releases) is the canonical, auto-updating install path. Point users there first.
  • npm still works but is no longer recommended. 0.10.0 is the final version published to npm; the @aoagents/ao package is frozen and will not receive further updates. It remains a legacy on-ramp for users who already have ao on their PATH, where ao start fetches and opens the desktop build. Do not add features, docs, or flows that treat npm as the intended way to install AO.
  • Exactly one publisher. Only the designated release conductor runs a real publish, on any channel. Divergent artifacts from multiple publishers made the 28-29 Jul macOS incident unreadable. Use the fork dev loop for test builds. Full rule and rationale: frontend/docs/desktop-release.md, "Hard rule: exactly one publisher".
  • AgentLab publishes unsigned builds only. Releases from agentlab-in/hosted-ao must not use code-signing or notarization credentials and must not be described as signed or notarized. Preserve build provenance, checksums, updater feeds, and artifact-completeness checks; platform trust warnings are expected for these unsigned artifacts.
  • macOS ships both a .zip and a .dmg. The dmg is first install only. The zip and latest-mac.yml must keep publishing forever: electron-updater cannot install an update from a dmg. macOS differential updates are permanently disabled (full download only); see issues #3151 and #3267.

Coding conventions

  • Keep every change surgical and directly tied to the task. Avoid drive-by cleanup, broad renames, formatting churn, speculative abstractions, and architectural refactors unless the task explicitly asks for them.
  • Follow existing Go package boundaries. CLI code should call daemon HTTP routes through shared CLI client helpers; it should not open SQLite, spawn runtimes, or call adapters directly.
  • Keep Cobra commands in the relevant command file and table-test them in the style of backend/internal/cli/*_test.go.
  • Mirror existing response/request DTOs in the CLI instead of importing HTTP controller packages into CLI code, unless the package already establishes that dependency.
  • Return usage errors as usageError so CLI misuse exits 2; runtime/daemon failures should exit 1.
  • Preserve API error envelopes and request IDs when surfacing daemon errors.
  • Use context.Context as the first argument for functions that do I/O or blocking work.
  • Do not add abstractions for one-off use cases. Add helpers only when they remove duplication across real call sites.
  • Tests should cover the user-visible behavior and boundary being changed: happy path, validation/missing args, daemon error envelopes, and any destructive confirmation path.

Hard rules and boundaries

  • The daemon's primary (loopback) listener stays bound to 127.0.0.1 and unauthenticated. Do not change its bind host or add auth to it.
  • The daemon MAY run a second, opt-in LAN listener (the "Connect Mobile" feature) that binds 0.0.0.0 only while explicitly enabled, only behind the bearer-password authMiddleware, serving the app API but never the loopback-gated control routes (/shutdown, telemetry, mobile control). It is plaintext and home-network-only by deliberate decision, see docs/adr/0001-lan-listener-for-mobile.md and CONTEXT.md.
  • A permitted network-facing bind is ao vm serve in its hosted configuration, the VM gateway: a separate process from the daemon, run only on a user-owned, user-bound hosted VM (never local mode), that binds :80 and :443 for ACME/TLS, verifies the AO access token on every request before proxying to the loopback daemon, and never proxies the loopback-gated control routes (/shutdown, telemetry, mobile control); see docs/adr/0002-hosted-public-gateway.md. The daemon itself is unchanged by this: still loopback-only, still unauthenticated.
  • The only remaining permitted network-facing bind is ao vm serve in pair mode: the same separate gateway process, run only on a user-owned box the user has explicitly paired (never local mode), that binds only the HTTPS port (no :80, no ACME) and serves a persisted self-signed certificate whose SHA-256 fingerprint the user pins out of band, verifies the box's 8-character passcode (hash compared constant-time, per-source lockout) on every request before proxying to the loopback daemon, never proxies the loopback-gated control routes (/shutdown, telemetry, mobile control), and never contacts the control plane; see docs/adr/0003-pair-mode-gateway.md. Reaching a box by bare IP is in scope for this mode only, not for the hosted configuration. Pair mode is the default way to add any machine, a LAN box or a cloud VM alike, not a LAN-only carve-out: see docs/adr/0004-pairing-string-and-cloud-pair-scope.md, which reverses 0003's "cloud VM is not a supported configuration" scoping while leaving the transport itself unchanged. The daemon is unchanged by this too: still loopback-only, still unauthenticated. Do not add any other network-facing bind.
  • The CLI is a thin client. Do not port old in-process TypeScript CLI behavior that bypasses daemon HTTP routes.
  • Do not store derived/display session status. Status is derived from durable facts (activity_state, is_terminated, PR/check/comment facts) at service read time.
  • Do not treat failed/unknown runtime probes as proof a session is dead.
  • Do not force-delete dirty registered worktrees.
  • Do not modify already-merged SQLite migrations. Add a new migration instead.
  • Do not hand-edit backend/internal/storage/sqlite/gen/*; change backend/internal/storage/sqlite/queries/* or migrations and run npm run sqlc.
  • SQLite change events come from DB triggers into change_log; do not add parallel manual CDC emission from store methods unless the architecture changes explicitly.
  • Keep generated OpenAPI/API DTO drift in mind: controller response shapes live in backend/internal/httpd/controllers/dto.go and tests may assert CLI/HTTP wire compatibility.
  • Do not add network calls to tests unless the package already has an integration/e2e pattern for them. Prefer httptest, fakes, and injected dependencies.
  • Do not commit local run state, daemon data, temporary worktrees, build outputs, or credentials.
  • All app state lives under ~/.ao/hosted only. The daemon's data dir, running.json, worktrees, repos, machine.json, and the Electron supervisor's userData (Chromium cache, cookies, local/session storage, crash dumps) must resolve under ~/.ao/hosted (overridable via AO_DATA_DIR/AO_RUN_FILE). Never write to or read from ~/Library/Application Support or any other OS default app-data location. main.ts pins Electron's userData to ~/.ao/hosted/electron; do not remove that override or rely on Electron's default path. The subdirectory is deliberate: the upstream agent-orchestrator app writes its own running.json and ao.db directly under ~/.ao, and two builds sharing that directory fight over daemon discovery, the pid, the port, and a SQLite file whose goose history the other build owns. Derive the default from config.StateRootSegments() (Go) or shared/state-root.ts (renderer/main); never re-spell the path.

API contract changes

The daemon API is code-first. The OpenAPI spec and frontend TypeScript types are generated artifacts, edit the source, then regenerate.

Source files to edit:

  • backend/internal/httpd/controllers/dto.go: request/response shapes.
  • backend/internal/httpd/apispec/specgen/build.go: operation registry; add a schemaNames entry for any new named type.

Regenerate after editing:

npm run api          # runs api:spec then api:ts in sequence

This is equivalent to running:

npm run api:spec     # cd backend && go generate ./internal/httpd/apispec/...
npm run api:ts       # npx openapi-typescript@7.4.4 backend/internal/httpd/apispec/openapi.yaml -o frontend/src/api/schema.ts

Verify:

cd backend && go test ./internal/httpd/...    # spec drift + route/spec parity tests (does not cover schema.ts, that is checked by the api-drift CI job)

Commit openapi.yaml and frontend/src/api/schema.ts together with the Go changes. CI will regenerate both files and fail if the committed versions are out of date. The CLI hand-mirrored DTOs remain a deliberate manual boundary and are not generated.

PR hygiene

  • Branch from develop, and open PRs against develop, unless explicitly continuing an existing PR. develop is this repository's default branch and every PR merges there. main is a stale snapshot, not the integration branch, so branching from it produces PRs against the wrong base and a diff full of changes that are already shipped.
  • Keep one issue per PR. If asked for separate work, create a separate branch and PR.
  • Use conventional commit messages (feat:, fix:, docs:, test:, chore:).
  • No AI attribution in commits or PR bodies: no Co-Authored-By: Claude... / Claude-Session: trailers, no "Generated with Claude Code" footers. End the commit message at the last line of actual content.
  • Explain intentional omissions in the PR body, especially when the TypeScript original had more behavior than the Go rewrite domain currently supports.
  • Run the narrowest relevant tests first, then the repo/CI commands that match the touched area.

Download now (ZIP)

  • 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 28,693 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 repository5 other files it gives its agents.

Does it work?

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

Reviews can't be read right now.

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.