# Project defaults for the CLI

Source: https://codeherder.com/docs/project-config/

Commit a .codeherder.env file to a repo so everyone who checks it out gets the same server and workspace, without exporting anything themselves.

If everyone on your team checks out the same repo and always points `ch` at the same server and workspace, you can commit that default once instead of asking each person to export it. A `.codeherder.env` file at the root of a repo gives `ch` those two defaults automatically, for anyone who runs it from inside that checkout.

It’s meant to be committed. It never holds a token, a key, or anything else that identifies you — see [What it never sets](https://codeherder.com/docs/project-config/#what-it-never-sets) below.

## Where it goes, and how ch finds it

Create a file named `.codeherder.env` at the root of your repository:

```
cat > .codeherder.env << 'EOF'
CH_ADDR=https://codeherder.example.com
CH_WORKSPACE_ID=acme/platform
EOF
```

Every `ch` command walks upward from your current directory looking for that file (apart from `ch device-server` — see [The ch device-server exception](https://codeherder.com/docs/project-config/#the-ch-device-server-exception) below), so it’s found whether you run `ch` from the repo root or from a subdirectory somewhere inside the checkout. Commit it like any other file:

```
git add .codeherder.env
git commit -m "Add CodeHerder project defaults"
```

## Format

The file uses the same `KEY=value` shape as a shell `.env` file:

- One `KEY=value` pair per line.
- An optional `export` prefix is allowed and ignored — `export CH_ADDR=...` and `CH_ADDR=...` behave the same way.
- Wrap a value in single or double quotes if you want to; the quotes are stripped.
- Lines starting with `#` are comments, and blank lines are skipped.
- A line with no `=` is skipped rather than treated as an error.

## The two keys it can set

Only two keys are read from this file — anything else is ignored (see [What it ignores](https://codeherder.com/docs/project-config/#what-it-ignores)):

| Key | What it sets |
| --- | --- |
| `CH_ADDR` | The server your commands talk to. Set this only if your team runs its own CodeHerder server rather than the CodeHerder cloud. |
| `CH_WORKSPACE_ID` | The workspace commands operate on — a name, slug, slug path, or UUID; see [Managing workspaces](https://codeherder.com/docs/workspaces/#selecting-your-active-workspace-in-the-cli). |

## Where it sits in precedence

The project file supplies the **lowest** -precedence default for each key: it’s applied only when your environment doesn’t already have a value for that key. If you’ve exported `CH_ADDR` or `CH_WORKSPACE_ID` yourself, or you’re using a profile or a `--workspace` / `--addr` flag, the effective value comes from that source instead. See [Credential precedence](https://codeherder.com/docs/credentials/#credential-precedence) for how this fits alongside browser sign-in, `CH_TOKEN`, and profiles.

Because `CH_ADDR` changes which server your commands talk to, applying it from the project file always prints a notice so it’s never a silent switch:

```
ch: /path/to/repo/.codeherder.env: applying CH_ADDR=https://codeherder.example.com from the project file — commands now talk to this server
```

## What it ignores

Any key in the file other than `CH_ADDR` and `CH_WORKSPACE_ID` is ignored, and `ch` prints a line to say so:

```
ch: .codeherder.env at /path/to/repo/.codeherder.env: ignoring SOME_OTHER_KEY — not a project-config key
```

## What it never sets

Credentials and session identity are never read from a project file — `CH_TOKEN`, a profile name, or anything that identifies a signed-in person, agent, or session is rejected outright, with a sharper message:

```
ch: .codeherder.env at /path/to/repo/.codeherder.env: ignoring CH_TOKEN — credentials and session identity are never read from a project file
```

This is deliberate: a `.codeherder.env` file is committed to the repo, so anyone who clones it can read it. It should never carry anything a committer wouldn’t want the whole team — or anyone with read access to the repo — to see.

Two refusals follow from the same principle, both about the server the project file names in `CH_ADDR`:

- If the project file sets `CH_ADDR` and you’re also supplying a bearer token — via `CH_TOKEN`, `--token`, or a profile (`--profile` / `CH_PROFILE`) — without otherwise confirming you mean to send it to that server, `ch` refuses: `ch: /path/to/repo/.codeherder.env declares CH_ADDR=https://codeherder.example.com — refusing to send your bearer token there without your consent. Export CH_ADDR=https://codeherder.example.com yourself, or pass --addr https://codeherder.example.com, if you mean it.` Exporting `CH_ADDR` yourself, or passing `--addr` explicitly, counts as consent and clears the refusal.
- If the project file sets `CH_ADDR` and your cached `ch login` credential was minted against a different server, `ch` won’t send that credential to the project’s server: `ch: /path/to/repo/.codeherder.env declares CH_ADDR=https://codeherder.example.com, but your cached credential (`ch login`) is for a different server (https://other.example.com) — refusing to send it there. Run `ch login` against https://codeherder.example.com, or pass --token.`

Either way, follow the message: run `ch login` against the server the project file names, or pass `--token` explicitly.

## The ch device-server exception

`ch device-server` never reads a project file, even when you run it from inside a repo that has one. It’s a long-running process, and its environment is inherited by every session it later spawns — a repo-level default has no business leaking into every task that device ever runs. Point a device at a specific server or workspace with its own flags or environment instead; see [Managing your devices](https://codeherder.com/docs/devices/).

## Checking what applied

`ch whoami` shows whether a project file supplied anything for the current invocation, and which keys:

```
project config: /path/to/repo/.codeherder.env (CH_ADDR, CH_WORKSPACE_ID)
```

This row only appears when at least one key was actually applied from the file — if your environment already set both keys itself, the project file’s values were never used, and the row doesn’t show. `ch whoami --json` carries the same information as `projectConfigPath` and `projectConfigApplied`.

## Related guides

- [A repository’s project folder](https://codeherder.com/docs/project-folder/) — a different, similarly-named `.codeherder` folder for workflow, stage, and rubric documents, not this file
- [Credentials and profiles](https://codeherder.com/docs/credentials/) — the full credential-resolution order, browser sign-in, and profiles
- [Managing workspaces](https://codeherder.com/docs/workspaces/) — how the CLI resolves your active workspace
- [Using the ch CLI](https://codeherder.com/docs/using-the-cli/) — the conventions that apply to every command
