Skip to content

Latest commit

 

History

History
130 lines (104 loc) · 5.82 KB

File metadata and controls

130 lines (104 loc) · 5.82 KB

AGENTS.md

Guidelines for agents working on Berd.

Berd is a standalone Tauri 2 + React 19 desktop. ACP is the main interface we use for the actual agent loop - creating and running sessions, finding available models, and setting configuration. When available, we work over ACP methods, but the UI can handle operations that are not yet in ACP or are client specific.

Layout

  • src/ — React UI/features/shared code
  • src-tauri/ — Tauri shell that starts or resolves goose serve
  • sdk/ — vendored @aaif/goose-sdk package and generated ACP types
  • distro/ — bundled app defaults and packaged distribution assets
  • goose-backend.lock.json — pinned upstream Goose backend used by dev and bundles
  • scripts/ensure-local-goose.sh — managed local Goose checkout for dev
  • scripts/prepare-goose-sidecar.sh — stages the pinned or explicit Goose binary for Tauri bundling
  • scripts/update-goose-backend-lock.sh — resolves and records a new Goose backend pin
  • src/features/berdctl/ — berdctl command registry
  • src-tauri/plugins/berdctl/ — berdctl broker
  • src-tauri/crates/berdctl/ — bundled berdctl CLI
  • distro/skills/berd-help/references/berdctl.md — berdctl guidance agents read from the bundled berd-help skill

Architectural laws

LAWS/ defines required product and user experience behavior. Before planning, implementing, or reviewing behavior changes, read LAWS/README.md and every law file relevant to the affected behavior. Laws take correctness precedence over the current code and tests; when they disagree, change the implementation and tests or explicitly propose a product-approved law change.

Startup assets

Startup artifact media is resolved by the Tauri backend and returned as local cache paths. Renderer code should use getArtifacts() or selectProjectPreviewArtifacts() from src/shared/api/artifacts.ts, then pass paths through convertFileSrc(..., "asset") before rendering media. Do not vendor startup media, fetch catalogs in the renderer, or construct CDN URLs in UI code.

Experimental features

Experiments are opt-in, user-local switches for in-progress UI or workflow behavior. Use .agents/skills/experimental-features/SKILL.md before adding, reviewing, graduating, or removing an experiment.

Do not create one-off localStorage keys, distro flags, Tauri commands, or capabilities for per-user experiments unless the skill says the use case requires it.

Common commands

  • just setup — install pnpm deps, build SDK, build managed local Goose
  • just dev — run the Tauri app in dev mode
  • just fmt — format frontend and Tauri/Rust files
  • just fmt-check — check frontend and Tauri/Rust formatting
  • just lint — Biome lint checks
  • just typecheck — TypeScript type checks
  • just check — frontend formatting/lint/i18n/type checks
  • just test — Vitest suite
  • just tauri-check — Rust check with external sidecars disabled
  • just clippy — Rust clippy with warnings denied
  • just ci — local validation gate: frontend checks, Tauri/Rust checks, clippy, tests, build
  • just bundle — stage the pinned Goose backend and run pnpm tauri build

When to validate

  • Frontend changes: just check
  • Vitest-covered behavior: just test
  • src-tauri/, Tauri config, sidecars, or Rust: just tauri-check
  • berdctl commands: pnpm generate:berdctl-contract, pnpm vitest run src/features/berdctl, and cargo test -p berdctl (from src-tauri/)
  • Broad/release/packaging changes: just ci

berdctl

berdctl lets agents control the app: CLI → broker → renderer registry. Design and reasoning: docs/berdctl-architecture.md. To add or change a command, use .agents/skills/berdctl-new-command/SKILL.md (just new-command <noun> <verb>).

Invariants (1, 3, 4 are gated by test failures; 2, 5, 6 are review rules — the doc has the whys and the enforcement map):

  1. No command-specific knowledge below the renderer registry — the broker stays transport-only (single reviewed exception: the create-cap's action == "create" peek).
  2. Single dispatch point in the renderer.
  3. Bounds live in zod; clap only mirrors them.
  4. Help is hand-authored in the command module (summary, description, helpFooter, .describe() per field); cargo test -p berdctl fails on empty/TODO prose.
  5. UI-visible verbs only; prefer reversible mutations, but one-way visible product actions like creating a session or sending a prompt are allowed. Delete, bulk, silent, or invisible work reopens the auth decision as a design review, not a PR.
  6. Reviewers identify breaking wire reshapes and bump protocolVersion in both discovery.rs copies and the contract.ts mirror; tests pin only that the constants are equal.

The CLI is built from the contract at startup: command modules (zod schemas

  • help prose) → pnpm generate:berdctl-contractapi-surface.json (the client-neutral wire surface, with JSON Schema per action) + cli-surface.json (the CLI projection) → embedded by the berdctl crate, whose tree.rs builds the clap tree at runtime (validate.rs gates consistency via the crate's tests). Never hand-edit the contract JSONs.

Sidecar rule

Release builds should use the Goose backend pinned in goose-backend.lock.json:

just setup
just bundle

The Tauri config uses "externalBin": ["binaries/goosed"]; the staging script copies to src-tauri/binaries/goosed-$(rustc -vV | sed -n 's|host: ||p'), which is the filename Tauri expects. Use GOOSE_BIN=/path/to/goose only as an explicit local override.

Conventions

  • Use @/ imports for frontend code.
  • Use cn() from @/shared/lib/cn for Tailwind class merging.
  • All <button> elements need type="button" unless intentionally submitting.
  • Do not hand-edit generated SDK files unless this repo intentionally freezes a generated snapshot; prefer updating sdk/schema/* and regenerating.