kamehadb
AGENTS.md14 starsChanged 28 days agoApache-2.0View on GitHub
This file provides guidance for coding agents working in this repository. KamehaDB is a local-first database GUI built as a single Wails v2 desktop app: a Go backend embedded in the executable plus a React 19 + Vite frontend. The current app supports PostgreSQL, MySQL, SQLite, MongoDB, Redis, SQL Server, Oracle, ClickHouse, DuckDB, and MariaDB. It includes schema browsing, a CodeMirror SQL editor, query history, PostgreSQL stats views, schema timeline/diff workflows, Redis/Mongo explorers, embedded PostgreSQL and Mongo shells, PostgreSQL backup/restore…
- Installs packages
- Commits and pushes
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,700 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 repository17 other files it gives its agents.
- landing/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- brainstorm-featureSkill
- bump-versionSkill
- context-handoffSkill
- document-wikiSkill
- estimate-featureSkill
- implement-taskSkill
- lean-auditSkill
- plan-featureSkill
- preparing-releasesSkill
- read-codebase-contextSkill
- review-and-verifySkill
- setup-codebaseSkill
- setup-openezSkill
- systematic-debuggingSkill
- using-devkitSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
43 rules. About 0 are common, 22 are distinctive, and 21 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈22
Distinctive · estimate
This author's own choices. Worth a look.
21
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 197
When changing bound service signatures, regenerate bindings and verify the desktop tsc pass — shape drift surfaces as type errors in …
- Very specific: line 198
When changing desktop UI behavior, prefer running the desktop tests and a targeted wails build
- Very specific: line 205
If a bundled workflow fails only in the built app, check the in-app Logs page first, then inspect ${KAMEHADB_DATA_DIR}/logs/ if you need …
- Distinctive: line 233
Push Back: If a simpler approach exists or the requested path is flawed, suggest an alternative.
- Distinctive: line 234
Clarify First: If a request is unclear, stop and name the specific confusion.
- Distinctive: line 239
No Over-Abstraction: Avoid abstractions for single-use code.
- Distinctive: line 240
Surgical Error Handling: Do not add error handling for impossible scenarios.
- Distinctive: line 241
Aggressive Simplification: If a solution is overcomplicated, rewrite it to be simpler.
- Distinctive: line 245
Zero Collateral Damage: Do not "improve" adjacent code, comments, or formatting.
- Distinctive: line 247
Orphan Cleanup: Remove imports/variables that YOUR changes made unused.
- Distinctive: line 248
Traceability: Every changed line must trace directly back to the user's request.
- Distinctive: line 254
Verification Gate: No task is "done" until success criteria are verified via tool output.
- Very specific: line 258
Rule: ALWAYS use the shadcn UI components from apps/desktop/src/components/ui/ instead of raw HTML elements when an equivalent exists.
- Very specific: line 272
Rule: Never hardcode database kind strings (e.g.
- Very specific: line 273
Use
KINDfrom@kamehadb/shared: All database kind comparisons must use KIND.POSTGRES, KIND.MYSQL, etc. - Very specific: line 274
Use
DEFAULT_PORTS: All port numbers must come from DEFAULT_PORTS[KIND.X] — never hardcode 5432, 3306, etc. - Very specific: line 275
Use timeout constants: All timeouts, cache durations, and intervals must use named constants from apps/desktop/src/lib/constants.ts …
- Very specific: line 276
Use
ALL_KINDS,SQL_KINDS,NOSQL_KINDS: When iterating over or validating database kinds, use these arrays — never inline a list of … - Very specific: line 279
Zod enums: Use z.enum(ALL_KINDS as [string, ...string[]]) — never inline a list of kind string literals.
- Distinctive: line 286
Rule: Every non-trivial function, hook, or block of logic must carry a short comment that explains the what (one line), the why (one line …
- Very specific: line 304
Package Manager: ALWAYS use pnpm for this project, except for the landing/ directory which is managed via npm.
- Very specific: line 305
Changelog: All user-facing changes must be recorded in CHANGELOG.md under [Unreleased] before merging.
- Distinctive: line 309
When a feature wave adds new engines, major workflows, or changes the product descriptor, sync these five surfaces in the same PR so they …
- Very specific: line 317
Run npm --prefix landing run build and pnpm build after any landing or README change to confirm nothing is broken.
- Distinctive: line 319
After every material product change, run through this list before merging.
- Distinctive: line 327
Search for an existing schema, type, helper, or adapter contract before adding another one.
- Distinctive: line 329
If the same shape appears in two places, extract it into a shared type or helper
- Distinctive: line 331
Do not add a general abstraction for a single use or remove a few clear lines only to reduce repetition.
- Very specific: line 336
Use type aliases for object shapes, component props, API data, adapter contracts, unions, mapped types, and utility compositions.
- Very specific: line 338
Never use any — use unknown and narrow with type guards
- Distinctive: line 342
Prefer string literal unions over enums:
- Distinctive: line 348
When a value can be one of several shapes, model it as a discriminated union (see below)
- Distinctive: line 371
Use a literal "tag" field so the compiler narrows automatically:
- Very specific: line 391
Use kind, type, or status as the discriminator field — pick one and stay consistent
- Very specific: line 392
Use as const on values that feed the union so literal types are preserved
- Distinctive: line 434
Place the comment above the line it explains, not as a trailing line
- Distinctive: line 435
Use full sentences with proper punctuation.
- Distinctive: line 464
Use a skill when its description matches the task.
- Very specific: line 470
Before code work in a new session, call memory_recall using 1–3 keywords from the task.
- Very specific: line 471
Use code_query before filesystem search.
- Very specific: line 472
Use code_context for symbol/file relationships.
- Very specific: line 473
Call memory_write after an architectural decision or a non-obvious constraint is confirmed.
- Distinctive: line 474
Use explicit workspace scope for cross-workspace work.
≈ “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
This file provides guidance for coding agents working in this repository.
Project Overview
KamehaDB is a local-first database GUI built as a single Wails v2 desktop app: a Go backend embedded in the executable plus a React 19 + Vite frontend. The current app supports PostgreSQL, MySQL, SQLite, MongoDB, Redis, SQL Server, Oracle, ClickHouse, DuckDB, and MariaDB. It includes schema browsing, a CodeMirror SQL editor, query history, PostgreSQL stats views, schema timeline/diff workflows, Redis/Mongo explorers, embedded PostgreSQL and Mongo shells, PostgreSQL backup/restore flows, an in-app logs viewer, a read-only MCP server, and an AI chat panel with schema-aware context.
There is also a separate marketing/docs site in landing/, but it is not part of the pnpm workspace used by the desktop app.
Repository Layout
├── apps/
│ └── desktop/ # React 19 + Vite 7 frontend (Wails webview)
├── dbcore/ # Reusable provider core: contracts, providers, lifecycle manager
├── internal/ # Go backend: services, store, MCP, terminal
├── packages/
│ └── shared/ # Shared Zod schemas and frontend-facing types
├── landing/ # Separate Next.js marketing site (not in pnpm workspace)
├── main.go / app.go # Wails entrypoint and bound app methods
├── wails.json # Wails project config (frontend dir, build hooks)
├── docker-compose.yml # Local dev databases
└── docker-init/ # Seed SQL for Postgres/MySQL/MariaDBWorkspace And Package Boundaries
- The pnpm workspace includes only
apps/*andpackages/*. landing/has its ownpackage-lock.jsonand is managed separately with npm.- Most root scripts target the pnpm workspace only. Do not assume they affect
landing/unless they explicitly usenpm --prefix landing. - The Go module lives at the repo root (
go.mod);internal/is not part of the pnpm workspace.
Commands
Workspace root
# Install workspace dependencies
pnpm install
# Start dev databases
docker compose up -d
# Run the full app in Wails dev mode (frontend watcher + Go backend)
pnpm dev
# Run only the frontend dev server (no backend bindings)
pnpm dev:desktop
# Build the production desktop binary into build/bin/
pnpm build
# Typecheck all workspace packages (desktop: pnpm --dir apps/desktop exec tsc --noEmit)
pnpm typecheck
# Lint all workspace packages that expose a lint script
pnpm lint
# Run all workspace package tests that expose a test script
pnpm test
# Run the Go backend tests
pnpm test:go
# Lint the Go backend with golangci-lint (resolved via `go tool` from go.mod — no separate install)
pnpm lint:go
# Format Go source with gofumpt + goimports
pnpm format:goImportant package-level scripts
# Desktop app
pnpm --filter @kamehadb/desktop dev
pnpm --filter @kamehadb/desktop build
pnpm --filter @kamehadb/desktop test
# Landing site
npm --prefix landing run dev
npm --prefix landing run build
npm --prefix landing run lint
node landing/scripts/capture-images.mjs # Regenerate AI compare panelsCurrent Architecture
Go backend (internal/)
The backend is embedded in the Wails binary — there is no external process or IPC.
internal/store/— SQLite metadata store (kamehadb.db): profiles, query history, AI settings, chat history, MCP state, and the AES-256-GCM credential vaultdbcore/— reusable provider core (nointernal/or Wails imports):dbcore/engines/holds theSQLAdaptercontract and shared helpers,dbcore/providers/<name>/holds each provider (postgres via pgx, mysql/mariadb, sqlite, sqlserver, oracle, clickhouse, duckdb, mongo, redis),dbcore/providers/allassembles all ten kinds, anddbcore.Manager/Registryown provider lifecycleinternal/database/— app facade wiring the store to the shared manager;internal/engines/keeps app-only kind metadata (legacy kinds, MCP lists);internal/mongo/keepsmongoshsupportinternal/api/— Wails-bound services (ConnectionsService,SqlService,SchemaService,MongoService,RedisService,AiService,QueryHistoryService,McpService,MaintenanceService,TerminalService,LogsService) constructed byNewServicesininternal/api/connections.gointernal/schema/— snapshots, diffing, watcher, migration generationinternal/terminal/— shared PTY manager used by the mongosh and psql shellsinternal/maintenance/— file-database backup/restore and pg tool resolutioninternal/mcp/— read-only MCP server: loopback JSON-RPC listener, tool handlers, adapter manager, managed-account provisioninginternal/ai/— provider client, schema-context indexing, embeddings storeinternal/logs/— JSON-lines app log writer and bounded tail reader
Frontend ↔ backend bindings
- Bound Go methods are exposed through generated bindings in
apps/desktop/wailsjs/(regenerate withwails generate moduleorwails build). apps/desktop/src/lib/api.tswraps the generated bindings — all frontend calls go through it. There is no HTTP API, auth token, or sidecar port.- Backend → frontend notifications use
runtime.EventsEmit/EventsOn(connection health, terminal output, AI chat streaming, tool-job progress).
Shared contract
packages/shared/src/index.ts holds the frontend-facing contract:
KIND/DbKind, kind lists, default ports, and helpers for the 10 supported engines- Connection profile and input Zod schemas used by the connection dialog
- SQL, Redis, MongoDB, AI, and MCP-related TypeScript types
isQuerySafe/safeErrorMessageand other small shared utilities
The runtime source of truth is the Go models in wailsjs/go/models.ts; keep packages/shared shapes aligned with them.
Desktop app
apps/desktop/src/App.tsx drives the top-level app views (workspace, api-settings, logs) and the tabbed workspace.
Design system tokens and conventions are documented in apps/desktop/DESIGN-SYSTEM.md.
Main areas:
components/sidebar.tsxfor connection and schema navigationcomponents/workspace-screen.tsx,components/workspace-tab-bar.tsx, andcomponents/workspace-content.tsxfor tab orchestrationcomponents/sql-editor.tsxfor CodeMirror query editing and executioncomponents/table-view.tsxfor SQL table browsingcomponents/schema-graph.tsxfor ER diagramscomponents/schema-timeline.tsx,components/schema-diff-view.tsx, andcomponents/migration-assistant.tsxfor schema change workflowscomponents/database-stats.tsxandcomponents/table-stats.tsxfor PostgreSQL metricscomponents/postgres-psql-tab.tsx,components/postgres-backup-dialog.tsx, andcomponents/postgres-restore-dialog.tsxfor PostgreSQL maintenance workflowscomponents/mongo-view.tsx,components/mongo-shell.tsx, andcomponents/redis-view.tsxfor non-SQL enginescomponents/query-history-panel.tsxfor saved SQL history/favoritescomponents/logs-page.tsxfor viewing frontend and backend logs inside the appcomponents/ai-chat-panel.tsx,components/api-settings-page.tsx, andcomponents/mcp-settings-section.tsxfor AI and MCP
State and data flow:
apps/desktop/src/store/index.tsuses TanStack Store for workspace stateapps/desktop/src/hooks/contains TanStack Query-based data hooksapps/desktop/src/lib/code-editor.tsxis the shared CodeMirror 6 wrapper (SQL/Mongo/Redis editors)apps/desktop/src/lib/sql-autocomplete.tsandlib/mongo-autocomplete.tscontain client-side completion logic feeding the editorsapps/desktop/src/lib/app-logs.tssends frontend errors to the Go log store and reads the combined snapshot for the Logs page
Database Support
Supported now:
- PostgreSQL
- MySQL
- SQLite
- MongoDB
- Redis
- SQL Server
- Oracle
- ClickHouse
- DuckDB
- MariaDB
Notes:
- PostgreSQL has the richest stats support.
- PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, ClickHouse, and DuckDB use the SQL adapter path.
- MongoDB uses a dedicated service and adapter flow.
- Redis uses a dedicated service and adapter flow, not the SQL path.
- DuckDB connects to local .duckdb files (file-based).
- PostgreSQL also has app-managed
psql, backup, restore, and schema diff/timeline workflows on the desktop side. - MongoDB can open an embedded
mongoshsession; ifmongoshis missing locally, the backend can install an app-managed copy without modifying the user's global installation.
Connection Defaults For Docker
| Engine | Port | User | Password | Database |
| PostgreSQL | 5432 | kameha | kameha | kamehadb |
| MySQL | 3306 | kameha | kameha | kamehadb |
| MariaDB | 3307 | kameha | kameha | kamehadb |
| Redis | 6379 | — | — | — |
| MongoDB | 27017 | — | — | — |
| SQL Server | 1433 | sa | Kameha1! | kamehadb |
| Oracle | 1521 | SYS | oracle | ORCLPDB1 |
| ClickHouse | 8123 | default | default | kamehadb |
| DuckDB | 5433 | — | — | — |
Testing And Verification
pnpm testruns workspace package tests; the desktop package usesvitest runpnpm test:goruns the Go backend suite (go test ./...)pnpm lint:goruns golangci-lint andpnpm format:goruns gofumpt+goimports; both resolve the tool from thego.modtooldirective, so no machine-level install is needed..golangci.ymlholds the config. The pre-commit hook formats staged.gofiles, then runs the repository-wide lint because golangci-lint cannot lint named files from multiple directories in one invocation; lint-staged runs task groups serially to limit resource contention. The pre-push hook also runspnpm lint:goacross the whole repo.- Backend changes should also be verified with
go build ./...and, when bindings change,wails generate module - CI runs
pnpm typecheck, desktoptsc --noEmit,pnpm lint, desktop tests,go test ./..., and a fullwails build - When changing bound service signatures, regenerate bindings and verify the desktop
tscpass — shape drift surfaces as type errors inwailsjs/ - When changing desktop UI behavior, prefer running the desktop tests and a targeted
wails build
Logs And Diagnostics
- The desktop app exposes a built-in Logs page that reads frontend and backend logs from one place.
- Frontend runtime errors are forwarded through
apps/desktop/src/lib/app-logs.tsinto the Go log store viaLogsService.AppendFrontendLog. - Backend logs are written by
internal/logsto${app_data_dir}/logs/app.logas JSON lines;internal/logsalso tailsfrontend.logand merges legacytauri.log/sidecar.logfiles when present. - If a bundled workflow fails only in the built app, check the in-app Logs page first, then inspect
${KAMEHADB_DATA_DIR}/logs/if you need the raw files.
Release Workflow
The checked-in GitHub workflow is .github/workflows/release.yml.
Key facts:
- Releases are triggered by tags matching
v* workflow_dispatchexpects an existing tag input- The workflow creates a draft GitHub release, builds per-OS binaries via
wails build(macOS universal.appzip, Linux amd64 tarball, Windows amd64.exe), then uploads assets - GitHub still adds source archives automatically; those are not the installable app bundles
Typical release flow:
git push origin <branch>
git tag v0.1.0-rc.1
git push origin v0.1.0-rc.1Behavioral Guidelines
These guidelines prioritize caution and precision over speed.
1. Think Before Coding
- No Assumptions: Surface tradeoffs explicitly. If uncertain or multiple interpretations exist, ask before picking.
- Push Back: If a simpler approach exists or the requested path is flawed, suggest an alternative.
- Clarify First: If a request is unclear, stop and name the specific confusion.
2. Simplicity First
- Minimum Viable Code: Implement only what is asked. No speculative features or "future-proofing."
- No Over-Abstraction: Avoid abstractions for single-use code.
- Surgical Error Handling: Do not add error handling for impossible scenarios.
- Aggressive Simplification: If a solution is overcomplicated, rewrite it to be simpler.
3. Surgical Changes
- Zero Collateral Damage: Do not "improve" adjacent code, comments, or formatting.
- Style Match: Match the existing codebase style strictly, even if you prefer another pattern.
- Orphan Cleanup: Remove imports/variables that YOUR changes made unused. Do not touch pre-existing dead code unless asked.
- Traceability: Every changed line must trace directly back to the user's request.
4. Goal-Driven Execution
- Verifiable Goals: Transform "fix bug" into "write reproducing test $\rightarrow$ make it pass."
- Structured Plans: For multi-step tasks, define:
[Step] $\rightarrow$ verify: [check]. - Verification Gate: No task is "done" until success criteria are verified via tool output.
5. Always Use shadcn Components
- Rule: ALWAYS use the shadcn UI components from
apps/desktop/src/components/ui/instead of raw HTML elements when an equivalent exists. - Available components (in
ui/):Button,Input,Textarea,Label,Select(+ parts),Table(+ parts),Card,Badge,Dialog,Sheet,DropdownMenu,Tabs,Tooltip,ScrollArea,Progress,Separator,Command,Sonnertoaster. - Mapping:
<input>→<Input><textarea>→<Textarea><label>→<Label><button>→<Button>(usevariant/sizeprops, not bespoke className hacks)<select>→<Select>+<SelectTrigger>+<SelectContent>+<SelectItem>+<SelectValue><table>/<thead>/<tbody>/<tr>/<th>/<td>→<Table>/<TableHeader>/<TableBody>/<TableRow>/<TableHead>/<TableCell>
- No new shadcn components without a shadcn CLI install — if a shadcn component does not exist in
ui/, install it via the shadcn CLI before using it; never hand-roll a parallel component. - Acceptable exceptions (document the reason inline): buttons required by a third-party library (e.g. React Flow's
<Controls>), elements with requiredroleattributes that shadcn doesn't expose (e.g.role="switch"toggles).
6. No Magic Strings or Numbers
- Rule: Never hardcode database kind strings (e.g.
'postgres','mysql'), port numbers, timeout values, or cache durations as literals in application code. Always use the shared constants. - Use
KINDfrom@kamehadb/shared: All database kind comparisons must useKIND.POSTGRES,KIND.MYSQL, etc. — never raw string literals. - Use
DEFAULT_PORTS: All port numbers must come fromDEFAULT_PORTS[KIND.X]— never hardcode5432,3306, etc. - Use timeout constants: All timeouts, cache durations, and intervals must use named constants from
apps/desktop/src/lib/constants.ts(frontend) or theinternal/package that owns the behavior — never inline5000,30000, etc. - Use
ALL_KINDS,SQL_KINDS,NOSQL_KINDS: When iterating over or validating database kinds, use these arrays — never inline a list of kind strings. - Use helper functions:
isSqlKind(),isNoSqlKind(),isPasswordRequired(),isFileDatabaseKind()— never write manualkind === 'postgres' || kind === 'mysql'chains. - Use
PROTOCOL_ALIASES: For URL protocol parsing, use the sharedPROTOCOL_ALIASESmap — never hardcode'postgresql'or'rediss'. - Zod enums: Use
z.enum(ALL_KINDS as [string, ...string[]])— never inline a list of kind string literals. - SQL CHECK constraints: Generate from
ALL_KINDS— never inline a list of kind string literals. - Exception: String literals inside SQL query text (e.g.
'mysql' AS applicationName) are SQL values, not DbKind comparisons — these are acceptable. - Exception: Minor query config values like
retry: 1are not considered magic numbers.
7. Always Comment Non-Trivial Code (How / Why / What)
- Rule: Every non-trivial function, hook, or block of logic must carry a short comment that explains the what (one line), the why (one line of intent / tradeoff), and the how only when the mechanism is non-obvious.
- What is "non-trivial": anything that isn't a one-liner that re-states its name. Trivial
return x + 1lines don't need a comment. A new function, a hook, a state machine, a tricky expression, a side effect, a workaround — these all do. - Comment style (match the existing project style; short, plain prose):
// Resize a column by direct DOM mutation during the drag for smoothness, // then commit the final pixel width to React state on mouseup so re-renders // only happen once per drag. (How / Why / What) - Bad: comments that just repeat the function name (
// Increments counter), comments that lie, comments without intent ("TODO" without context). - Good: comments that name the tradeoff, call out a workaround, or document a non-obvious invariant.
- No section-header comment walls — keep comments tight and attached to the code they describe.
File Search
For any file search or grep in the current git-indexed directory, use fff tools (ffgrep, fffind) instead of glob or grep. fff is the MCP server at ~/.local/bin/fff-mcp — it's faster, supports smart-case with fuzzy fallback, frecency-ranked results, and git-aware annotations.
Operational Rules
- Package Manager: ALWAYS use
pnpmfor this project, except for thelanding/directory which is managed vianpm. - Changelog: All user-facing changes must be recorded in
CHANGELOG.mdunder[Unreleased]before merging.
Public-Surface Drift Prevention
When a feature wave adds new engines, major workflows, or changes the product descriptor, sync these five surfaces in the same PR so they do not drift:
landing/src/components/home-view.tsx— hero copy, engine carousel, feature cards, Compare panel screenshotslanding/src/app/layout.tsx—<title>,<meta name="description">, keywords, OG/Twitter metadatalanding/src/app/opengraph-image.tsx— the active OG image source; regenerate the animated asset withlanding/scripts/render-og-animated.mjsintolanding/public/og-animated.giflanding/public/images/— Compare panel screenshots (sql-panel.png,chat-panel.png, plus any new ones)README.md— one-liner, feature list, engine table, install docs
Run npm --prefix landing run build and pnpm build after any landing or README change to confirm nothing is broken.
After every material product change, run through this list before merging.
TypeScript Coding Standards
These rules apply to all TypeScript code in apps/, packages/, and landing/.
No Code Duplication
- Search for an existing schema, type, helper, or adapter contract before adding another one; reuse the existing source of truth when it fits.
- Reuse Zod schemas and types from
packages/shared/src/index.ts— it is the source of truth - If the same shape appears in two places, extract it into a shared type or helper
- For logic duplicated across frontend and backend, keep the Go side authoritative and mirror only the shape in
packages/shared - Do not add a general abstraction for a single use or remove a few clear lines only to reduce repetition.
Use Types
- Annotate exported functions, public APIs, and component props explicitly
- Use
typealiases for object shapes, component props, API data, adapter contracts, unions, mapped types, and utility compositions; do not introduceinterfacedeclarations. - Convert an existing
interfaceto atypewhen editing that declaration. Useinterfaceonly when TypeScript declaration merging or an external API requires it, and explain the exception next to the declaration. - Never use
any— useunknownand narrow with type guards
Use Union Types
Prefer string literal unions over enums:
type QueryStatus = 'idle' | 'running' | 'success' | 'error';- When a value can be one of several shapes, model it as a discriminated union (see below)
Emit Type When Possible
Derive types from values so runtime and types stay in sync:
// typeof for object literals
const ADAPTER_LIMITS = { postgres: 100, mysql: 50 } as const;
type AdapterLimits = typeof ADAPTER_LIMITS;
// ReturnType / Awaited for function and promise return types
type Connection = Awaited<ReturnType<typeof loadConnection>>;
// z.infer for Zod schemas
const connectionSchema = z.object({ host: z.string(), port: z.number() });
type ConnectionInput = z.infer<typeof connectionSchema>;This avoids drift between the schema and the type.
Discriminated Unions
Use a literal "tag" field so the compiler narrows automatically:
type SqlResult =
| { kind: 'rows'; columns: string[]; rows: unknown[][] }
| { kind: 'affected'; count: number }
| { kind: 'error'; message: string };
function format(result: SqlResult): string {
switch (result.kind) {
case 'rows':
return `${result.rows.length} rows`;
case 'affected':
return `${result.count} affected`;
case 'error':
return result.message;
}
}- Use
kind,type, orstatusas the discriminator field — pick one and stay consistent - Use
as conston values that feed the union so literal types are preserved - Exhaustive
switchwith aneverdefault catches missed branches at compile time
Code Comments
For code that is long or has moderate-to-high complexity, add clear comments. Trivial code stays uncommented — match the existing density in the file.
When To Comment
- A function or block runs past ~30 lines
- Logic has non-obvious branches, side effects, or invariants
- Magic numbers, regex, or domain-specific constants appear
- Async, timing, retry, or concurrency behavior is hard to follow
- The reader would have to hold more than 2–3 things in their head at once
What To Write
- Why the code exists or why this approach was chosen
- Non-obvious invariants: "this list is always sorted by
createdAtdesc" - Correctness or performance tradeoffs the code encodes
- Pointer to the ticket, spec, or external constraint that drove the decision
What To Skip
- Restating what the code does in English
- Section banners like
// ============ Validation ============ - Comments that just rename a variable or repeat the line below
// GOOD: explains the why
// SQLite returns BigInt for INTEGER columns; clamp to MAX_SAFE_INTEGER
// to avoid JSON serialization precision loss above 2^53.
const id = Number(row.id % Number.MAX_SAFE_INTEGER);
// BAD: restates the what
// Convert id to number
const id = Number(row.id);Style
- One short line per comment is the default; multi-line only when truly needed
- Place the comment above the line it explains, not as a trailing line
- Use full sentences with proper punctuation; no "TODO later" or "fix me" leftovers
Agent Devkit Skills
This repo uses Agent Devkit for shared agent workflows. Skills live in .agents/skills/; using-devkit routes each task to its owning workflow. The bump-version and preparing-releases skills are repository-specific and remain alongside the Devkit set.
Available Agent Devkit Skills
| Skill | Use |
using-devkit | Select the owning workflow skill |
brainstorm-feature | Clarify new, ambiguous, or behavior-changing requests |
plan-feature | Plan approved non-trivial designs |
implement-task | Implement an approved bounded task or plan |
read-codebase-context | Trace code, callers, dependencies, and tests |
systematic-debugging | Investigate bugs, failures, and unexpected behavior |
review-and-verify | Review diffs and verify changes |
setup-codebase | Set up repository context and conventions |
setup-openez | Set up or refresh OpenEZ when needed |
document-wiki | Create or refresh the LLM-facing wiki |
lean-audit | Audit the repository for unnecessary complexity |
estimate-feature | Estimate work from an implementation plan |
context-handoff | Prepare a handoff when work must pause |
Repository-Specific Skills
bump-version— update the app version and changelog.preparing-releases— prepare and verify a desktop release.
Use a skill when its description matches the task. User instructions and this file take precedence over skills.
<!-- openez:start -->OpenEZ workflow
- Before code work in a new session, call
memory_recallusing 1–3 keywords from the task. - Use
code_querybefore filesystem search. - Use
code_contextfor symbol/file relationships. - Call
memory_writeafter an architectural decision or a non-obvious constraint is confirmed. - Use explicit workspace scope for cross-workspace work.
<!-- openez:end -->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.

