A repository's project folder
Commit a .codeherder folder to a repo to keep a team's own workflow, stage, and rubric documents in the codebase.
A .codeherder folder at the root of a repository is a place for a team to keep its own workflow, stage, and rubric documents alongside its code. Commit it, and everyone who clones the repo gets those documents too.
It’s not the same thing as .codeherder.env — see It’s not .codeherder.env below if that’s what you’re after.
Creating or adopting it
Run this from anywhere inside your checkout:
ch project init
It’s offline: no sign-in and no server request. It looks at .codeherder in your repository root and does exactly one of these things:
- Nothing there yet — it creates the folder and tells you to
git addit. - A real folder already there — it leaves it untouched and reports what it found.
- A leftover link from a torn-down session — CodeHerder sometimes leaves a symlink at this path after a sandbox is cleaned up.
ch project initrecognizes its own link, removes it, and creates a real folder in its place. - Anything else — a file, or a symlink to something CodeHerder didn’t create — it refuses and changes nothing, so you can sort out what’s there yourself.
ch project init never runs git. Stage and commit the folder yourself once it’s created:
git add .codeherder
git commit -m "Add project folder"
What goes in it
Your team’s documents live in three subdirectories of .codeherder:
workflows/— workflow documents, one per task type.stages/— stage documents your workflows can reference.rubrics/— rubric documents for stages that judge their own output.
ch project init creates the folder empty. Make whichever of these subdirectories you need yourself.
Document format
Each file is one JSON document. The preview rejects a file that does not match this format.
{
"schema_version": 1,
"kind": "stage",
"key": "code",
"label": "Code",
"content_hash": "<64 hex characters>",
"body": { "StageKey": "code", "Label": "Code", "Spec": { "prompt": "..." }, "Fields": [] }
}
Envelope fields
| Field | Required | Meaning |
|---|---|---|
schema_version |
yes | Must be 1. |
kind |
yes | stage, workflow, rubric or wiki. |
key |
yes | Lowercase letters, digits and _. It starts with a letter and has at most 64 characters. |
label |
yes | The display name. It must match the label inside the body. |
archived_at |
no | A timestamp that marks the document archived. Leave it out. |
requires |
no | The documents this one needs. Each entry is {"kind": ..., "key": ...}. |
content_hash |
yes | The hash of the document. See below. |
body |
yes | The content. Its shape depends on kind. Unknown keys fail. |
Body shape per kind
- stage —
StageKey,Label,SpecandFields. These keys use Go case.StageKeyandLabelmust match the envelope. Keys insideSpecuse snake case, such aspromptandwritable. This is not the{label, spec, fields}document thatch stage create --stage-filetakes. - workflow — a composition:
key,label,instances,fieldsand the other keys thatch workspace workflow compositionprints.keyandlabelmust match the envelope. - rubric —
key,stageKey,artifact,levelsandcriteria. - wiki —
{"file": "<OKF file text>"}.
The requires list
A workflow lists each stage that its instances use. A stage lists each rubric that its verifications name. A workflow that uses a stage from your workspace library needs that stage document in the folder too.
How content_hash is computed
- Copy the document and set
content_hashto an empty string. - Rewrite
bodywith its object keys sorted. Keep array order and number text. - Convert
archived_at, if present, to UTC. - Write the envelope as compact JSON. Keep the field order of the table above.
- Escape strings as Go
json.Marshaldoes:- Write
<,>and&as\u003c,\u003eand\u0026. - Write U+2028 and U+2029 as
\u2028and\u2029. - Keep all other non-ASCII characters as UTF-8.
- Use no other escapes than the ones JSON requires.
- Write
- Take the SHA-256 of those bytes and write it as lowercase hex.
Get a valid file
Do not write the hash by hand. Export a document from the server:
ch stage show code --as-project-doc > .codeherder/stages/code.json
ch workspace workflow composition story --as-project-doc > .codeherder/workflows/story.json
Both commands print the document with no {data} wrapper. A local edit to the body changes the hash. After a local edit, recompute the hash with the steps above. Or edit the stage or workflow on the server, then export again. The --as-project-doc flag cannot combine with --json. A disabled stage still exports, with no archived_at.
Where these documents take effect
This is the part worth being precise about: today, a project document only affects what you see when you run
ch workflow show --offline --type story
Name whichever task type you want to look at, such as story, bug, or auto. If you name one that doesn’t exist, the error lists the ones you can choose from.
That command composes a workflow entirely on your machine, no sign-in required. It starts from CodeHerder’s built-in workflow for the type you name, then layers your project’s workflows/, stages/, and rubrics/ documents on top, with your project’s version winning wherever the two overlap.
The preview reads your working tree, so a document you’ve just saved is already picked up. You don’t need to commit it first. Committing is how you share it with your teammates.
To preview documents kept somewhere else, name the directory that holds them with --project-dir:
ch workflow show --offline --type story --project-dir ~/workflow-drafts
CodeHerder then reads only that directory, and ignores your checkout’s .codeherder folder. It picks up every .json file underneath, at any depth, and each one has to be a workflow, stage, or rubric document. One stray .json file stops the command.
So name a directory that holds only those documents. A whole .codeherder folder qualifies, as long as nothing else under it is a .json file. Point the flag at one subdirectory, such as .codeherder/workflows, and it reads only that one. Your stage and rubric documents stay out of the preview.
Committing a project document does not, by itself, change the pipeline a task runs on the server. ch workflow show --offline is a local preview. To change what a task actually runs, use Customising a task’s workflow or Customising workflows instead.
It’s not .codeherder.env
.codeherder (this folder) and .codeherder.env (a single file) share a name and both live at your repository root, but they do unrelated things. .codeherder.env sets your default server and workspace for the ch CLI — see Project defaults for the CLI.
Related guides
- Project defaults for the CLI — the
.codeherder.envfile, not this folder - Customising a task’s workflow — the way to actually change the pipeline a task runs
- Customising workflows — change a whole type’s default workflow
- The stage library — browse and author the shared stages your workflows are built from
Last updated