> ## Documentation index
> Fetch the complete documentation index at: https://haarness.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure Haarness

Settings live in a `haarness.json` file. Put one in your home configuration folder for settings
that apply everywhere, and one in a project for settings that apply only there. Project settings
override yours, and command-line flags override both. The terminal UI, Desktop and the CLI all read
the same files.

## Set your default model

Create `~/.config/haarness/haarness.json`:

```json
{
  "model": "anthropic/claude-sonnet-5-5"
}
```

New chats use that model in the terminal UI, in Desktop and with `haarness run`, unless you pick
another one there. A chat you already started keeps its own. `haarness models` lists what you can
choose.

## Where settings live

| For | File |
| --- | --- |
| You, in every project | `~/.config/haarness/haarness.json` |
| One project | `haarness.json` at the project root, or `.haarness/haarness.json` |

Both files may contain comments, and `haarness.jsonc` works as a name too. In a Git repository,
Haarness reads project files from the repository root down to the folder you are in; the nearer
file wins, and `.haarness/haarness.json` wins over `haarness.json` in the same folder.

A section you set in a project file, such as `compaction`, replaces the whole section from your
global file. `defaults`, `providers`, `mcp` and `tool_availability` are merged entry by entry
instead, and a project's permission rules are added after yours.

Other things have their own places:

