|
1 | | -- To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`. |
2 | | -- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. |
3 | | -- The default branch in this repo is `dev`. |
4 | | -- Local `main` ref may not exist; use `dev` or `origin/dev` for diffs. |
5 | | -- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility. |
| 1 | +# OpenCode Monorepo Agent Guide |
6 | 2 |
|
7 | | -## Style Guide |
| 3 | +This file is for coding agents working in `/Users/ryanvogel/dev/opencode`. |
8 | 4 |
|
9 | | -### General Principles |
| 5 | +## Scope And Precedence |
10 | 6 |
|
11 | | -- Keep things in one function unless composable or reusable |
12 | | -- Avoid `try`/`catch` where possible |
13 | | -- Avoid using the `any` type |
14 | | -- Prefer single word variable names where possible |
15 | | -- Use Bun APIs when possible, like `Bun.file()` |
16 | | -- Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity |
17 | | -- Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream |
| 7 | +- Start with this file for repo-wide defaults. |
| 8 | +- Then check package-local `AGENTS.md` files for stricter rules. |
| 9 | +- Existing local guides include `packages/opencode/AGENTS.md` and `packages/app/AGENTS.md`. |
| 10 | +- Package-specific guides override this file when they conflict. |
18 | 11 |
|
19 | | -### Naming |
| 12 | +## Repo Facts |
| 13 | + |
| 14 | +- Package manager: `bun` (`bun@1.3.11`). |
| 15 | +- Monorepo tool: `turbo`. |
| 16 | +- Default branch: `dev`. |
| 17 | +- Root test script intentionally fails; do not run tests from root. |
| 18 | + |
| 19 | +## Cursor / Copilot Rules |
| 20 | + |
| 21 | +- No `.cursor/rules/` directory found. |
| 22 | +- No `.cursorrules` file found. |
| 23 | +- No `.github/copilot-instructions.md` file found. |
| 24 | +- If these files are added later, treat them as mandatory project policy. |
| 25 | + |
| 26 | +## High-Value Commands |
| 27 | + |
| 28 | +Run commands from the correct package directory unless noted. |
| 29 | + |
| 30 | +### Root |
| 31 | + |
| 32 | +- Install deps: `bun install` |
| 33 | +- Run all typechecks via turbo: `bun run typecheck` |
| 34 | +- OpenCode dev CLI entry: `bun run dev` |
| 35 | +- OpenCode serve (common): `bun run dev serve --hostname 0.0.0.0 --port 4096` |
| 36 | + |
| 37 | +### `packages/opencode` |
20 | 38 |
|
21 | | -Prefer single word names for variables and functions. Only use multiple words if necessary. |
| 39 | +- Dev CLI: `bun run dev` |
| 40 | +- Typecheck: `bun run typecheck` |
| 41 | +- Tests (all): `bun test --timeout 30000` |
| 42 | +- Tests (single file): `bun test test/path/to/file.test.ts --timeout 30000` |
| 43 | +- Tests (single test name): `bun test test/path/to/file.test.ts -t "name fragment" --timeout 30000` |
| 44 | +- Build: `bun run build` |
| 45 | +- Drizzle helper: `bun run db` |
22 | 46 |
|
23 | | -### Naming Enforcement (Read This) |
| 47 | +### `packages/app` |
24 | 48 |
|
25 | | -THIS RULE IS MANDATORY FOR AGENT WRITTEN CODE. |
| 49 | +- Dev server: `bun dev` |
| 50 | +- Build: `bun run build` |
| 51 | +- Typecheck: `bun run typecheck` |
| 52 | +- Unit tests (all): `bun run test:unit` |
| 53 | +- Unit tests (single file): `bun test --preload ./happydom.ts ./src/path/to/file.test.ts` |
| 54 | +- Unit tests (single test name): `bun test --preload ./happydom.ts ./src/path/to/file.test.ts -t "name fragment"` |
| 55 | +- E2E tests: `bun run test:e2e` |
26 | 56 |
|
27 | | -- Use single word names by default for new locals, params, and helper functions. |
28 | | -- Multi-word names are allowed only when a single word would be unclear or ambiguous. |
29 | | -- Do not introduce new camelCase compounds when a short single-word alternative is clear. |
30 | | -- Before finishing edits, review touched lines and shorten newly introduced identifiers where possible. |
31 | | -- Good short names to prefer: `pid`, `cfg`, `err`, `opts`, `dir`, `root`, `child`, `state`, `timeout`. |
32 | | -- Examples to avoid unless truly required: `inputPID`, `existingClient`, `connectTimeout`, `workerPath`. |
| 57 | +### `packages/mobile-voice` |
33 | 58 |
|
34 | | -```ts |
35 | | -// Good |
36 | | -const foo = 1 |
37 | | -function journal(dir: string) {} |
| 59 | +- Start Expo: `bun run start` |
| 60 | +- Start Expo dev client: `bunx expo start --dev-client --clear --host lan` |
| 61 | +- iOS native run: `bun run ios` |
| 62 | +- Android native run: `bun run android` |
| 63 | +- Lint: `bun run lint` |
| 64 | +- Expo doctor: `bunx expo-doctor` |
| 65 | +- Dependency compatibility check: `bunx expo install --check` |
38 | 66 |
|
39 | | -// Bad |
40 | | -const fooBar = 1 |
41 | | -function prepareJournal(dir: string) {} |
42 | | -``` |
| 67 | +### `packages/apn-relay` |
43 | 68 |
|
44 | | -Reduce total variable count by inlining when a value is only used once. |
| 69 | +- Start relay: `bun run dev` |
| 70 | +- Typecheck: `bun run typecheck` |
| 71 | +- DB connectivity check: `bun run db:check` |
45 | 72 |
|
46 | | -```ts |
47 | | -// Good |
48 | | -const journal = await Bun.file(path.join(dir, "journal.json")).json() |
| 73 | +## Build / Lint / Test Expectations |
49 | 74 |
|
50 | | -// Bad |
51 | | -const journalPath = path.join(dir, "journal.json") |
52 | | -const journal = await Bun.file(journalPath).json() |
53 | | -``` |
| 75 | +- Always run the narrowest checks that prove your change. |
| 76 | +- For backend changes: run package typecheck + relevant tests. |
| 77 | +- For mobile changes: run `expo lint` and at least one `expo` compile-style command if possible. |
| 78 | +- Never claim tests passed unless you ran them in this workspace. |
54 | 79 |
|
55 | | -### Destructuring |
| 80 | +## Single-Test Guidance |
56 | 81 |
|
57 | | -Avoid unnecessary destructuring. Use dot notation to preserve context. |
| 82 | +- Prefer running one file first, then broaden scope. |
| 83 | +- For Bun tests, pass the file path directly. |
| 84 | +- For name filtering, use `-t "..."`. |
| 85 | +- Keep original timeouts when scripts define them. |
58 | 86 |
|
59 | | -```ts |
60 | | -// Good |
61 | | -obj.a |
62 | | -obj.b |
| 87 | +## Code Style Guidelines |
63 | 88 |
|
64 | | -// Bad |
65 | | -const { a, b } = obj |
66 | | -``` |
| 89 | +These conventions are already used heavily in this repo and should be preserved. |
67 | 90 |
|
68 | | -### Variables |
| 91 | +### Formatting |
69 | 92 |
|
70 | | -Prefer `const` over `let`. Use ternaries or early returns instead of reassignment. |
| 93 | +- Use Prettier defaults configured in root: `semi: false`, `printWidth: 120`. |
| 94 | +- Keep imports grouped and stable; avoid noisy reorder-only edits. |
| 95 | +- Avoid unrelated formatting churn in touched files. |
71 | 96 |
|
72 | | -```ts |
73 | | -// Good |
74 | | -const foo = condition ? 1 : 2 |
| 97 | +### Imports |
75 | 98 |
|
76 | | -// Bad |
77 | | -let foo |
78 | | -if (condition) foo = 1 |
79 | | -else foo = 2 |
80 | | -``` |
| 99 | +- Prefer explicit imports over dynamic imports unless runtime gating is required. |
| 100 | +- Prefer existing alias patterns (for example `@/...`) where already configured. |
| 101 | +- Do not introduce new dependency layers when a local util already exists. |
| 102 | + |
| 103 | +### Types |
| 104 | + |
| 105 | +- Avoid `any`. |
| 106 | +- Prefer inference for local variables. |
| 107 | +- Add explicit annotations for exported APIs and complex boundaries. |
| 108 | +- Prefer `zod` schemas for request/response validation and parsing. |
| 109 | + |
| 110 | +### Naming |
| 111 | + |
| 112 | +- Follow existing repo preference for short, clear names. |
| 113 | +- Use single-word names when readable; use multi-word only for clarity. |
| 114 | +- Keep naming consistent with nearby code. |
81 | 115 |
|
82 | 116 | ### Control Flow |
83 | 117 |
|
84 | | -Avoid `else` statements. Prefer early returns. |
| 118 | +- Prefer early returns over nested `else` blocks. |
| 119 | +- Keep functions focused; split only when it improves reuse or readability. |
| 120 | + |
| 121 | +### Error Handling |
| 122 | + |
| 123 | +- Fail with actionable messages. |
| 124 | +- Avoid swallowing errors silently. |
| 125 | +- Log enough context to debug production issues (IDs, env, status), but never secrets. |
| 126 | +- In UI code, degrade gracefully for missing capabilities. |
| 127 | + |
| 128 | +### Data / DB |
| 129 | + |
| 130 | +- For Drizzle schema, use snake_case fields and columns. |
| 131 | +- Keep migration and schema changes minimal and explicit. |
| 132 | +- Follow package-specific DB guidance in `packages/opencode/AGENTS.md`. |
85 | 133 |
|
86 | | -```ts |
87 | | -// Good |
88 | | -function foo() { |
89 | | - if (condition) return 1 |
90 | | - return 2 |
91 | | -} |
| 134 | +### Testing Philosophy |
92 | 135 |
|
93 | | -// Bad |
94 | | -function foo() { |
95 | | - if (condition) return 1 |
96 | | - else return 2 |
97 | | -} |
98 | | -``` |
| 136 | +- Prefer testing real behavior over mocks. |
| 137 | +- Add regression tests for bug fixes where practical. |
| 138 | +- Keep fixtures small and focused. |
99 | 139 |
|
100 | | -### Schema Definitions (Drizzle) |
| 140 | +## Agent Workflow Tips |
101 | 141 |
|
102 | | -Use snake_case for field names so column names don't need to be redefined as strings. |
| 142 | +- Read existing code paths before introducing new abstractions. |
| 143 | +- Match local patterns first; do not impose a new style per file. |
| 144 | +- If a package has its own `AGENTS.md`, review it before editing. |
| 145 | +- For OpenCode Effect services, follow `packages/opencode/AGENTS.md` strictly. |
103 | 146 |
|
104 | | -```ts |
105 | | -// Good |
106 | | -const table = sqliteTable("session", { |
107 | | - id: text().primaryKey(), |
108 | | - project_id: text().notNull(), |
109 | | - created_at: integer().notNull(), |
110 | | -}) |
| 147 | +## Known Operational Notes |
111 | 148 |
|
112 | | -// Bad |
113 | | -const table = sqliteTable("session", { |
114 | | - id: text("id").primaryKey(), |
115 | | - projectID: text("project_id").notNull(), |
116 | | - createdAt: integer("created_at").notNull(), |
117 | | -}) |
118 | | -``` |
| 149 | +- `packages/app/AGENTS.md` says: never restart app/server processes during that package's debugging workflow. |
| 150 | +- `packages/app/AGENTS.md` also documents local backend+web split for UI work. |
| 151 | +- `packages/opencode/AGENTS.md` contains mandatory Effect and database conventions. |
119 | 152 |
|
120 | | -## Testing |
| 153 | +## Regeneration / Special Scripts |
121 | 154 |
|
122 | | -- Avoid mocks as much as possible |
123 | | -- Test actual implementation, do not duplicate logic into tests |
124 | | -- Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs like `packages/opencode`. |
| 155 | +- Regenerate JS SDK with: `./packages/sdk/js/script/build.ts` |
125 | 156 |
|
126 | | -## Type Checking |
| 157 | +## Quick Checklist Before Finishing |
127 | 158 |
|
128 | | -- Always run `bun typecheck` from package directories (e.g., `packages/opencode`), never `tsc` directly. |
| 159 | +- Ran relevant package checks. |
| 160 | +- Updated docs/config when behavior changed. |
| 161 | +- Avoided committing unrelated files. |
| 162 | +- Kept edits minimal and aligned with local conventions. |
0 commit comments