agentleFS
asta-nguyenasta-nguyen/kamehadb/AGENTS.md

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

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
  1. Very specific:

    When changing bound service signatures, regenerate bindings and verify the desktop tsc pass — shape drift surfaces as type errors in …

    line 197
  2. Very specific:

    When changing desktop UI behavior, prefer running the desktop tests and a targeted wails build

    line 198
  3. Very specific:

    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 …

    line 205
  4. Distinctive:

    Push Back: If a simpler approach exists or the requested path is flawed, suggest an alternative.

    line 233
  5. Distinctive:

    Clarify First: If a request is unclear, stop and name the specific confusion.

    line 234
  6. Distinctive:

    No Over-Abstraction: Avoid abstractions for single-use code.

    line 239
  7. Distinctive:

    Surgical Error Handling: Do not add error handling for impossible scenarios.

    line 240
  8. Distinctive:

    Aggressive Simplification: If a solution is overcomplicated, rewrite it to be simpler.

    line 241
  9. Distinctive:

    Zero Collateral Damage: Do not "improve" adjacent code, comments, or formatting.

    line 245
  10. Distinctive:

    Orphan Cleanup: Remove imports/variables that YOUR changes made unused.

    line 247
  11. Distinctive:

    Traceability: Every changed line must trace directly back to the user's request.

    line 248
  12. Distinctive:

    Verification Gate: No task is "done" until success criteria are verified via tool output.

    line 254
  13. Very specific:

    Rule: ALWAYS use the shadcn UI components from apps/desktop/src/components/ui/ instead of raw HTML elements when an equivalent exists.

    line 258
  14. Very specific:

    Rule: Never hardcode database kind strings (e.g.

    line 272
  15. Very specific:

    Use KIND from @kamehadb/shared: All database kind comparisons must use KIND.POSTGRES, KIND.MYSQL, etc.

    line 273
  16. Very specific:

    Use DEFAULT_PORTS: All port numbers must come from DEFAULT_PORTS[KIND.X] — never hardcode 5432, 3306, etc.

    line 274
  17. Very specific:

    Use timeout constants: All timeouts, cache durations, and intervals must use named constants from apps/desktop/src/lib/constants.ts …

    line 275
  18. Very specific:

    Use ALL_KINDS, SQL_KINDS, NOSQL_KINDS: When iterating over or validating database kinds, use these arrays — never inline a list of …

    line 276
  19. Very specific:

    Zod enums: Use z.enum(ALL_KINDS as [string, ...string[]]) — never inline a list of kind string literals.

    line 279
  20. Distinctive:

    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 …

    line 286
  21. Very specific:

    Package Manager: ALWAYS use pnpm for this project, except for the landing/ directory which is managed via npm.

    line 304
  22. Very specific:

    Changelog: All user-facing changes must be recorded in CHANGELOG.md under [Unreleased] before merging.

    line 305
  23. Distinctive:

    When a feature wave adds new engines, major workflows, or changes the product descriptor, sync these five surfaces in the same PR so they …

    line 309
  24. Very specific:

    Run npm --prefix landing run build and pnpm build after any landing or README change to confirm nothing is broken.

    line 317
  25. Distinctive:

    After every material product change, run through this list before merging.

    line 319
  26. Distinctive:

    Search for an existing schema, type, helper, or adapter contract before adding another one.

    line 327
  27. Distinctive:

    If the same shape appears in two places, extract it into a shared type or helper

    line 329
  28. Distinctive:

    Do not add a general abstraction for a single use or remove a few clear lines only to reduce repetition.

    line 331
  29. Very specific:

    Use type aliases for object shapes, component props, API data, adapter contracts, unions, mapped types, and utility compositions.

    line 336
  30. Very specific:

    Never use any — use unknown and narrow with type guards

    line 338
  31. Distinctive:

    Prefer string literal unions over enums:

    line 342
  32. Distinctive:

    When a value can be one of several shapes, model it as a discriminated union (see below)

    line 348
  33. Distinctive:

    Use a literal "tag" field so the compiler narrows automatically:

    line 371
  34. Very specific:

    Use kind, type, or status as the discriminator field — pick one and stay consistent

    line 391
  35. Very specific:

    Use as const on values that feed the union so literal types are preserved

    line 392
  36. Distinctive:

    Place the comment above the line it explains, not as a trailing line

    line 434
  37. Distinctive:

    Use full sentences with proper punctuation.

    line 435
  38. Distinctive:

    Use a skill when its description matches the task.

    line 464
  39. Very specific:

    Before code work in a new session, call memory_recall using 1–3 keywords from the task.

    line 470
  40. Very specific:

    Use code_query before filesystem search.

    line 471
  41. Very specific:

    Use code_context for symbol/file relationships.

    line 472
  42. Very specific:

    Call memory_write after an architectural decision or a non-obvious constraint is confirmed.

    line 473
  43. Distinctive:

    Use explicit workspace scope for cross-workspace work.

    line 474

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

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/MariaDB

Workspace And Package Boundaries

  • The pnpm workspace includes only apps/* and packages/*.
  • landing/ has its own package-lock.json and is managed separately with npm.
  • Most root scripts target the pnpm workspace only. Do not assume they affect landing/ unless they explicitly use npm --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:go

Important 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 panels

Current 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 vault
  • dbcore/ — reusable provider core (no internal/ or Wails imports): dbcore/engines/ holds the SQLAdapter contract and shared helpers, dbcore/providers/<name>/ holds each provider (postgres via pgx, mysql/mariadb, sqlite, sqlserver, oracle, clickhouse, duckdb, mongo, redis), dbcore/providers/all assembles all ten kinds, and dbcore.Manager/Registry own provider lifecycle
  • internal/database/ — app facade wiring the store to the shared manager; internal/engines/ keeps app-only kind metadata (legacy kinds, MCP lists); internal/mongo/ keeps mongosh support
  • internal/api/ — Wails-bound services (ConnectionsService, SqlService, SchemaService, MongoService, RedisService, AiService, QueryHistoryService, McpService, MaintenanceService, TerminalService, LogsService) constructed by NewServices in internal/api/connections.go
  • internal/schema/ — snapshots, diffing, watcher, migration generation
  • internal/terminal/ — shared PTY manager used by the mongosh and psql shells
  • internal/maintenance/ — file-database backup/restore and pg tool resolution
  • internal/mcp/ — read-only MCP server: loopback JSON-RPC listener, tool handlers, adapter manager, managed-account provisioning
  • internal/ai/ — provider client, schema-context indexing, embeddings store
  • internal/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 with wails generate module or wails build).
  • apps/desktop/src/lib/api.ts wraps 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/safeErrorMessage and 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.tsx for connection and schema navigation
  • components/workspace-screen.tsx, components/workspace-tab-bar.tsx, and components/workspace-content.tsx for tab orchestration
  • components/sql-editor.tsx for CodeMirror query editing and execution
  • components/table-view.tsx for SQL table browsing
  • components/schema-graph.tsx for ER diagrams
  • components/schema-timeline.tsx, components/schema-diff-view.tsx, and components/migration-assistant.tsx for schema change workflows
  • components/database-stats.tsx and components/table-stats.tsx for PostgreSQL metrics
  • components/postgres-psql-tab.tsx, components/postgres-backup-dialog.tsx, and components/postgres-restore-dialog.tsx for PostgreSQL maintenance workflows
  • components/mongo-view.tsx, components/mongo-shell.tsx, and components/redis-view.tsx for non-SQL engines
  • components/query-history-panel.tsx for saved SQL history/favorites
  • components/logs-page.tsx for viewing frontend and backend logs inside the app
  • components/ai-chat-panel.tsx, components/api-settings-page.tsx, and components/mcp-settings-section.tsx for AI and MCP

State and data flow:

  • apps/desktop/src/store/index.ts uses TanStack Store for workspace state
  • apps/desktop/src/hooks/ contains TanStack Query-based data hooks
  • apps/desktop/src/lib/code-editor.tsx is the shared CodeMirror 6 wrapper (SQL/Mongo/Redis editors)
  • apps/desktop/src/lib/sql-autocomplete.ts and lib/mongo-autocomplete.ts contain client-side completion logic feeding the editors
  • apps/desktop/src/lib/app-logs.ts sends 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 mongosh session; if mongosh is missing locally, the backend can install an app-managed copy without modifying the user's global installation.

Connection Defaults For Docker

EnginePortUserPasswordDatabase
PostgreSQL5432kamehakamehakamehadb
MySQL3306kamehakamehakamehadb
MariaDB3307kamehakamehakamehadb
Redis6379———
MongoDB27017———
SQL Server1433saKameha1!kamehadb
Oracle1521SYSoracleORCLPDB1
ClickHouse8123defaultdefaultkamehadb
DuckDB5433———

Testing And Verification

  • pnpm test runs workspace package tests; the desktop package uses vitest run
  • pnpm test:go runs the Go backend suite (go test ./...)
  • pnpm lint:go runs golangci-lint and pnpm format:go runs gofumpt+goimports; both resolve the tool from the go.mod tool directive, so no machine-level install is needed. .golangci.yml holds the config. The pre-commit hook formats staged .go files, 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 runs pnpm lint:go across the whole repo.
  • Backend changes should also be verified with go build ./... and, when bindings change, wails generate module
  • CI runs pnpm typecheck, desktop tsc --noEmit, pnpm lint, desktop tests, go test ./..., and a full wails build
  • When changing bound service signatures, regenerate bindings and verify the desktop tsc pass — shape drift surfaces as type errors in wailsjs/
  • 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.ts into the Go log store via LogsService.AppendFrontendLog.
  • Backend logs are written by internal/logs to ${app_data_dir}/logs/app.log as JSON lines; internal/logs also tails frontend.log and merges legacy tauri.log/sidecar.log files 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_dispatch expects an existing tag input
  • The workflow creates a draft GitHub release, builds per-OS binaries via wails build (macOS universal .app zip, 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.1

Behavioral 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, Sonner toaster.
  • Mapping:
    • <input> → <Input>
    • <textarea> → <Textarea>
    • <label> → <Label>
    • <button> → <Button> (use variant/size props, 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 required role attributes 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 KIND from @kamehadb/shared: All database kind comparisons must use KIND.POSTGRES, KIND.MYSQL, etc. — never raw string literals.
  • Use DEFAULT_PORTS: All port numbers must come from DEFAULT_PORTS[KIND.X] — never hardcode 5432, 3306, etc.
  • Use timeout constants: All timeouts, cache durations, and intervals must use named constants from apps/desktop/src/lib/constants.ts (frontend) or the internal/ package that owns the behavior — never inline 5000, 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 manual kind === 'postgres' || kind === 'mysql' chains.
  • Use PROTOCOL_ALIASES: For URL protocol parsing, use the shared PROTOCOL_ALIASES map — 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: 1 are 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 + 1 lines 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 pnpm for this project, except for the landing/ directory which is managed via npm.
  • Changelog: All user-facing changes must be recorded in CHANGELOG.md under [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:

  1. landing/src/components/home-view.tsx — hero copy, engine carousel, feature cards, Compare panel screenshots
  2. landing/src/app/layout.tsx — <title>, <meta name="description">, keywords, OG/Twitter metadata
  3. landing/src/app/opengraph-image.tsx — the active OG image source; regenerate the animated asset with landing/scripts/render-og-animated.mjs into landing/public/og-animated.gif
  4. landing/public/images/ — Compare panel screenshots (sql-panel.png, chat-panel.png, plus any new ones)
  5. 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 type aliases for object shapes, component props, API data, adapter contracts, unions, mapped types, and utility compositions; do not introduce interface declarations.
  • Convert an existing interface to a type when editing that declaration. Use interface only when TypeScript declaration merging or an external API requires it, and explain the exception next to the declaration.
  • Never use any — use unknown and 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, or status as the discriminator field — pick one and stay consistent
  • Use as const on values that feed the union so literal types are preserved
  • Exhaustive switch with a never default 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 createdAt desc"
  • 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

SkillUse
using-devkitSelect the owning workflow skill
brainstorm-featureClarify new, ambiguous, or behavior-changing requests
plan-featurePlan approved non-trivial designs
implement-taskImplement an approved bounded task or plan
read-codebase-contextTrace code, callers, dependencies, and tests
systematic-debuggingInvestigate bugs, failures, and unexpected behavior
review-and-verifyReview diffs and verify changes
setup-codebaseSet up repository context and conventions
setup-openezSet up or refresh OpenEZ when needed
document-wikiCreate or refresh the LLM-facing wiki
lean-auditAudit the repository for unnecessary complexity
estimate-featureEstimate work from an implementation plan
context-handoffPrepare 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_recall using 1–3 keywords from the task.
  • Use code_query before filesystem search.
  • Use code_context for symbol/file relationships.
  • Call memory_write after an architectural decision or a non-obvious constraint is confirmed.
  • Use explicit workspace scope for cross-workspace work.
<!-- openez:end -->

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.