agentleFS
matteoepitechmatteoepitech/tonton-claude/AGENTS.md

tonton-claude

AGENTS.md4 starsChanged 17 days agoMITView on GitHub

Instructions for AI coding agents (Claude Code, Codex, Cursor, Copilot…) and for the humans driving them. Read this before changing anything; README.md and docs/self-hosting.md explain the product and the security model. Tonton Claude shows the Claude Code sessions of all your machines in the notch of a Mac. Three parts talk through a WebSocket relay, and everything that describes what Claude is doing is end-to-end encrypted:

  • 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,439 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.

The file

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

1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    No new dependency without a reason in the PR.

    line 132

≈ “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

AGENTS.md

Instructions for AI coding agents (Claude Code, Codex, Cursor, Copilot…) and for the humans driving them. Read this before changing anything; README.md and docs/self-hosting.md explain the product and the security model.

The project in one minute

Tonton Claude shows the Claude Code sessions of all your machines in the notch of a Mac. Three parts talk through a WebSocket relay, and everything that describes what Claude is doing is end-to-end encrypted:

claude ─ hooks + MCP channel ─▶ agent ──sealed blobs──▶ relay ──WebSocket──▶ macOS app (notch)
opencode ─ Tonton plugin ──────▶ agent
PathWhatLanguage
agent/One binary per machine: a background service, Claude Code hooks, an MCP channel that streams the transcript and relays prompts and permissions. Tray icons in agent/tray/ (Swift on macOS, PowerShell on Windows).TypeScript (Bun)
relay/Accounts, machines and sealed session history in SQLite, live sessions in memory, WebSocket routing, the web app at its address. Never sees plaintext.TypeScript (Bun)
shared/The client core: wire protocol, end-to-end crypto, account token, session models and a relay client. Used by the agent, the relay and the client apps, and runs in browsers. Versions, for the agent and the relay.TypeScript
app/The macOS app. TontonCore holds the testable logic (crypto, wire format, models, markdown) and also builds for iOS, TontonMac what reads this Mac's own files (local Claude Code and OpenCode sessions, the local agent), TontonClaude the SwiftUI views.Swift 5.10, macOS 14+
ios/The iPhone app (TontonClaude.xcodeproj, Xcode 16 or later), its Live Activity (TontonWidgets) and the extension that opens permission alerts (TontonNotifications), on TontonCore.Swift 5, iOS 17+
raycast/A Raycast extension that lists the sessions and messages them through the app's AppleScript dictionary (app/Resources/TontonClaude.sdef).TypeScript (React)
web/The website (web/site/, React with shadcn/ui, Tailwind and React Flow): served by the relay at its address, and released as one HTML file (bun run web, tonton-web.html). Built on the client core in shared/, which decrypts in the browser. views.ts and markdown.ts are the island's; hero.ts, the hero screen's view model, serves both.TypeScript (React)
desktop/The island for Windows and Linux: an Electron window at the top of the screen with the web app's views (web/views.ts) and Tonton's page (src/renderer/hero.ts), a tray icon, and the account in the system's keyring. Its own package.json.TypeScript (Electron)
scripts/Release builds and the install scripts published with each release (install.sh, install.ps1, install-relay.sh).TS, sh, PowerShell
flake.nix, nix/The Nix flake: the release's agent and relay as packages, and NixOS modules for each (docs/nix.md). nix/release.json names the release: bun scripts/nix-release.ts after each one.Nix
test/Tests that run a real relay with a real agent. Unit tests live next to each part (agent/test, relay/test, app/Tests).TypeScript

Commands

bun install
bun run check                 # Biome (format + lint) and tsc: must be clean
bun run format                # applies Biome's fixes
bun test                      # all TypeScript tests, including test/end-to-end.test.ts
bun run relay                 # a relay on :7777 with its data in ./data

cd app
swift format lint --strict --configuration .swift-format --recursive Sources Tests ../agent/tray/macos ../ios
swift build && swift test
./scripts/sync-strings.sh     # adds new UI strings to Resources/Localizable.xcstrings (CI runs it with --check)
./scripts/build-app.sh        # build/TontonClaude.app (--install copies it to /Applications and launches it)

cd ios                        # the iPhone app, for the Simulator, unsigned
xcodebuild -project TontonClaude.xcodeproj -scheme TontonClaude -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build

cd desktop
bun install && bun run check  # Electron and electron-builder, then tsc
bun run start                 # the island from source; TONTON_ISLAND_HOME=<temp dir> keeps its account apart
bun run package:windows       # out/TontonClaude-Setup-<version>.exe, unsigned (builds from macOS and Linux too)
bun run package:linux         # out/TontonClaude-<version>-x86_64.AppImage and -amd64.deb, unsigned

The iOS project uses folders Xcode keeps in sync: a new .swift file in ios/TontonClaude, TontonWidgets, TontonNotifications, Shared or SharedUI is built without touching project.pbxproj.

