npm install --save-dev @firedrill/cli, followed by npx firedrill init. Until then, use a reviewed packed release artifact or an authorized framework source checkout. The exact available flags are documented in the CLI reference.
For your existing agent, start with local tools:
.firedrill/reports/index.html. This central page lets you search and filter recorded executions, then open an individual report’s task, checks, tool calls and data changes. It refreshes when the CLI or SDK saves reports; no inspector server is required to browse it. A custom --report-dir has its own index.html. The CLI prints this path once as All reports, and JSON/SDK results expose reportIndex.
Individual run folders remain portable evidence bundles. The central index is just navigation over verified bundles; unavailable reports are listed without unsafe links, and bounded-history limits are stated on the page. Copy the index and its run folders together if you intend to share a browsable collection. Keep generated output out of Git.
1. Pick a verified starting path
In an interactive terminal,firedrill init guides tool selection, optional
authoring, and local startup. A catalog package requires installation consent if
missing; custom tools need no key or account. The wizard does not require you to
invent a test task before starting the backend. In JSON, CI, or piped use, bare
init remains read-only. Use --tool, --custom, or a legacy --path to make an
explicit setup selection; --start opts into foreground execution.
--path firedrill-agent and --path coding-agent forms install the
same skill and repository brief under .agents/. Firedrill Agent uses the
separately installed @firedrill/agent and your ANTHROPIC_API_KEY; its default
task is preparing tools, not inventing a test suite. The template path remains an
explicit complete runnable example. The legacy manual path creates a world shell
and probe tool; prefer --custom <id> for an editable stateful backend. Existing
files are never silently replaced. Setup ensures .firedrill/ is Git-ignored.
Alternatively, copy examples/quickstart into a temporary directory or inspect it in place. It contains one intentionally plain agent and one Tool so the framework concepts stay visible.
agent.mjs is the agent being tested; the firedrill/ folder describes its controlled surroundings and tests. The Tool declaration owns record/input/output schemas; its behavior module owns the fake consequences. world.yaml owns shared starting conditions and permissions, scenarios provide starting data or variations, and each drill owns its task and assertions. The example agent is a deterministic HTTP client, not an LLM.
The generated template follows the same folders, with its demonstration agent kept separately in firedrill-example/agent.mjs. Both are teaching conventions, not required project layouts. Resource files are discovered recursively under sourceRoot; descriptive kebab-case filenames with .tool, .scenario, .target, .drill or .suite suffixes make their purpose obvious. YAML, YML and JSON are supported. References use stable in-file IDs, so changing a display title need not move a file.
Existing flat projects remain valid and need no migration. Do not rerun init just to rearrange an existing world. If you choose to move source, preserve IDs, update relative Tool module paths and any configured world path, then validate. Set sourceRoot and world in firedrill.json if you prefer another source folder or world filename; neither tools/ nor any other example subfolder is mandatory.
Run firedrill validate, inspect the discovered work with firedrill plan, then run firedrill. A fresh SQLite world is created, the agent is invoked with only its declared binding, assertions inspect the resulting consequences, and the terminal prints a local HTML report path.
What belongs in Git
The ignored side is reproducible runtime output and may contain synthetic data, model output, and evidence. Provider keys belong in the agent’s normal ignored environment files or secret manager—never in either Firedrill source or reports.
Repository data is the reproducible starting definition, not a live database dump. Each trial, retry, and concurrent run materializes its own SQLite file from the pinned build plus scenario. Runtime Tool calls mutate that isolated file and never write records back into YAML or JSON. Editing repository data creates the starting state for later builds and runs; retained older worlds and evidence remain unchanged. All Tools selected for one trial share that trial’s world database, which is what makes cross-Tool consequences, the clock, pending events, and the ordered journal atomic. A project may therefore retain many SQLite worlds without assigning one database per vendor or Tool.
2. Replace the fixture with the agent’s real boundaries
Work from the interfaces the agent already uses:- Model each required action surface as a Tool operation with typed input, output, and deterministic behavior.
- Put baseline records, actors, permissions, time, and initial events in the world.
- Put each meaningful starting condition or provider failure in a scenario.
- Choose one target matching how the agent already runs: module, command, local HTTP, or an SDK callback.
- Give the target only the direct, HTTP, MCP, or CLI bindings it needs.
- Write drills around observable consequences and safety invariants, not phrasing in the model response.
Reuse an installed Tool package when one fits
A reusable Tool is an ordinary package dependency, not a framework feature switch. Install it with the project’s package manager, then select it once infiredrill.json:
firedrill validate reads and locks the selected declaration without executing behavior. Use firedrill tool inspect <tool-id> to see exactly what was selected, then firedrill tool validate <tool-id> or run a drill to execute it locally. Your repository still owns its initial data, actors, scenarios, targets, and drills. Firedrill never edits the installed package.
Browse the reviewed community catalog with firedrill tool list, or find one
integration with firedrill tool search <text>. The printed install source is
exact and can be passed to firedrill tool add <source> --install after review.
3. Keep the agent integration at one seam
For a command target, Firedrill sends a JSON invocation on stdin and supplies the declared binding variables, such asFIREDRILL_HTTP_URL and FIREDRILL_HTTP_TOKEN, their MCP equivalents, or FIREDRILL_CLI_URL and FIREDRILL_CLI_TOKEN. For an external target, runDrills() supplies the same values in binding.environment. A direct binding is available only to a module or callback target that declares it.
Firedrill does not become the model-provider credential store. An external callback uses the provider configuration already available to its owning process. A command target can map only the host variables it needs:
timeoutMs covers the complete agent interaction, including all model turns and Tool calls, so choose it for the slowest expected end-to-end loop rather than one request.
Repoint the agent’s existing test configuration, or use a separate test-only adapter around its ordinary entry point. Do not modify production agent logic, duplicate every action, or scatter test-mode branches through business logic.
When an ordinary test needs different starting data or a temporary Tool behavior, use the repository-level SDK rather than editing source and restoring it:
setup object is serialized, normalized, hashed, and compiled into a derived immutable build. It may add or replace starting state rows and actors, set virtual time, activate declared faults, append initial events, select installed Tool packages, point one declared Tool at a repository-owned behavior module, and map temporary bindings onto names the agent already understands. It never writes those choices back to YAML, JSON, or SQLite behind the report. Command targets receive binding aliases automatically; caller-owned targets pass binding.environment through the agent’s existing configuration seam. Unsupported protocol mappings fail before agent execution. Full details are in the @firedrill/sdk guide.
HTTP-bound agents can discover loaded operations at GET $FIREDRILL_HTTP_URL/v1/tools
and call one at POST /v1/operations/{packageId}/{operationId} with bearer
authentication. Discovery is not an access grant: the kernel checks actor
permissions on invocation. MCP-bound agents use the supplied Streamable HTTP URL
and token; discovered names are {packageId}.{operationId}. CLI-bound agents call
firedrill world tools --json and firedrill world call <tool-id> <operation-id> --input '{...}' --json. The protocol READMEs define the exact envelopes.
4. Run and diagnose
0 means every selected drill passed. Exit code 1 means source, execution, or assertions failed. Exit code 2 means the CLI invocation itself was invalid. Human and JSON modes carry the same diagnostics and report locations.
Every trial retains its exact world and writes terminal, JSON, JSONL, JUnit, and self-contained HTML evidence under the current project’s .firedrill/ directory. That directory is generated and Git-ignored by default. Use firedrill report verify <report-directory> to check the exact file set, hashes, schemas, identities, evidence ordering, and generated projections without an account or network. This proves bundle integrity, not authorship. The report’s reproduction command loads its content-addressed build with --build-hash and reruns the recorded seed. Keep that project-local build directory while reproducing; if it was removed, restore the source revision and setup that produced the displayed hash and compile it again.
A drill timeline can span hours of virtual time while running locally in minutes. It declares actors, ordered interactions, a horizon, invariant checkpoints, and Tool-call and event budgets; it is still a drill and uses the same runner and evidence. Watch mode queues edits and reruns without overlapping. To inspect change, compare two verified report directories:
<tool-id>-conformance (or pass --suite), cover every declared operation/error/event/fault/subscription, and run firedrill tool test <tool-id>. Firedrill executes it twice against one immutable build and checks same-seed state and trajectory hashes. After it passes, a human who owns the source may prepare a non-uploading review bundle:
5. Let an authoring agent iterate to green
A coding agent should begin with.agents/firedrill/BRIEF.md and .agents/skills/firedrill/SKILL.md, inspect the real agent’s tool clients, existing mocks, fixtures, and failure tests, create or select Tool packages, then run firedrill validate --json repeatedly until diagnostics are empty. It should run a small passing and intentionally failing drill before adding breadth. It must not invent unsupported fidelity or change production behavior merely to satisfy a fixture.
The optional local Firedrill Agent follows that same skill rather than a private format:
@firedrill/compiler/schema/* and @firedrill/contracts/schema/*. Source diagnostics include stable codes, file locations, paths, and corrective suggestions for machine use.