# hank.json
A `hank.json` file is the program a Hankweave run executes. It declares an immutable workflow: a sequence of codons (sealed agent tasks) and loops (repeated branches of codons) that the runner executes in order once the file loads. The root fields around that sequence set up the shared context – editor schema support, environment requirements, global prompt layers, and hank-level overrides – while the `hank` array itself is where the work happens.
This page is the field-level reference for that file. It explains what each key accepts, what the loader enforces beyond what an editor can check, and where the surrounding contracts (budgets, loops, sentinels, model routing) are documented.
## How to read this page
Use this page to look up the fields accepted in `hank.json`. The tables show the published JSON Schema, including types, required fields, constraints, and schema defaults. The text below each table adds loader behavior that an editor cannot check, such as file existence and model availability. Code blocks come from shipped fixtures and validation captures, so the spellings and diagnostics they show are the ones the runtime actually produces.
A `[changed]` or `[since]` marker appears only where the release history identifies a version. Model names in examples come from shipped fixtures. For configuration precedence, see [Hanks](/concepts/hanks); for file discovery and `--validate`, see the [CLI reference](/reference/cli).
The schema's root description still points to the stale URL `https://hankweave.dev/reference/configuration`; use this page instead.
## Choose the hank's root fields
A hank is a JSON workflow object. Only `hank` is required, and no fields outside the seven listed below are accepted. The root fields divide into three jobs: editor support (`$schema`), human-facing bookkeeping (`meta`), and run-wide behavior (`requirements`, `overrides`, and the global system prompt fields).
| field | type | default | required | constraints | description |
| ------------------------ | ------------------------- | ------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `$schema` | `string` | | no | | JSON Schema URL for editor support |
| `meta` | `object` | | no | | Metadata for sharing/indexing (optional) |
| `overrides` | `object` | | no | | Architect's overrides (optional) |
| `requirements` | `object` | | no | | Requirements that must be met for this hank to run (optional) |
| `globalSystemPromptFile` | `string \| array` | | no | | Global system prompt file(s) applied to all codons. Must be relative path(s) inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are rejected. |
| `globalSystemPromptText` | `string` | | no | | Global system prompt text applied to all codons |
| `hank` | `array` | | yes | minItems 1 | The immutable logic sequence (required) |
`$schema` is an optional string for editor support. If it is absent, the runtime writes it back on every startup and during `--validate`, then prints `+ Added $schema to for editor support`. The value is `https://unpkg.com/hankweave@latest/schemas/hank.schema.json`.
The schemas are also available from the npm package, so you can wire them into an editor once and get autocomplete and inline validation for every configuration file Hankweave reads. In VS Code, map each file pattern to its schema:
```json
{
"json.schemas": [
{
"fileMatch": ["**/hank.json"],
"url": "https://unpkg.com/hankweave@latest/schemas/hank.schema.json"
},
{
"fileMatch": ["**/hankweave.json"],
"url": "https://unpkg.com/hankweave@latest/schemas/hankweave.schema.json"
},
{
"fileMatch": ["**/*.sentinel.json"],
"url": "https://unpkg.com/hankweave@latest/schemas/sentinel.schema.json"
}
]
}
```
`meta` contains required `name` and `version`, plus optional `description` and `author`. Metadata is for humans: it helps remember what was built six months from now. `requirements` contains `env: string[]`; each declared name is checked fail-fast at startup and during `--validate` by either the direct environment-variable name or its `HANKWEAVE_`-prefixed form. `overrides` contains hank-level settings; precedence is owned by [Hanks](/concepts/hanks).
`globalSystemPromptFile` is a string or string array of file references. `globalSystemPromptText` is inline text. Supplying both global-system fields is a load error. The global system prompt is prepended before codon `appendSystemPromptFile` or `appendSystemPromptText` content; the parts are joined with a blank line, then receive template replacement and HTML-comment stripping.
Global prompts apply the same instruction to every codon, which keeps workflow-wide conventions in one place instead of repeating them in each task prompt. Typical content includes workspace layout, coding standards, domain constraints, and project requirements:
| Use Case | Example Content |
| ------------------- | ------------------------------------------------------------------------------------------------ |
| Workspace layout | "The codebase is a TypeScript monorepo with packages/ for libraries and apps/ for applications." |
| Coding standards | "Use functional components. All functions need JSDoc. No console.log in production." |
| Domain context | "This is a fintech app. PII must never be logged. All amounts are in cents." |
| Project constraints | "The project targets Node 22+. Don't use APIs removed in newer releases." |
`overrides` may contain `model`, `dataHashTimeLimit`, `sentinel`, `shimIdleTimeout`, and `budget`. The `sentinel` override carries `enablePersistence`, `healthCheckGracePeriodMs`, and `waitForAllHealthChecks`. `dataHashTimeLimit` is accepted as a positive hank override but is not consumed by the 0.10.0 hashing calls; normal startup omits it when calling the execution setup, and `--validate` uses the built-in 5000-millisecond value directly. Budget allocation belongs to [budgets](/concepts/budgets), and config precedence belongs to [Hanks](/concepts/hanks); this page does not restate either contract.
`hank` is an array with at least one item: the immutable logic sequence whose codon order is fixed when the hank **loads**. Its items are codons – sealed agent tasks – or loops – repeated branches containing codons. An unknown root key is a load error. `strand` is not an alternate root key: only `hank` is legal. A file named `strand.json` is usable only when passed explicitly as a config path, because implicit discovery finds `hank.json` only.
\[changed 0.10.0] The published root schema fields were fixed so editors no longer flag `requirements` and `globalSystemPrompt*` as unknown keys.
The shipped init fixture shows how these pieces fit together in a real file: the `$schema` and `meta` block at the root, then the first codon of the `hank` array with its prompt file, checkpointed files, and output copy step.
```json
{
"$schema": "https://unpkg.com/hankweave@latest/schemas/hank.schema.json",
"meta": {
"name": "My Workflow",
"version": "1.0.0",
"description": "Generated by hankweave init"
},
"hank": [
{
"id": "analyze-haiku",
"name": "Analyze Project (Haiku)",
"model": "haiku",
"continuationMode": "fresh",
"promptFile": "./prompts/analyze-haiku.md",
"checkpointedFiles": ["analysis-haiku.md"],
"outputFiles": [
{
"copy": ["analysis-haiku.md"]
}
]
},
…
]
}
```
[Hanks](/concepts/hanks), [hankweave.json](/reference/hankweave-json), and [environment variables](/reference/environment-variables).
## Configure one codon
A codon describes one sealed agent task. `id`, `name`, `model`, and `continuationMode` are required. You can omit `type`; its schema default is `"codon"`. The full field list follows; the subsections after it group the fields by the three things a codon definition controls: what the model is asked to do, how failures and resource limits are handled, and how files move into, through, and out of the workspace.
| field | type | default | required | constraints | description |
| ------------------------ | ------------------------- | ------- | -------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | `codon` | no | = `codon` | Type discriminator - optional, defaults to 'codon' |
| `id` | `string` | | yes | minLength 1 | Unique identifier for this codon (e.g., 'codon-1', 'data-analysis') |
| `name` | `string` | | yes | minLength 1 | Human-readable name displayed in UI and logs |
| `promptFile` | `string \| array` | | no | | Path to a file containing the prompt (mutually exclusive with promptText). Must be a relative path inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are rejected. |
| `promptText` | `string` | | no | | Inline prompt text (mutually exclusive with promptFile) |
| `appendSystemPromptFile` | `string \| array` | | no | | Path to a file containing system prompt to append (mutually exclusive with appendSystemPromptText). Must be a relative path inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are… |
| `appendSystemPromptText` | `string` | | no | | Inline system prompt text to append (mutually exclusive with appendSystemPromptFile) |
| `model` | `string` | | yes | minLength 1 | Model to use for this codon. Can be a Claude model ('sonnet', 'opus'), Gemini model ('gemini-2.0-flash-exp', 'flash'), or any other model supported by the configured shim. |
| `continuationMode` | `enum` | | yes | `fresh` \| `continue-previous` | How this codon should handle continuation from previous codons. 'fresh': Start a new session (default for most cases). 'continue-previous': Continue from the previous codon's session, maintaining context and conversatio… |
| `rigSetup` | `array` | | no | | Rig setup operations to run before codon starts. Each operation must complete successfully for codon to start. |
| `description` | `string` | | no | | Optional description shown to users about what this codon does |
| `checkpointedFiles` | `array` | | no | | Glob patterns for files to checkpoint during codon execution. These files will be: watched for changes and streamed to the client, tracked in the git-based checkpoint system, and resolved using gitignore rules for consi… |
| `env` | `object` | | no | | Optional environment variables to set for the Claude process |
| `outputFiles` | `array