Imported from withcoral/coral (
AGENTS.md). Install upstream withnpx skills add withcoral/coral. Copyright stays with the author.
AGENTS.md
Repo Map
crates/coral-api: protobuf contract and generated Rust bindings.crates/coral-app: local server composition, state, workspaces, source lifecycle, and workspace-scoped catalog discovery behavior.crates/coral-cli: terminal adapter.crates/coral-client: intentionally thin transport bootstrap plus Arrow IPC decode/render helpers.crates/coral-engine: engine-side backend compilation, runtime registration, and query execution.crates/coral-mcp: MCP tool core with stdio and Streamable HTTP transport adapters overcoral-client.crates/coral-spec: declarative source-spec parsing, validation, input discovery, and normalized source-definition models.crates/coral-telemetry: cross-crate telemetry helpers that are independent of app bootstrap, query runtime, and adapter surfaces.apps/coral-ui: React Router/Wax frontend shell, npm packagecoral-ui. It is validated independently and is not built by Rust crate build scripts.apps/desktop: Electron shell around Coral UI and the local Coral sidecar.apps/docs: Mintlify documentation site.plugins/coral: Agent plugin packaging.plugins/coral/skillsis the canonical in-repo home for maintained Coral agent skills.
Rules
- Run
make rust-checksbefore submitting PRs that include changes to Rust code. - For Postgres-backed database changes, run
make postgres-tests. Keep this as the single entry point for local and CI Postgres coverage; do not duplicate its Cargo test invocations in workflows or contributor instructions. The target usesCORAL_TEST_POSTGRES_URLwhen supplied. Otherwise it starts a local Docker Postgres and creates a fresh database inside the reusable container. Docker chooses an available localhost port by default; usemake postgres-urlto print the server URL orLOCAL_POSTGRES_PORT=55432 make postgres-startwhen you need a stable port. Usemake postgres-startwhen you only need the server,make postgres-stopwhen finished, andmake postgres-cleanto remove the reusable container. - Run
make schema-checkbefore submitting PRs that touch generated manifest schemas or the Rust helpers that generate them. Usemake schema-generateto refresh generated schema files. The Validate workflow enforces this through itsschema-freshnessjob when schema inputs change. - Coral UI changes must pass
npm run check --prefix apps/coral-ui,npm run typecheck --prefix apps/coral-ui,npm test --prefix apps/coral-ui, andnpm run build --prefix apps/coral-ui, followed bynpm run test:server --prefix apps/coral-ui, before submitting. The production server smoke test consumes the build output and runs on every Coral UI CI job. - Desktop changes must pass
npm run check --prefix apps/desktopandnpm test --prefix apps/desktopbefore submitting. - Do not add Vitest coverage to
apps/coral-uifor new work. The app is exempt from the repo test-writing expectation. Existing tests stay and must keep passing. Add a test there only when the user asks for it, or to lock an explicit architectural invariant such asapp/routes.test.tsandapp/__tests__/architecture.test.ts. Never extract a single-use helper into its own module so that a test has something to assert against. The architecture test rejects any test file underapp/components,app/views, andapp/wax/componentsat zero violations, and holdsallowedTests, the recorded list of every other test file the app carries. A new test anywhere underapp/fails until someone adds its path to that list. - Use Storybook and Chromatic for Coral UI component visual states.
- Coral UI styling uses vanilla-extract; do not introduce Tailwind.
- Run
make perf-checkbefore submitting PRs that could affect CLI startup, local server bootstrap, source registration, orcoral.tablescatalog query latency. CI installs the bundledgithubsource with fake credentials and fails when releasecoral sql "select * from coral.tables"has a hyperfine mean above 750 ms. - Pull requests do not automatically build macOS Desktop packages. Use manual dispatch for an unsigned packaging preflight when a distribution-sensitive change warrants one. Validation artifacts stay unsigned and must not be reused for a release; Desktop release publishing must rebuild from a clean checkout with signing and notarization.
- The
Validateworkflow intentionally skips draft pull request runs, starts again onready_for_review, and still triggers onconverted_to_draftso the replacement skipped run cancels any in-progress validation for the PR branch. Keep that draft gate aligned between the initial change detector and final aggregatevalidatejob. - Keep Release Please branch updates coalesced and cheap to supersede. The
release-pleaseworkflow may create multiple local regeneration commits, but must push them together through its final push step.Validateintentionally givesrelease-please--*pull requests a 120-second settle period before checkout and change detection so concurrency cancellation stops intermediate branch states before expensive jobs fan out. make rust-checksis the Rust-only local gate and should keep using--all-features.- Coral UI is built by its own repository and CI orchestration; the CLI does not embed browser assets.
- Use
make docker-buildto compile the current checkout in a native Linux BuildKit stage and package that binary ascoral:local. SetDOCKER_IMAGE=coral:testto change the local tag orDOCKER_NO_CACHE=1to bypass Docker layer caching. Keep the exported-binary layout and runtime platform aligned with thedocker-publishworkflow; local Docker-exporter loads disable provenance because that exporter cannot load attestation manifests. Local builds must not download a published Coral binary. - Use
make coral-ui-docker-buildto build Coral UI from the current checkout andmake coral-ui-docker-smoketo run the configuration matrix against an already-built Coral UI image. Use the self-containedmake coral-ui-docker-testfor both. That matrix is peer-free: it asserts which runtime configurations boot and which fail fast, while readiness against a live Coral is covered by the mocked health client inapps/coral-ui/app/routes/readyz.server.test.ts. - Use
make coral-docker-stub-testto build the Coral image with a stub binary and exercisedocker/entrypoint.sh(config seeding, seed-once semantics, and the unwritable-volume failure). The entrypoint is pure shell up to its closing exec, so this needs no Rust build; the real binary is covered bymake rust-checksand the real image by the release smoke in.github/workflows/docker-publish.yml. Coral UI's runtime stage must remain COPY-only and non-root; build and dependency stages run on the build platform. Local builds follow the Docker daemon's architecture, while CI builds and verifies linux/amd64 only. TLS termination belongs to the operator and is not provisioned by the image or its smoke harness. - Keep adapters thin. If CLI or MCP behavior gets complex, move it inward.
- Keep server topology orchestration private to
coral-cliwhile CLI commands are its only consumers. Do not extract the orchestration into a shared orchestration crate unless it gains a non-CLI consumer; the combined topology is provisional and may be removed rather than promoted. - Keep transport contract concerns in
coral-api, source-spec concerns incoral-spec, app/state concerns incoral-app, and query/runtime concerns incoral-engine. - Keep app-owned runtime package assembly in
coral-app.coral-engineshould compile generic runtime components, not interpret DSL v4 authored manifests, materialized fingerprints, semantic IR, or projection catalogs. - Keep Coral UI Coral access behind React Router server loaders, actions, or
resource routes using
apps/coral-ui/app/lib/coral-request.server.ts. Do not expose a generic renderer-to-Coral transport or Desktop sidecar proxy; add an explicit server route when browser-triggered Coral behavior is needed. - Keep Coral UI data access in React Router loaders and actions. Presentation
(
app/components,app/views,app/wax/components) renders loader data and submits through fetchers: it must not import*.servermodules, open a network connection, reachwindow.coralDesktop, or await insideuseEffect. The architecture test enforces all four at zero violations. An effect that awaits is the specific mistake to watch for — it rebuilds the router's caching, pending state, and revalidation in component state, worse each time. - The packaged Coral UI server resolves its external runtime packages from the
Electron app. Keep every
apps/coral-uiproduction dependency represented inapps/desktopproduction dependencies; the desktop config tests enforce this packaging contract. - Use
CORAL_DESKTOP_APP=1as Coral UI's single external desktop build marker. React Router route composition may read it fromprocess.env, whileapps/coral-ui/vite.config.tsexposes only its compiled boolean value asimport.meta.env.CORAL_DESKTOP_APP. Do not add a parallelVITE_CORAL_DESKTOP_APPmarker or expose broaderCORAL_*values to browser code. - For DSL v4 materialization, the user owns when a source is generated or regenerated. Coral materializes at source add, queries only from the installed materialized package, and never silently refreshes descriptors, projections, or persisted artifacts. Treat fingerprints, producer versions, identity metadata, and raw-document hashes as advisory provenance: report mismatches through tracing, but load readable, structurally compatible artifacts. Isolate source-local compatibility failures without hiding operational failures.
- A DSL v4 source declares top-level
inputs:and exactly one singularsurface:. The sourcenameis its SQL namespace. Do not add surface ids, namespace suffixes, or multiple surfaces to one manifest; represent distinct provider interfaces as distinct source specs instead. - Keep cross-crate W3C trace-context propagation helpers in
coral-telemetry; do not makecoral-app,coral-client,coral-engine, orcoral-mcpdepend on each other just to share telemetry carrier logic. - Keep shared Arrow IPC decoding and result rendering in
coral-client. - Treat
coral-appas an internal composition root even if sibling crates use its bootstrap seam today. - If a caller needs explicit local server control, prefer
coral-client::localover widening the default client surface. - Keep process environment access owned by the right crate.
coral-appowns runtime/bootstrap env reads,coral-cliowns CLI-surface env reads, and other crates should receive explicit values from callers instead of reading ambient process environment directly. - Keep docs lean and readable. For CLI or MCP changes, update
apps/docs/only when the change affects a public surface or captures important user-facing or contributor-facing knowledge. Do not document every implementation detail. When docs are warranted, choose the best existing location first and make the amount of space match the feature's user-facing weight and visibility. - Keep stable bundled sources under
sources/core/**; put preview DSL v4 source specs undersources/v4/[source]/manifest.yamlwith distinct manifest names (defined in the manifest'snamefield) such as<name>_v4. When a provider has distinct interfaces, use sibling source directories such asgithubandgithub_mcp. Do not bundlesources/v4into the binary; install preview v4 sources withcoral source add --file. Do not replace or migrate an existing v3 source merely because a preview v4 spec exists. - Changes to
scripts/install.shmust keep theValidateworkflow's install-script matrix in sync with every OS/architecture target that the installer supports. - Keep general repository automation in
xtask; reservescripts/for the bash Coral installer and installer-specific support. - Keep
xtaskorganized by workflow: docs generation lives underxtask/src/docs/, shared source-manifest discovery lives inxtask/src/sources.rs, command-latency checks live inxtask/src/perf.rs, benchmark dispatch lives underxtask/src/benchmarks/, and the isolated benchmark package and fixtures live underxtask/benchmarks/. Skill export lives inxtask/src/skills.rs. Release signing and notarization automation lives inxtask/src/release.rs. The DSL v4 inference report lives inxtask/src/metadata_report.rs. - Use
cargo run --locked -p xtask -- benchmark list-columnsto measure the complete MCPlist_columnsresponse for the checked-in synthetic wide-table fixture with theo200k_basetokenizer. The benchmark must call the real MCP tool in-process, report without enforcing a token budget, and keep benchmark-only code out of production crates. - Use
cargo run --locked -p xtask -- v4-metadata-reportbefore and after a change to DSL v4 row-path, pagination, or lookup-key inference, and diff the two reports. It imports every non-MCP v4 source undersources/v4and emits one CSV row per operation, so an unintended reshape in a source nobody was thinking about shows up as a diff hunk. Pass--cache-dirso a before/after pair fetches each descriptor once. It is deliberately not wired into CI: it fetches multi-megabyte vendor descriptors over the network, and vendor descriptors change under us, so a green run proves nothing about the commit that produced it. - Universal Search relevance benchmarking also lives in the isolated
coral-benchmarkspackage. Keep real catalog inventories, generated questions, collected queries, responses, focused corpora, and replay reports under ignored run directories. Only synthetic, deliberately non-sensitive benchmark fixtures may be checked in. Use frozen-query replay rather than rerunning agents while tuning ranking weights, and do not run agent collection in CI. - The Electron desktop app version is tied to the CLI release version through
release-please. The release workflow builds the macOS desktop app from
apps/desktop, uploads its DMG/ZIP/update metadata to the same GitHub Release as the CLI artifacts, and the website should link to thereleases/latest/downloadDMG rather than storing desktop binaries itself. make docs-checkintentionally skips the aggregate community source catalog. Any PR may leave that generated page stale so unrelated changes do not fail on aggregate community catalog drift; keep docs freshness strict for bundled sources undersources/core/**,apps/docs/docs.json, and the changelog.- The live docs site deploys from the long-lived
docsbranch, notmain, so the published catalog matches the latest released binary.mainstill owns docs freshness, but merging tomainno longer publishes the site by itself: the release workflow advancesdocsafter release artifacts are published. Seeapps/docs/AGENTS.mdfor the full publishing model. - Keep checked-in generated files marked in
.gitattributeswithlinguist-generatedso GitHub collapses them by default in PR diffs. - Source inputs that carry credentials must be
kind: secret, neverkind: variable. This includes API keys, bearer tokens, access tokens, passwords, private keys, authorization header values, and admin/read keys, even when the credential is read-only or the source also supports anonymous access. - When source credential retrieval or auth guidance changes, keep the source
spec docs and maintained Coral source-spec skills aligned in the same change.
OAuth source-spec behavior needs both reader-facing docs and agent-facing
author/review guidance because
credential.methodscontrols setup whileauthstill controls runtime requests. - Keep maintained Coral agent skills in
plugins/coral/skills. External distribution repos or packages should mirror from that directory rather than becoming a separate source of truth. Usecargo run --locked -p xtask -- export-skills --dest <path>for local export checks and distribution syncs. - Keep
plugins/coralconformant with Agent Plugins 1.0: portable metadata belongs in rootplugin.json, skills are discovered fromskills/, and MCP servers are declared in rootmcp.json. Keep the legacy.codex-plugin,.mcp.json, and.app.jsonpackage files for pre-0.147 Codex compatibility. Put current Codex-only metadata underextensions.com.openai, and align shared metadata and MCP invocation across both representations. - Coral skills must include
agents/openai.yaml. Keepinterface.display_namein the formCoralorCoral <Title Case Suffix>, keep the top-levelSKILL.mdheading equal to that display name, and set non-emptyshort_descriptionanddefault_promptvalues. The default prompt should mention the skill token, such as$coral-create-source-spec. - When proposing or updating a PR title, use Conventional Commits:
type(scope): summary. - When using a scope, prefer one that matches the primary area changed,
usually the crate name minus the
coral-prefix,docs,sources/core/<name>, orsources/community/<name>. - Keep the PR title up to date as the branch evolves. If the change shifts in scope or intent, update the title to match the current final shape of the branch.
- Use
!only for breaking changes, placing it immediately before the colon:type!: summaryortype(scope)!: summary. Local WIP commit messages can stay pragmatic unless the user explicitly asks for polished commit history. - If you add a source using dummy credentials in order to test a change, always configure Coral to store those credentials on the filesystem. Do not store dummy credentials in the OS keychain.
Meta Changes
A meta change modifies how contributors or agents should work in this repo, not only runtime behavior. Examples include repo layout, crate ownership, source directory conventions, docs generation behavior, CLI/MCP surface rules, PR title/scope guidance, verification commands, and agent-facing review or source-authoring instructions.
For meta changes:
- Update the nearest relevant
AGENTS.mdin the same change. - Update
apps/docs/, generated docs, or docs tooling only when the changed behavior is user-facing or docs-authoring-facing, and use the smallest useful edit in the best existing location. - Preserve provenance: keep observed repo facts, project direction, local preferences, and generated context separate instead of merging them into one untraceable rule.
- Treat repeated human steering as a defect in the operating loop. Identify the failure class, update durable context or tooling when that can prevent recurrence, and verify the new rule before resuming unrelated work.
- Include explicit validation showing the guidance matches the implemented behavior.
- Mention in the PR description what agent or contributor behavior changed.
What Counts As a Breaking Change for a CLI?
For a CLI, the user interface is the API.
A change is breaking if it can break existing:
- commands people run manually
- scripts and CI jobs
- documented workflows
- integrations that parse output
Treat these as stable contract surfaces:
- command/subcommand names
- flags and positional arguments
- exit codes
- structured output (for example JSON)
- config file keys, format, and location
- environment variables and precedence rules
If any of those change incompatibly, it is a breaking change.
