otto
AGENTS.md7 starsChanged 5 months agoMITView on GitHub
Start here if you are an AI coding agent working on otto. otto is pivoting from a standalone Electron shell into an extension of Paperclip (the open-source agent-orchestration app). Mental model: Paperclip is the office, otto is the culture layer, Letta is the memory/runtime. - v1 (in progress): "use Letta from Paperclip." Ship a letta_local external adapter at packages/paperclip-letta-adapter that drives an existing local Letta agent from a Paperclip issue (memory continuity via the Letta agentId). It targets Paperclip's external-adapter…
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 repositoryOne other file it gives its agents.
- charterSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
16 rules. About 0 are common, 9 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
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
- Very specific: line 3
Start here if you are an AI coding agent working on otto.
- Very specific: line 24
Do NOT archive the Electron shell in v1: Keep apps/desktop/ as the internal lab / Letta console.
- Distinctive: line 41
If a change does not gate irreversibility or make behavior compound, question it.
- Distinctive: line 49
Do not show mock operational data.
- Distinctive: line 57
Do not publish, tag, release, change visibility, or change license without explicit human approval.
- Distinctive: line 58
Do not claim done without receipts.
- Distinctive: line 59
Do not add private/product-specific control systems to the OSS core unless behind a clear boundary.
- Distinctive: line 63
Keep slash-command launches tiny.
- Distinctive: line 75
Use GitHub Issues for new nits, bugs, polish requests, and follow-up work.
- Very specific: line 76
Every GitHub Issue must carry exactly one priority label: p0, p1, p2, or p3.
- Very specific: line 120
Nonintrusive desktop smoke (default for agents): prefer task staging:build plus CDP/Playwright smokes, or task staging (background launch).
- Very specific: line 122
After any apps/desktop/ implementation turn, refresh staging (not live):
- Very specific: line 147
Do not use task refresh or any local branch build to overwrite the canonical app.
- Distinctive: line 148
Use disposable/staging app bundles for local desktop proof unless Sebastian explicitly authorizes touching an official bundle.
- Very specific: line 151
Do not call Electron “connected” unless session.initialize() succeeds against a live Letta agent.
- Distinctive: line 178
Keep private/product-specific control systems out of the OSS core.
≈ “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.
Files
AGENTS.md
Start here if you are an AI coding agent working on otto.
Direction (read first): otto → Paperclip plugin
otto is pivoting from a standalone Electron shell into an extension of Paperclip (the open-source agent-orchestration app). Mental model: Paperclip is the office, otto is the culture layer, Letta is the memory/runtime.
- v1 (in progress): "use Letta from Paperclip." Ship a
letta_localexternal adapter atpackages/paperclip-letta-adapterthat drives an existing local Letta agent from a Paperclip issue (memory continuity via the LettaagentId). It targets Paperclip's external-adapter contract: a package exportingcreateServerAdapter(): ServerAdapterModule, installed viaPOST /api/adapters(isLocalPath: true). Provider keys live in Letta; the adapter only observes aproviderConfiguredboolean, never the keys.- Network boundary: the adapter runs where the Paperclip server runs. v1 proof target is a local Paperclip host + an existing local Letta runtime on the same Mac. Cloud Paperclip → remote Letta or an explicit tunnel is a later step. This is the assumption most likely to be wrong; resolve it first.
- v2: culture loop ships as a Paperclip plugin (receipts to issues; correction → proposal →
ratification → Standard). Adapters and Plugins are two different Paperclip surfaces — v1 is an
adapter, not a plugin. v1 carries only a tiny
receiptRefplaceholder, no real culture. - Do NOT archive the Electron shell in v1. Keep
apps/desktop/as the internal lab / Letta console; build the adapter in its own package. Archive shell surfaces only after the Paperclip adapter completes one real issue round-trip. The governance layer (standards/,practices/,routines/,receipts/,skill/,autonomy/) is kept for v2.
The legacy product rules below still describe the active desktop shell (kept as the lab). They remain
in force for apps/desktop/ (e.g. provider keys belong in Letta; do not show mock data; only
Sebastian accepts done).
North star
otto makes agent behavior compound.
correction -> proposal -> ratification -> standard/practice/routine -> receipt -> better next actionIf a change does not gate irreversibility or make behavior compound, question it.
Current product rules
- Product/UI name is
ottolowercase. UseOttoonly when grammar/platform labels force it. - Owl/avatar image is the primary mark. Do not reintroduce the old line-drawn owl as the product logo.
- v1 is local-only. Default ("This Mac"): otto bundles and supervises its own embedded Letta runtime — download otto and it works, no separate Letta install. Advanced ("Existing local Letta"): connect to a Letta.app the user already runs (no silent fallback). Either way, provider/API keys belong in Letta, not otto (otto stores only a
hasProviderKeyboolean). Seedocs/v1/embedded-letta-bundle.md. - Embedded runtime is bundled from the published
@letta-ai/letta-codepackage (Apache-2.0), never forked. Carry its LICENSE in the bundle, keepTHIRD_PARTY_NOTICES.mdaccurate (bun run gen:notices), and attribute as "powered by Letta". Do not ship Letta marks/logos as otto branding (otto's mark is the owl). - Do not show mock operational data. If a pane is not wired, show an honest empty state.
- Smoke tests must never write into Sebastian's live
conversation=default; use disposable conversations.
Git and safety
- Inspect
git statusbefore editing. - Protect user changes; stage only intended files.
- Remotes:
originonly →https://github.com/otto-haus/otto.git. Do not add remotes or push to archived predecessor repositories. - Do not publish, tag, release, change visibility, or change license without explicit human approval.
- Do not claim done without receipts.
- Do not add private/product-specific control systems to the OSS core unless behind a clear boundary.
Agent launch contracts
Keep slash-command launches tiny; the markdown file is the contract:
/goal Read docs/agent-goals/codex-goal.md and follow it.
/goal Read docs/agent-goals/claude-goal.md and follow it.
/goalbuddy Read docs/agent-goals/composer-goal.md and prepare the board.See docs/agent-goals/README.md for parallelism, collision rules, and trunk workflow. Default throughput: one independent ticket = one agent = one branch/worktree. Sebastian is the merge/release/one-way-door gate.
Current issue/review workflow
- Use GitHub Issues for new nits, bugs, polish requests, and follow-up work. Do not create new local ticket files for ordinary intake.
- Every GitHub Issue must carry exactly one priority label:
p0,p1,p2, orp3. If Sebastian says P0, usep0. - Agents must respect priority when choosing work:
p0beforep1beforep2beforep3, then lane/status/severity. - Any
gh issue createcommand must include one priority label at creation time, e.g.--label p0or--label p2; do not create unprioritized issues. - Historical
planning/hq-tickets/files remain archived/mirrored context; do not treat them as the active intake queue unless Sebastian explicitly reopens that lane. - Chat claims are not state. If Sebastian reports a nit in chat, capture it as a GitHub Issue with evidence/screenshot links when available.
- PRs that need Sebastian's merge attention should carry
status: ready for reviewonly after CI is green and the implementer has done a real review pass. - Implementer cannot self-certify Done for consequential changes. Use an unbiased reviewer/subagent when the risk warrants it, and include proof in the PR body or linked issue.
- Sebastian is the merge gate. Keep ready-for-review PR count low; prefer fast, small PRs over large batches.
- Merge/review gates are per ticket / per PR — they must not pause the whole lane. After handing off one PR, scout the next file-disjoint Ready issue (
docs/agent-goals/README.md,docs/goals/github-ready-loop/).
Verify
bun install
bun run typecheck
bun test
bun run verify:v0
bun run --cwd apps/desktop typecheck
bun run --cwd apps/desktop electron:typecheckDesktop:
task electron # live Electron app in dev
task staging # build/package/isolated staging app; background launch (no focus steal)
task staging:build # build/package only — no launch (preferred for agent verify loops)
task staging:open # explicit visible launch when debugging UI
task install:release # canonical otto.app — GitHub Release only; requires OTTO_ALLOW_RELEASE_INSTALL=1
task smoke:release:metadata # read-only — compare installed otto.app to latest or OTTO_RELEASE_TAG
task smoke:letta-cli # resolveCli + version/help; opt-in turn with LETTA_AGENT_ID (#295)
task smoke:cli # isolated disposable conversation; never default
task smoke:cron # opt-in Letta cron create/list/delete smoke; never default
task smoke:attachments # fixture save + runtime attachment context + leak checks (#299)
task smoke:permission # #298 permission allow/deny round-trip (mock transport; no app bundles)Permission round-trip (#298):
bun scripts/permission-round-trip-smoke.ts
# or: task smoke:permissionNonintrusive desktop smoke (default for agents): prefer task staging:build plus CDP/Playwright smokes, or task staging (background launch). Staging bundles set OTTO_SMOKE=1 and default OTTO_WINDOW_MODE=background so windows do not steal focus. Use task staging:open or OTTO_WINDOW_MODE=visible only when a human needs a visible window. Never mutate /Applications/otto.app.
After any apps/desktop/ implementation turn, refresh staging (not live):
task staging:build # preferred — no window focus steal (#326)
# or task staging # → /Applications/otto-staging.app; background launch; refuses unless HEAD=origin/main (#314)
task staging:main # fetch origin/main then staging (same gate when on main)Staging smokes (never /Applications/otto.app):
bash apps/desktop/scripts/deploy-staging.sh
OTTO_RECEIPT_DIR=$PWD/docs/receipts/staging task smoke:staging:two-thread # 046 thread isolationClean-machine E2E (#291 — isolated HOME, no host Letta config, never live/staging installs):
bun run --cwd apps/desktop app:dir
NODE_PATH=$HOME/.codex/admin/node_modules task smoke:clean-machineCanonical app boundary:
/Applications/otto.appmust only be installed or updated from a published GitHub Release desktop artifact (latest or rollback tag viaOTTO_RELEASE_TAG).- Do not use
task refreshor any local branch build to overwrite the canonical app. - Use disposable/staging app bundles for local desktop proof unless Sebastian explicitly authorizes touching an official bundle.
- Rollback:
OTTO_RELEASE_TAG=<tag> task smoke:release:metadata(read-only proof); install only with Sebastian approval viaOTTO_ALLOW_RELEASE_INSTALL=1 OTTO_RELEASE_TAG=<tag> task install:release.
Do not call Electron “connected” unless session.initialize() succeeds against a live Letta agent.
Repo map
packages/core/ shared v0 contract types
packages/practices/ PracticeSpec loader, validator, CLI
apps/desktop/ Vite + Electron workspace shell
docs/agent-goals/ file-native Codex/Claude/Composer launch contracts
docs/design/ brand guide, onboarding, motion, reference icons (public canon)
extension/ Letta Code commands and permission gates
skill/ Charter and Routine skills
practices/ practice.yaml specs
routines/ proposed Routine specs
standards/ canon and precedents (earned semver: standards/standards/earned-semver.md)
templates/ Charter, Practice, Routine, Standard, Ticket, Worker packets
receipts/ proof artifacts
planning/hq-tickets/ ticket conveyor (canonical queue)
planning/lane-tickets/ historical lane-numbered tickets (001–016)
SHIP_CHECKS/ per-surface acceptance checksPublic safety boundary
otto may include generic agent behavior governance: Standards, Practices, Routines, approvals, receipts, reversibility gates, and memory writeback governance.
Keep private/product-specific control systems out of the OSS core.
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
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.

