agentleFS
Anil-matchaAnil-matcha/open-dots/mobile/AGENTS.md

open-dots / mobile

AGENTS.md6.9k starsChanged 6 days agoApache-2.0View on GitHub

This is the native phone app for Suparagent: Expo (managed) and React Native, TypeScript, Expo Router. It pairs with the user's own server and talks to the same /api/v1 API as the web UI, as a paired device with the chat scope (see docs/AUTH.md). It adds no server of its own. Do not trust memory for Expo, EAS or React Native APIs. Read the major version of expo in package.json, then use the matching docs at https://docs.expo.dev/versions/v<major>.0.0/ and the index…

Adopted by

Steady: 0 new projects took it in the last 4 weeks, none the 4 weeks before.thin data

Week of Sep 13: 0 new projectsWeek of Sep 20: 0 new projectsWeek of Sep 27: 0 new projectsWeek of Oct 4: 0 new projectsWeek of Oct 11: 0 new projectsWeek of Oct 18: 0 new projectsWeek of Oct 25: 0 new projectsWeek of Nov 1: 0 new projects
Sep 2026Oct 2026Nov 2026
New projects taking a version of this file each week, over the 8 weeks our latest run read: only 0 in all, so this is a hint, not a trend.

Who's talking about Anil-matcha/open-dots

The biggest 5 of 15 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 15

Talked about on GitHub and Hacker News (15 times).

On GitHub · 14

9 more on GitHub

On Hacker News · 1

  • 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,843 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 repository3 other files it gives its agents.

The file

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

6 rules. About 1 is common, 1 is distinctive, and 4 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    Do not trust memory for Expo, EAS or React Native APIs.

    line 7
  2. Very specific:

    Add packages with npx expo install <package>, not npm install, so versions match the SDK.

    line 9
  3. Very specific:

    Run npx expo install --check after dependency changes.

    line 11
  4. Very specific:

    Never create or edit ios/ or android/ by hand.

    line 12
  5. Distinctive:

    All of these work on Windows, macOS and Linux.

    line 25
  6. Common:

    No secrets in the repo. Signing keys, store credentials and push credentials are CI secrets only.

    line 47

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

Mobile app instructions

This is the native phone app for Suparagent: Expo (managed) and React Native, TypeScript, Expo Router. It pairs with the user's own server and talks to the same /api/v1 API as the web UI, as a paired device with the chat scope (see docs/AUTH.md). It adds no server of its own.

Expo changes every release

Do not trust memory for Expo, EAS or React Native APIs. Read the major version of expo in package.json, then use the matching docs at https://docs.expo.dev/versions/v<major>.0.0/ and the index at https://docs.expo.dev/llms.txt.

  • Add packages with npx expo install <package>, not npm install, so versions match the SDK. Dev tools go in devDependencies.
  • react, react-dom and react-test-renderer must stay on the exact same version.
  • Run npx expo install --check after dependency changes.
  • Never create or edit ios/ or android/ by hand; they are generated from app.json and config plugins. They are Git-ignored.
  • Routes live in src/app/. Keep other code (components, hooks, API client) and all tests outside it: every file in src/app/ is bundled as a route, so a test there breaks check:bundle. Tests live in src/tests/.

Checks (run from this directory)

npm ci
npm run lint
npm run typecheck
npm test
npm run check:bundle   # exports the JS bundle for iOS and Android; no device or Xcode needed

All of these work on Windows, macOS and Linux. Building or running the iOS app needs macOS; say which OS a check was actually run on. Running on a device needs a development build or Expo Go.

