Reference
Configuration reference
Find machine configuration, project instructions, model connections, and explicit launch overrides.
View as textOn this page
- Choose the right place
- Configuration boundaries and precedence
- Web-fetch settings
- Language-server settings
- Language server workspace folder
- MCP settings
- MCP identity, credentials and lifecycle
- MCP sampling limits
- Machine settings
- Worktree policy, offline operation, and inactivity
- Example: limit concurrent agents
- Verify a change
- Configuration errors
Choose the right place
| Location | Purpose |
|---|---|
~/.haskell-agent/config.json | Machine-wide harness configuration: theme, MCP, web fetching, LSP, worktrees, and agent concurrency |
~/.haskell-agent/models.json | Additional model definitions and endpoint connections |
<checkout>/.haskell-agent/settings.json | Remembered checkout choices and approval policy; see persisted settings |
~/.haskell-agent/settings.json | User model, title-model and terminal preferences |
| Process environment | Credentials and explicit transport/helper overrides; see environment variables |
AGENTS.md | Repository instructions for the model, not a JSON settings file |
| Launch arguments | Explicit choices for this invocation, such as model, working directory, and interface |
version must be the integer 1. Boolean settings take JSON true or false, not quoted strings. Both inactivityDays and an explicitly configured maxConcurrentAgents must be integers of at least one. Omitting the concurrency limit leaves it unspecified at machine scope; it does not override a project or launch setting.
Configuration boundaries and precedence
Do not treat every configuration source as one merged JSON tree. config.json configures the harness, models.json defines model connections, and AGENTS.md supplies model instructions. Putting a JSON option in AGENTS.md does not configure the runtime.
For concurrent agents, the explicit CLI limit wins over the project limit, which wins over the machine limit. For model selection and connection definitions, use the model guide. For instruction discovery, use project instructions.
Web-fetch settings
These settings control the harness's client-side web-fetch capability. They are not a general firewall for shell commands, MCP servers, or provider-hosted browsing.
| Field under webFetch | Type / default | Constraints |
|---|---|---|
enabled | Boolean / false | Must be enabled before requests can run |
allowedDomains | String array / empty | An empty list denies all requests; entries must not be blank |
timeoutSeconds | Integer / 60 | 1–300 seconds |
maxContentBytes | Integer / 10485760 | 1–52428800 bytes; maximum fetched content |
maxInlineBytes | Integer / 100000 | 1–1048576 bytes and no greater than maxContentBytes; inline result limit |
Merge this section into your existing configuration to permit a specific documentation host:
{
"version": 1,
"webFetch": {
"enabled": true,
"allowedDomains": ["haskell.org"],
"timeoutSeconds": 30,
"maxContentBytes": 1048576,
"maxInlineBytes": 50000
}
}Restart the session after a manual edit and request an actual fetch of a page at https://haskell.org/. Inspect the tool result rather than accepting a response generated from model knowledge. A different host is not authorized merely because it belongs to the same organization. Keep the allowed host list narrow.
Language-server settings
lsp.enabled defaults to false and lsp.servers defaults to an empty object. Each key under servers names one local language-server process. Install the executable through your project's Nix development environment before enabling it.
| Server field | Type / default | Purpose |
|---|---|---|
command | Required string | Executable to launch; must not be blank |
args | String array / empty | Separate arguments; not a shell command string |
env | String-to-string object / empty | Environment overrides; values are redacted from diagnostics |
extensionToLanguage | Required nonempty string-to-string object | Map filename extensions to language identifiers; neither keys nor values may be blank |
initializationOptions | Optional JSON | Server-specific initialization payload |
settings | Optional JSON | Server-specific workspace settings |
workspaceFolder | Optional string | Explicit workspace folder |
startupTimeoutMilliseconds | Integer / 15000 | Startup deadline; 1–120000 milliseconds |
shutdownTimeoutMilliseconds | Integer / 5000 | Shutdown deadline; 1–120000 milliseconds |
Only stdio transport is supported. Do not copy configurations that require restartOnCrash: true or maxRestarts: the loader rejects them. Server settings depend on the language server, not the agent.
Language server workspace folder
Omitted workspaceFolder uses the active workspace. A relative value such as packages/api is resolved beneath that workspace, not beneath ~/.haskell-agent. The folder must already exist. Both paths are canonicalized, and a folder outside the active workspace is rejected, including a symlink that escapes it.
Each configured server receives one resolved root URI and a one-element workspace-folder list. This field is a string, not a multi-root array. Configure separate named server entries when different contained subdirectories need separate roots. An invalid workspaceFolder error means check existence/path permissions; an “inside the active workspace” error means choose a contained directory rather than relaxing unrelated tool approvals.
MCP settings
mcpServers maps names to local commands or remote URLs. Each entry must configure exactly one of those transports. The MCP field reference covers timeouts, OAuth, environment values, protocol selection, and optional capabilities.
For guided changes, use /meta. The Meta Console validates and previews supported configuration changes before applying them. Preserve unrelated settings when editing files manually.
MCP identity, credentials and lifecycle
Remote connectionId values must be nonempty, at most 128 characters and contain only lowercase ASCII letters, digits and hyphens. They identify connections, not display labels. Preserve generated identities; do not copy an identity from another connection to reuse its credentials.
If connectionCredentials is absent, it defaults to whether connectionId is present. Explicit false retains CLI-configured credentials; true selects managed connection credentials. Automatic migration of a legacy remote entry generates an identity and generation, sets this flag to false and fills a missing display name from its catalog label. Migration therefore does not silently move legacy authorization into the protected store.
connectionGeneration distinguishes lifecycle revisions. Managed authorization and enable/disable operations replace it; callbacks for an older generation must not restore a replaced or disabled connection. Use the management interface to authorize, disable or remove connections, rather than manually restoring an old generation. A failed migration requires repairing private configuration write access and retrying, not deleting all credentials. Refresh a stale management preview before saving.
For local servers, omitted cwd uses the workspace passed to MCP startup. An explicit value is passed to the process launcher unchanged; a relative value is relative to the agent process working directory, not the directory containing config.json. Prefer an absolute path when a server must start in a fixed directory.
MCP sampling limits
Enabling sampling allows a server to request an isolated one-shot completion using the active model/backend. Requests need at least one message and support only user/assistant roles with text strings, text-content objects or arrays of text content. Images and other content types are rejected. The system prompt and optional temperature are forwarded; the requested maximum output token count is clamped to at least one and remains subject to provider limits.
The main conversation is not shared: previous response state is cleared, tools and parallel tool calls are disabled, and provider storage is requested off where supported. A generated tool call, empty response or provider error rejects the request. Context/model preference hints do not switch the active model or import workspace context. Usage belongs to the active model's configured credential/billing route, not a free allowance supplied by the MCP server. Leave sampling disabled for untrusted servers.
Machine settings
The file is JSON, with quoted keys and no comments. Missing fields use the defaults below. A missing or blank file uses the default configuration. A malformed or semantically invalid file produces an error; do not assume that an invalid value silently falls back to its default.
| Field | Default | Meaning |
|---|---|---|
version | 1 | Configuration schema version |
theme | "midnight" | String: auto, midnight, daylight, tokyonight, rosepine-moon, or oscura-midnight |
mcpInitStrategy | "auto" | MCP initialization strategy; also accepts "progressive" and "blocking" |
mcpServers | Empty object | Named local or remote MCP server configurations |
webFetch.enabled | false | Enable client-side URL fetching; the domain allowlist still applies |
webFetch.allowedDomains | Empty list | Allowed domains; an empty list denies requests |
lsp.enabled | false | Enable configured language-server support |
worktree.fetchLatestUpstream | true | Fetch upstream when preparing managed worktrees |
worktree.inactivityDays | 1 | Inactivity threshold used by worktree management |
maxConcurrentAgents | Unset | Machine-level concurrent-agent limit |
Worktree policy, offline operation, and inactivity
The machine-wide worktree object contains two fields. fetchLatestUpstream is a boolean, defaulting to true; inactivityDays is a positive integer, defaulting to 1. For offline creation and a seven-day inactivity threshold, merge this into ~/.haskell-agent/config.json, preserving unrelated fields:
{
"version": 1,
"worktree": {
"fetchLatestUpstream": false,
"inactivityDays": 7
}
}With fetching disabled, new managed worktrees start from local HEAD. With fetching enabled, the current branch's configured remote wins, followed by upstream, origin, then a sole remaining remote. If no remote is selected, creation uses local HEAD. Otherwise it fetches the remote default branch into an isolated temporary ref: it does not merge into your checkout or update normal remote-tracking refs.
A cached remote default branch is reused. If that branch no longer exists, the agent discovers the remote default again; authentication, connectivity, or other fetch errors stop creation rather than silently using stale commits. For deliberately offline work, set fetching to false; do not interpret a failed fetch as a successful refresh. If a remote changes its default but keeps the old branch, explicitly fetch the new remote-tracking branch and update Git's remote HEAD with git remote set-head REMOTE --auto.
Interactive and subagent worktree creation reload the current machine policy for each creation. Initial CLI creation and background cleanup use the validated startup snapshot; restart the CLI to apply manual changes to that snapshot. Changes do not rewrite existing worktree branches.
Inactivity means elapsed 24-hour days since the later of the worktree's recorded activity and saved-session activity, not its creation age. Lease acquisition/release and explicit enrollment or recovery update recorded activity. The threshold never authorizes deletion on its own: active leases, protected/recovery-state checkouts, uncertain ownership, dirty files, and work not proven incorporated prevent collection.
Background maintenance runs asynchronously during session resource setup, not as an exact expiry timer. Each pass has bounded time and removal-attempt budgets, so an eligible checkout may survive until a later pass. A failure to establish activity evidence retains work rather than assuming inactivity. Use the worktree lifecycle guide to inspect eligibility, preview manual cleanup, and protect or recover work before changing retention settings.
Example: limit concurrent agents
/meta set the concurrent agent limit to 3Inspect the proposed scope and value before confirming. An explicit launch limit takes precedence over project settings, which take precedence over the machine setting:
agent-cli --max-concurrent-agents 2For a new configuration file, this minimal example sets only the machine limit. Do not replace an existing file with it; merge the field instead.
{
"version": 1,
"maxConcurrentAgents": 3
}Verify a change
Harness-managed machine updates use a process-shared lock and atomic replacement. The configuration directory and file are written with private permissions. Preserve config.lock and config.revision-key alongside the file; the revision key supports detecting changes to the saved configuration.
Loading an older remote MCP entry can assign and persist a missing connection identity. A read can therefore require write access during migration. If it fails, check ownership and permissions rather than inventing IDs. A stale configuration preview should be refreshed and reviewed again, not forced over another process's edit.
- Save a private backup of the existing file. Configuration can contain credentials; do not paste it into issue reports or commit it to a repository.
- Change one section, preserving unrelated keys. Prefer
/metafor a validated preview instead of editing a large file blindly. - Restart after manually changing startup settings. For an external MCP catalog edit,
/mcpfollowed byrreloads the runtime without discarding the session. - Exercise the capability you changed: a fetch, a language-server operation, an MCP read, or a small delegated task. A file that parses is not proof that its external service works.
Use /session-info to inspect the active session and /model to check model selection. Restart the CLI when testing manually edited startup settings. If a configuration fails to load, restore your saved copy rather than deleting credentials or widening permissions.
Configuration errors
| Error or symptom | Correction |
|---|---|
Unsupported harness config version | Use version 1; do not copy another product's schema |
must configure exactly one of url or command | Keep only the HTTP URL or local executable for that MCP entry |
maxInlineBytes must not exceed maxContentBytes | Reduce the inline limit or increase the content limit within its documented bounds |
LSP transport is unsupported | Configure a stdio language server, not an HTTP endpoint |
| Change appears to have no effect | Check the file location, restart the affected runtime, and inspect project/launch overrides before changing more values |
Continue with custom model configuration, MCP integrations, or project instructions.