# Configuration

> Set stacks defaults in config.json and environment variables, and find where it keeps data, state and caches on disk.

stacks works with no configuration. Everything on this page is optional: a `config.json` for defaults you'd otherwise pass as flags, and environment variables for paths, logging, network and telemetry.

## config.json

The file lives at `~/.config/stacks/config.json`, or `$XDG_CONFIG_HOME/stacks/config.json` when that's set. A missing file is fine.

```json title="~/.config/stacks/config.json"
{
  "agents": ["claude", "codex"],
  "always": ["git-hooks"],
  "author": "A. Name",
  "package_scope": "@acme",
  "preset": "sandbox"
}
```

| Key | Meaning |
| --- | --- |
| `agents` | Agents whose `adapters/<agent>/` files are written: any of `claude`, `codex`, `opencode`, `cursor`. `--agents` overrides it. Default `["claude"]` |
| `always` | Fragment ids added to every composition they fit. One that doesn't fit, or doesn't exist, is skipped with a warning. `--without` still removes one |
| `author` | Author name for templates. `--author` overrides it; without either, stacks uses `git config user.name` |
| `package_scope` | npm scope for templates, such as `@acme`. `--scope` overrides it |
| `preset` | `default` or `sandbox` for `new`. `--preset` and `--sandbox` override it |
| `dataDir` | Data directory. `STACKS_DATA_DIR` overrides it |
| `telemetry` | `false` turns off anonymous usage telemetry. Prefer `stacks telemetry disable`, which also deletes pending events and identity |

The schema is closed: any other key is an error, reported as `InvalidConfig` (exit 3). Environment variables override file values, and blank values count as absent.

stacks reads the file lazily, once per invocation, so `--help`, `--version` and `stacks doctor` still work when it's broken. `doctor` reports a malformed file under `configErrors` and exits 0, so run it to find the problem:

```sh title="Terminal"
stacks doctor
```

Your own stacks and fragments live beside this file, in `stacks/<id>/` and `fragments/<id>/`. That directory is the trusted `user` origin; see [Registries and trust](https://stacks.steamfield.io/docs/concepts/registries-and-trust.md).

## Environment variables

### Paths

| Variable | Meaning |
| --- | --- |
| `STACKS_DATA_DIR` | Data directory. Default `$XDG_DATA_HOME/stacks` (`~/.local/share/stacks`) |
| `STACKS_STATE_DIR` | Project state records and telemetry state. Default `$XDG_STATE_HOME/stacks` (`~/.local/state/stacks`) |
| `HOME`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, `XDG_STATE_HOME`, `XDG_CACHE_HOME` | Path roots. The cache is `$XDG_CACHE_HOME/stacks` (`~/.cache/stacks`) |

### Registry and network

| Variable | Meaning |
| --- | --- |
| `STACKS_INDEX_URL` | Read entries from a different registry index instead of the default signed one. HTTPS only, except plain HTTP on `localhost` or `127.0.0.1`. An invalid URL is never fetched. Its entries are untrusted, and published stats are turned off |
| `STACKS_REGISTRY_DIR` | A directory used in place of the bundled registry, relative to the working directory. Its entries are untrusted |
| `STACKS_OFFLINE` | `1` turns off every network request: index refreshes, stats, search API calls and telemetry. Verified cached entries stay available. Same as `--offline` |

### Telemetry

| Variable | Meaning |
| --- | --- |
| `DO_NOT_TRACK` | Any value except empty, `0` or `false` turns off telemetry and keeps `stacks search` requests on this machine |
| `STACKS_TELEMETRY_DISABLED` | Any value except empty, `0` or `false` turns off telemetry. Doesn't affect search |
| `CI` | Any set value, even empty, turns off telemetry and selects agent output at a terminal |
| `STACKS_TELEMETRY_DEBUG` | `1` prints each event to stderr instead of queuing or sending it. Consent rules still apply |
| `STACKS_TELEMETRY_URL` | Send events to a different server, for testing your own collector |

[Telemetry](https://stacks.steamfield.io/docs/reference/telemetry.md) covers the commands and the order these switches are checked in.

### Output and logging

| Variable | Meaning |
| --- | --- |
| `NO_COLOR` | Any nonempty value turns off color and the live progress line. Wins over `FORCE_COLOR` |
| `FORCE_COLOR` | `1` colors human output on a stderr that isn't a terminal, as long as stdout is one |
| `STACKS_LOG_FILE` | Path to a JSONL log file. Its directory is created when needed |
| `STACKS_LOG_FORMAT` | `json` for JSON diagnostics, otherwise plain readable logs |
| `LOG_LEVEL` | `trace`, `debug`, `info`, `warn`, `error`, `fatal` or `none`. Default `warn`, which is also the fallback for an invalid value |

[Output, JSON and exit codes](https://stacks.steamfield.io/docs/reference/output.md) explains when logs reach stderr.

## Shared flags

Every command accepts these, in addition to its own flags:

| Flag | What it does |
| --- | --- |
| `--json` | Write one JSON result to stdout. A failure writes one JSON error envelope as the last stderr line |
| `--offline` | Use cached and bundled entries without network requests. Same as `STACKS_OFFLINE=1` |
| `--no-telemetry` | Skip telemetry for this invocation, keeping queued events |
| `--log-level` | Minimum log level for this invocation |

## Files on disk

| Path | What's there |
| --- | --- |
| `~/.config/stacks/config.json` | Optional settings |
| `~/.config/stacks/stacks/`, `~/.config/stacks/fragments/` | Your own entries |
| `~/.local/state/stacks/projects/<projectId>.json` | Each project's state record: the second copy of its verify digest and its timings |
| `~/.local/state/stacks/telemetry/` | Telemetry consent, identity and pending events |
| `~/.cache/stacks/index/` | The verified registry index and extracted entry bundles |
| `~/.cache/stacks/stats/` | Cached published stats, one state file per resource |
| `~/.cache/stacks/search/backoff.json` | Search API backoff: endpoint URLs and expiry times only |

Every cache can be deleted safely; stacks rebuilds it on the next request. Deleting a project's state record turns its tamper check into `manifest-only` until `stacks verify --accept-changes` writes a new one.

## Network requests

stacks sends every request to one host, https://stacks.steamfield.io:

| Request | When | Deadline | On failure |
| --- | --- | --- | --- |
| Registry index and entry bundles | `list`, `show`, `new` and `add`, when the cached index is over 24 hours old | 1,500 ms | Last verified index or the bundled registry; retry after ten minutes, or 24 hours after a 404 |
| Published stats | `list` and `show`, when the cached copy is over 24 hours old | 1,500 ms | No stats shown; retry after ten minutes, or 24 hours after a 404 |
| Search | `stacks search`, unless `--local` | 800 ms | Local ranking; retry after ten minutes |
| Signed dependency allowlist | `new`, when the cached copy is over 24 hours old | 1,500 ms | Last verified copy, or none; retry after ten minutes |
| Telemetry events | After `verify`, before `new` or `add` hands off to an agent, and `stacks telemetry flush` | 800 ms (5 seconds for `flush`) | Events stay queued; retry after ten minutes |

`--offline` or `STACKS_OFFLINE=1` turns all of them off. [Telemetry](https://stacks.steamfield.io/docs/reference/telemetry.md) covers when events are sent and the other ways to stop them. `stacks verify` never makes registry, stats or search requests.

`stacks doctor --json` reports the index cache's state under `remoteIndex` without contacting the server. [Registries and trust](https://stacks.steamfield.io/docs/concepts/registries-and-trust.md#the-signed-index) explains what the CLI verifies before using an index.