Layout

  • src/app/: screens only (Expo Router). _layout.tsx guards the routes: paired phones see index (the conversation list), thread/[id] and settings; unpaired ones see pair and scan.
  • src/components/: pieces shared by screens (transcript-row, composer, approval-card, keyboard-screen, markdown). Attachments: lib/attachments.ts (limits, the multipart body, reading turn.started's list) and lib/pick-attachments.ts (the two system pickers). The multipart body is built by hand because expo/fetch cannot send { uri } parts. Agents: lib/agents.ts and app/new.tsx (the picker, a modal route). New conversation goes straight to a new conversation when the server has no agents, and opens the picker otherwise. A phone paired with the manage scope ("Chat, files and agents") can also create and edit agents: app/agents/ (the list, and the editor at /agents/new and /agents/<id>), lib/agent-draft.ts (fields, the server's limits, what is sent, refusals in words), lib/engines.ts (the engines and models for the pickers) and components/form.tsx (the form controls). The editor sends only what changed and never a workspace folder, "Accept edits", connected apps or the lead role: the server refuses those from any device without admin (field_requires_admin), and the screens do not offer them. Deleting an agent stays in the web app. The same scope can make, change and delete rooms: app/room-settings.tsx (?id=new or a room id), app/room-details.tsx (instructions, routing, members, hold or resume, delete after typing the name), lib/room-draft.ts and components/member-picker.tsx; a change to the members sends the roster the form was opened with (expected_member_ids) so the server can refuse a stale edit. canManageAgents(scopes) only decides what to show; the server enforces it. Rooms: lib/rooms.ts (the feed reducer, mentions, approvals), lib/use-room.ts and app/rooms/. A room's messages are the stored events of its own thread, so the phone follows that thread with the same stream as a conversation. A chat-only device cannot create or edit rooms (docs/AUTH.md), so there is no such screen. The room lists its pending approvals without a thread id, so loadRoomApprovals asks each member's own thread; an answer goes to that thread. Colors: never write a color in a component. Take it from lib/theme.ts (useStyles(createStyles)); its values are the web app's tokens from frontend/app/globals.css and theme-drift.test.ts fails when they differ, so change a color in the web file first, then in theme.ts (warnBackground is the only phone-only color); the camera overlay and the translucent chip on the person's bubble are the only exceptions, and theme.test.tsx checks every text and background pair for a 4.5:1 contrast in both looks. lib/markdown.ts is the Markdown reader: no HTML, and only http(s) links are followed.
  • src/lib/: everything else. server-url, pairing-link, pairing-api, api, sse and transcript are plain TypeScript with no React Native imports, so they are easy to test; credentials is the only place the token is stored; auth-context holds the pairing state; use-api and use-thread tie the API to React.
  • The chat reads a thread by following its event stream from the last event seen (sse.ts). A reconnect sends Last-Event-ID, and transcript.ts applies each stored event at most once, so a replay can never show anything twice. If the platform cannot read a response as it arrives, followThread falls back to paging GET /threads/{id}/events. Event types the app does not draw become one muted row; metadata-only types are skipped.
  • Approvals: the oldest pending approval is pinned above the composer with every input of the call (long values cut, with "Show all") and Allow and Deny. The card never decides for the person: it waits for the stream's approval.resolved to show the result. "Always allow" rules are not part of the app.
  • Hosted workspace (the paid cloud workspace at suparagent.ai, an alternative to pairing with your own server): a hosted phone is a paired phone whose server is the hosted origin and whose token is its own workspace token, with hosted: { email, accountToken } on the auth state, so every screen and createApi work unchanged. lib/hosted.ts is the account API (email code sign-in, status, wake, foreground signal, this phone's workspace token; plain TypeScript, one fixed origin that a release build cannot change, every answer read tolerantly, no token ever logged or put in a URL), lib/hosted-flow.ts waits for a sleeping workspace and recovers a rejected token (time is injected), lib/hosted-credentials.ts keeps the account session and the install id in the secure store apart from the workspace token (lib/credentials.ts marks it hosted), components/hosted-gate.tsx shows the app only while the workspace is ready and sends the foreground signal, app/hosted.tsx is the sign-in. Rules that the tests pin: reading the state never starts anything; only an explicit wake does, once, when the app opens or the person asks; a blocked state (plan ended, hours used up) is shown and never retried by itself; a 503 from a call or stream only reports that the workspace is asleep (onUnavailable), it never wakes it; a 401 asks the service for a new token at most every 30 seconds and signs out only if the account sign-in ended too; the two tokens are never mixed; a hosted phone has no agent or room editing (the service never grants manage to it). File access is opt-in: a hosted phone starts with chat, and the Settings switch "File access" calls hostedSetFiles in auth-context.tsx, which asks for a new token (files or chat) with the account session and replaces the old one; it needs a running workspace and never wakes it, and a renewed token keeps the chosen scope.
  • src/tests/: Jest tests. Jest's React Native environment replaces fetch with a stub, so unit tests pass a fake fetch into the lib functions. To check against a real server, run the compiled lib code under plain Node against a throwaway backend (SQLite file, the CI test key, python -m app.auth.cli pairing-code --scope chat).

Rules for this package

  • Scope is fixed by the maintainer's design note: pair, threads, chat with stop, approvals, plus the features added one by one afterwards (Markdown, attachments, dark theme, agent picker, rooms, conversation search, and the hosted workspace, decided as M-D5 on 2026-11-06). Do not add voice, push, settings editing or other features without a decision.
  • Touch targets: a control the person taps is at least touch.min (44) points in lib/theme.ts; a smaller-looking one gets hitSlop to that size. touch-targets.test.tsx checks the main ones.
  • Release builds shrink and rename code (R8), which Expo Go does not. The QR scanner needs extraProguardRules for ML Kit in app.json (app-config.test.ts checks it): without them the camera shows and never reads a code, and a rule narrower than all of com.google.mlkit.** crashed the app at launch. Check a change that adds a native library in a signed release build on a phone, not only in Expo Go.
  • Typeface: Geist and Geist Mono, as on the web. Import Text and TextInput from @/components/text, never from React Native, so a style's fontWeight becomes the right font file (lib/fonts.ts, lib/font-assets.ts); write fontFamily: MONO for code. A new weight needs its file added to font-assets.ts and a name in FAMILY; fonts.test.tsx checks they match. The fonts load once in _layout.tsx and the app falls back to the system font if they cannot.
  • The app is a chat-scope client. It must reject a pairing session that has admin scope, and must not rely on hiding screens as authorization.
  • The bearer token goes only into the OS secure store, never into logs, URLs or plain storage.
  • The app talks to the server over HTTPS, or over plain HTTP when the host is on the person's own network (isLocalHost in lib/server-url.ts: localhost, loopback, 10/8, 172.16/12, 192.168/16, 169.254/16, ::1, fc00::/7, *.local), in dev and release builds alike (D-025). normalizeServerUrl is the one rule: pairDevice, createApi and a saved session all re-check it, and a reply from plain HTTP on a non-local host (a redirect) is not used. The OS cleartext settings (usesCleartextTraffic, NSAllowsLocalNetworking, set in app.json) only make this possible; they cannot match IP ranges, so the JS rule is the real limit. Do not widen it (any other host, 100.64/10) without a maintainer decision.
  • Decode API responses tolerantly: ignore unknown fields and show unknown event types as a generic row.
  • No secrets in the repo. Signing keys, store credentials and push credentials are CI secrets only; a contributor must be able to build and run against their own server without any of them.
  • Bundle id ai.suparagent.app and URL scheme suparagent are fixed. The display name in app.json is Suparagent and can still be changed before a store release.

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.