| What | Where |
| --- | --- |
| Agents, commands, skills | `agents/`, `commands/` and `skills/` in `~/.config/haarness/` or the project's `.haarness/` |
| Instructions | `~/.config/haarness/AGENTS.md`, and `AGENTS.md` files in the project |
| Hooks | `hooks` in `haarness.json`; see [Run commands on chat events](https://haarness.ai/docs/cli/hooks.md) |
| Provider credentials | `~/.local/share/haarness/auth.json`; never in a project |

### haarness.json or config.toml?

Use `haarness.json` for everything on these pages. `haarness provider add`, `haarness mcp add`,
`haarness telemetry off` and the settings screens in the terminal UI and Desktop write there, and
`--project` writes to the project's `haarness.json`.

`~/.config/haarness/config.toml` holds the terminal UI's own `[tui]` settings: shortcuts,
background colour and the status line command. See [Make it yours](https://haarness.ai/docs/tui/tour.md#make-it-yours).
Settings an older setup keeps in `config.toml` still work; when both files set the same thing,
`haarness.json` wins.

Desktop keeps its own window preferences, such as appearance and keyboard shortcuts, on this
computer, outside these files.

## Settings you might change

```jsonc
{
  "small_model": "anthropic/claude-haiku-4-5", // a cheaper model for naming chats
  "defaults": {
    "reasoning_effort": "high",   // none, minimal, low, medium, high, xhigh, max
    "output_style": "concise",    // concise, explanatory, formal, minimal
    "ultracode": false            // start new chats in ultracode
  },
  "compaction": {
    "enabled": true,              // false: only /compact summarises
    "threshold": 0.85             // summarise when the context is this full
  },
  "snapshots": {
    "retention_days": 7           // checkpoints behind /undo and /diff; 0 keeps them all
  },
  "tool_availability": {
    "webfetch": false             // hide a tool from the model
  }
}
```

| Setting | Does |
| --- | --- |
| `default_agent` | Agent for new chats, such as `"build"` |
| `small_model` | `provider/model` that names new chats. Auto's reviewer also uses it when it is on the chat's provider |
| `defaults.output_style` | A built-in style, or the name of your own file in `output-styles/` |
| `compaction.tail_turns` | Recent turns kept word for word after a summary (default 2) |
| `snapshots.enabled` | On by default in Git repositories |
| `lazy_tools.mode` | `auto` (default), `always` or `off`: load rarely used tool descriptions only when needed |
| `tool_availability` | `false` hides a tool and blocks calls to it |
| `auto_review` | How Auto's reviewer model works: `model`, plain-language `allow` and `block` lines, `timeout` (60 s), or `enabled: false`. A project can only add `block` lines or lower `timeout` |

[Permissions and Auto's reviewer](https://haarness.ai/docs/security/permissions.md#tune-the-reviewer-or-turn-it-off),
[execution budgets](https://haarness.ai/docs/security/execution-budgets.md),
[custom providers](https://haarness.ai/docs/providers/custom-providers.md), [MCP servers](https://haarness.ai/docs/cli/mcp-servers.md) and
[hooks](https://haarness.ai/docs/cli/hooks.md) are configured in the same file and have their own pages.

## Language servers and formatters

Built-in language servers are on and start only when the agent works on a matching file. If one
is not installed, the chat carries on and `/status` shows it as missing.

```jsonc
{
  "lsp": {
    "servers": {
      "rust": { "enabled": false },                 // turn off a built-in
      "acme": {                                     // add your own
        "command": ["acme-language-server", "--stdio"],
        "extensions": [".acme"]
      }
    }
  },
  "formatter": {
    "enabled": true                                 // off by default
  }
}
```

With formatting on, Haarness formats a file after the agent writes or edits it, using the
formatters it finds installed. Add your own under `formatter.formatters.<name>` with `command`
(use `$FILE` for the path) and `extensions`. Commands are lists of arguments; they never go
through a shell.

## Give the agent project instructions

Write your rules in `AGENTS.md`. Haarness reads `~/.config/haarness/AGENTS.md` first, then each
`AGENTS.md` from the repository root down to the folder you are in. When the agent reads a file in
a subfolder that has its own `AGENTS.md`, that file is added too.

An `AGENTS.md` can pull in another file with `@docs/rules.md` (or `@"path with spaces.md"`).
Imports go at most five levels deep, and files over 40 KiB are skipped. A project file cannot
import a file from outside the folder you opened, and an import never reads a secret file such as
`.env`.

To add more files or URLs, list them under `instructions`:

```json
{
  "instructions": ["docs/rules/*.md", "~/team/rules.md", "https://example.com/rules.md"]
}
```

A URL that fails to load is skipped.

To change Haarness's own built-in instructions rather than add to them, use a
[prompt file](https://haarness.ai/docs/cli/agents-commands-skills.md#change-haarnesss-built-in-instructions).

### Use my CLAUDE.md files too

Haarness does not read Claude Code files unless you ask it to:

```json
{
  "compatibility": {
    "claude_code": { "instructions": true }
  }
}
```

`instructions` adds `CLAUDE.md` files. `agents`, `skills` and `commands` do the same for the
matching `.claude/` folders. If a folder has both, `AGENTS.md` wins.

## Changes apply without a restart

Haarness picks up edits to settings, agents, commands, skills, hooks, MCP servers and workflows on
its own. If a turn is running, it waits until the turn ends. If an edit is invalid, the previous
settings stay in use. Snapshot settings apply the next time the workspace server starts.

## Ignore a project's configuration

Open a repository you do not trust with:

```sh
haarness --disable-project-config
```

or set `HAARNESS_DISABLE_PROJECT_CONFIG=1`. Haarness then ignores the project's settings,
`AGENTS.md`, agents, commands, skills, hooks, MCP servers, workflows, plugins and extensions. Your
own global configuration and the approvals you saved still apply. `AGENTS.md` files in subfolders
can still reach the model when it reads files there.

## Give your team a shared starting setup

Point `HAARNESS_SYSTEM_CONFIG_DIR` at a folder laid out like `~/.config/haarness`: a team's Git
checkout, or a folder your device management installs. Haarness reads this system folder below
everything else, so each person's own settings and the project's still win.

```sh
HAARNESS_SYSTEM_CONFIG_DIR=/opt/acme/haarness haarness
haarness doctor     # shows "system config: /opt/acme/haarness"
```

It can hold `haarness.json`, `AGENTS.md`, `agents/`, `commands/`, `skills/`, `output-styles/`,
`prompts/`, `themes/` and local plugins in `plugins/local/`. The path must be absolute.

Haarness never writes into the folder, so it can be read-only. Its items are marked **System** in
Desktop and `system` in the terminal UI, with no Remove. Turning off one of its MCP servers saves your
own setting over it, and an agent that tries to edit a file there always asks you first.

Apps started from the Dock, Start menu or a launcher do not see variables from your shell profile.
Set the variable for your whole login session instead, for example with
`launchctl setenv HAARNESS_SYSTEM_CONFIG_DIR /opt/acme/haarness` on macOS, then open Desktop again.

## Move Haarness's folders

Haarness follows `XDG_CONFIG_HOME`, `XDG_DATA_HOME` and `XDG_CACHE_HOME` (absolute paths) on every
system, including macOS. Set `HAARNESS_HOME` to an absolute path to keep everything under one
folder, for example for a CI job or a second, separate install: configuration, provider
credentials, chats, caches, schedules and the terminal UI's settings. Schedules made there also run
there. [Where Haarness keeps its files](https://haarness.ai/docs/cli/troubleshooting.md#where-haarness-keeps-its-files)
lists the folders.

## Save and restore your setup

A profile is an archive of your configuration: settings, instructions, agents, commands, skills,
hooks, workflows, output styles, themes and the plugins you installed. It never includes
credentials or chats.

```sh
haarness profile save my-setup                    # writes my-setup.profile.zip
haarness profile inspect my-setup.profile.zip     # show what is inside
haarness profile restore my-setup.profile.zip --dry-run
haarness profile restore my-setup.profile.zip
```

`--scope global` or `--scope local` saves only your configuration or only this project's; the
default is both. Restore refuses to overwrite existing files unless you pass `--force`;
`--dry-run` lists every file it would add or replace. A profile does not carry your
[usage statistics](https://haarness.ai/docs/cli/stats-and-insights.md#what-does-haarness-share-with-haarness-cloud)
choice: each computer keeps its own. An MCP secret kept in the keychain travels only as its
`${keychain:NAME}` reference.

To keep profiles on a Haarness server and restore them on another machine:

```sh
export HAARNESS_PROFILE_URL=https://haarness.example
export HAARNESS_PROFILE_TOKEN=…
haarness profile push my-setup.profile.zip
haarness profile search
haarness profile pull <id>
```

Set the token in the environment rather than on the command line, so it stays out of your shell
history. The URL must use HTTPS unless it is on your own machine.

## Related

- [Agents, commands and skills](https://haarness.ai/docs/cli/agents-commands-skills.md)
- [Run commands on chat events (hooks)](https://haarness.ai/docs/cli/hooks.md)
- [Permissions](https://haarness.ai/docs/security/permissions.md)
- [Fix common problems](https://haarness.ai/docs/cli/troubleshooting.md)