CI (.github/workflows/ci.yml) runs check, test and the Swift lint, build and tests, plus syntax checks of the install scripts, a build of the macOS tray, a Simulator build of the iPhone app, and the island on Windows and Linux runners: runs against a relay (desktop/test/smoke: on Windows, X11, and GNOME's compositor on Wayland) and its packages. Run the ones for the parts you touched before saying you are done.

Rules that are easy to break

End-to-end encryption. Conversations, prompts, images, permission prompts, machine names, project paths and status texts are sealed (AES-256-GCM with the account key) before they leave a machine or the app. Never add a plaintext field that says anything about what Claude is doing, and never send decrypted content anywhere, logs included. If the relay needs a value to route or limit, it must be something it can see today (ids, states, sizes, timing).

One protocol, two languages. These pairs must change together, with tests on both sides:

TypeScriptSwift
shared/protocol.ts, shared/wire.tsapp/Sources/TontonCore/Wire.swift, Entry.swift
shared/crypto.tsapp/Sources/TontonCore/E2E.swift (same layout and additional data, tonton/v1)
shared/account-token.tsapp/Sources/TontonCore/Account.swift
shared/session.ts, shared/vault.ts, shared/payloads.tsapp/Sources/TontonCore/Session.swift, SessionVault.swift
IslandState, PermissionPush, PushDevice in shared/protocol.ts; islandState in relay/src/push.tsapp/Sources/TontonCore/Island.swift, Push.swift (the iPhone's Live Activity and alerts)

shared/test/swift-vectors.json holds blobs and relay messages made by the Swift side, with what it reads from them; both test suites check it. After a change to what either side seals or reads, write it again with TONTON_WRITE_VECTORS=1 swift test --filter VectorTests in app/.

The client core runs in browsers. Everything shared/index.ts exports uses WebCrypto and web APIs only, no Node or Bun ones: bun run check type-checks it against the DOM types alone (shared/tsconfig.json).

Versions mix in the wild. The relay is only updated when its own code changes, and machines can run an agent older than the app until someone clicks Update agent. So a new app or agent must work with the deployed relay, and the app must cope with older agents: add optional fields, ignore unknown ones, never rename or repurpose a field. If a change really needs a new relay, say so in the PR.

Relay data. Schema changes are a new entry at the end of MIGRATIONS in relay/src/registry.ts; never edit an existing one. Every input from a socket or a request goes through relay/src/validate.ts, and every new store gets a cap in relay/src/limits.ts.

Claude Code is a moving target. Transcripts (agent/src/transcript/parser.ts) are not a public format: skip what you don't recognize, never throw. Channels are a research preview started with --dangerously-load-development-channels (see agent/src/install/shell-profile.ts).

Claude Code and OpenCode. Tonton shows the sessions of both, and every feature works with both. Claude Code goes through hooks, the MCP channel and its transcripts (agent/src/channel, agent/src/transcript); OpenCode through Tonton's plugin and the tonton opencode bridge (agent/src/opencode), whose events are no more public than the transcripts: skip what you don't recognize, never throw. A change for one tool comes with the same change for the other, tested on both sides. When it really cannot work for one (Claude plan limits do not exist in OpenCode), say why in the PR.

Three platforms. The agent runs on Windows, macOS and Linux: use node:path, no POSIX-only shell calls, and keep scripts/install.sh and scripts/install.ps1 in step.

Don't touch the developer's own setup. tonton install edits the real ~/.claude/settings.json, shell profiles and login items. Run agents with TONTON_HOME=<temp dir> and TONTON_SERVICE=off, as the tests do, and don't run the installer or the uninstaller on the developer's machine unless asked.

Releases come from a signed v* tag pushed by the maintainer. Don't tag, publish a release or touch the repository's secrets.

Style

  • Match the code around you: names, comment density, idioms. Files open with a short comment saying what they are for; comments explain why, not what.
  • TypeScript: Biome settings in biome.json (2 spaces, single quotes, no semicolons, 140 columns). Strict tsc, no non-null assertions.
  • Swift: app/.swift-format (4 spaces, 140 columns, no force try). CI lints with --strict. Logic that can be tested goes in TontonCore; views stay thin.
  • Writing (docs, UI strings, PRs): plain, short English sentences. User-facing names follow the app: Settings › Machines, Update agent, the notch.
  • The Mac app is in English and French. UI text goes to Text, Button, .help, String(localized:) in the app or String(core:) in TontonCore, never as a String put together by hand, so it lands in app/Resources/Localizable.xcstrings. Run app/scripts/sync-strings.sh, then give each new string its French in the catalog (Xcode's editor, or the JSON): LocalizationTests fails for a string without French, with other values than the English, or without French punctuation, and CI fails when the catalog is behind the code.
  • No new dependency without a reason in the PR. The agent has two runtime dependencies. The website bundles React, shadcn/ui's Radix primitives, Tailwind and React Flow (#254), and jsQR, its QR scanner, all pinned; none of them goes into the agent. The app has one, Sparkle, for its own updates, and TontonCore has none. The island in desktop/ has Electron, and electron-builder to package it, in its own package.json.

Tests

  • Bug fix: add a test that fails without it. New behavior: test it where it lives (TontonCore, agent/test, relay/test), and in test/ when it crosses the relay.
  • Tests that wait on sockets or files poll until the condition holds (the eventually helper in test/service.test.ts); never assert right after an asynchronous event.
  • SwiftUI views can't be checked in CI. Render them to an image (see the check-swiftui-view skill) and say in the PR what you did not see on screen.

Commits and pull requests

  • Conventional commits, lower case, imperative, with the part as scope when there is one: feat(app): …, fix(agent): …, test: …, docs: ….
  • One topic per PR. The description says what changes and why, how it was tested, what was not checked, and a Rollout section when the relay or the agents need updating.

Skills

Step-by-step guides for recurring tasks live in .claude/skills/. Claude Code loads them on its own; other agents can read them as plain Markdown.

SkillWhen
protocol-changeAdding or changing a message or field between the agent, the relay and the app
local-stackRunning a relay, an agent and the app on one machine without touching the real setup
check-swiftui-viewSeeing what a SwiftUI view looks like without launching the app
releaseMaintainer only: cutting a version

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.