# A repository's project folder

Source: https://codeherder.com/docs/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`](https://codeherder.com/docs/project-folder/#its-not-codeherderenv) 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 add` it.
- **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 init` recognizes 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`, `Spec` and `Fields`. These keys use Go case. `StageKey` and `Label` must match the envelope. Keys inside `Spec` use snake case, such as `prompt` and `writable`. This is not the `{label, spec, fields}` document that `ch stage create --stage-file` takes.
- **workflow** — a composition: `key`, `label`, `instances`, `fields` and the other keys that `ch workspace workflow composition` prints. `key` and `label` must match the envelope.
- **rubric** — `key`, `stageKey`, `artifact`, `levels` and `criteria`.
- **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

1. Copy the document and set `content_hash` to an empty string.
2. Rewrite `body` with its object keys sorted. Keep array order and number text.
3. Convert `archived_at`, if present, to UTC.
4. Write the envelope as compact JSON. Keep the field order of the table above.
5. Escape strings as Go `json.Marshal` does:
  - Write `<`, `>` and `&` as `\u003c`, `\u003e` and `\u0026`.
  - Write U+2028 and U+2029 as `\u2028` and `\u2029`.
  - Keep all other non-ASCII characters as UTF-8.
  - Use no other escapes than the ones JSON requires.
6. 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](https://codeherder.com/docs/workflow-overrides/) or [Customising workflows](https://codeherder.com/docs/task-types/) 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](https://codeherder.com/docs/project-config/).

## Related guides

- [Project defaults for the CLI](https://codeherder.com/docs/project-config/) — the `.codeherder.env` file, not this folder
- [Customising a task’s workflow](https://codeherder.com/docs/workflow-overrides/) — the way to actually change the pipeline a task runs
- [Customising workflows](https://codeherder.com/docs/task-types/) — change a whole type’s default workflow
- [The stage library](https://codeherder.com/docs/stage-library/) — browse and author the shared stages your workflows are built from
