Skip to content

Configuration schema

The canonical JSON Schema is published at:

https://harnery.com/schemas/config.schema.json

Reference it in your config file’s $schema field to get editor autocomplete and validation in VS Code, Cursor, Zed, JetBrains, and anywhere else that respects $schema.

Settings resolve from these sources, lowest precedence first (later wins):

  1. ~/.config/harnery/config.jsonc: the user-global file, a base for every project on the machine (honors XDG_CONFIG_HOME; falls back to ~/.config)
  2. <project>/.harnery/config.jsonc: the project settings file, which overrides the user-global file field by field (a project that sets only web.port keeps a user-global web.bind)
  3. CLI flags + environment variables: per-invocation overrides (see each field’s env note)

The config reader (src/core/config.ts) merges the two files and owns binName, hooksSetupHint, tools, workflow, skills, presence, coord, artifacts, backup, and sync; the web layer reads files. One deliberate exception: the binName pin that harn init guards against re-stamping is read from the project file only. A user-global binName is a display fallback, never a project pin.

Field Type Default Description
$schema string none URL to the JSON Schema (used by editors for autocomplete/validation)
project_name string repo basename Display name surfaced in log lines and to peers
binName string harn Host CLI bin name used in agent-facing prompts (see below)
coord object see below Coord-layer settings
artifacts object see below Working-artifact retention
tools object see below Managed-tool provisioning consent (tools.ripgrep.autoInstall)
workflow object see below Workflow-engine defaults
skills object see below Shipped-skill suppression (skills.exclude)
instructions object see below Host-owned addendum spliced into AGENTS.md (instructions.hostAddendumFile)
presence object see below Cross-machine presence transports
files object see below Web file-viewer path policy (additive deny/allow globs)
web object see below Standalone Next.js dashboard
backup object see below restic-backed snapshots
sync object see below rclone-backed cross-machine sync

The host CLI’s bin name. Harnery’s coord binaries (agent-hook, agent-coord) and the web UI run as Harnery itself, so they can’t see the name of a consumer CLI that composes Harnery (e.g. myapp). They read it back from this field for every agent-facing string: end-of-turn nudges, council prompts, worktree-conflict hints. harn init stamps it automatically for a consumer (any bin name other than the harn default). Resolution precedence: HARNERY_BIN env → this field → "harn".

Field Type Default Description
freshness_seconds number 600 Heartbeat age (seconds) above which the sweeper prunes an agent (10 min)

Resolution: HARNERY_AGENT_COORD_FRESHNESS env (canonical; HARNERY_AGENT_FRESHNESS is a legacy alias) → this config.jsonc key → 600.

Field Type Default Description
default_retention_days number 3 Retention used by harn artifacts create when --days is absent

Resolution: HARNERY_ARTIFACT_RETENTION_DAYS env → this config.jsonc key → 3. See harn artifacts for cleanup behavior.

Field Type Default Description
subscriptionOnly bool false (engine) / true (stamped by harn init) Pin workflow run to subscription billing: API-key vars are scrubbed from every child env, so children can only authenticate via the adapter CLI’s stored login

harn init stamps { "subscriptionOnly": true } into any project without a committed workflow key; an existing workflow key of any shape is never touched (set false for key-only CI hosts). Env override per process: HARNERY_WORKFLOW_SUBSCRIPTION_ONLY=1|0. See run → billing safeguards.

Field Type Default Description
ripgrep.autoInstall bool false Let harn grep download the pinned, checksum-verified ripgrep into the harnery tools dir on first miss (falls back to GNU grep on any failure). A repo commits this once and every clone self-heals

Env override per process: HARNERY_TOOLS_AUTOINSTALL=1|0.

Field Type Default Description
exclude string[] [] Shipped harnery skills this repo suppresses, e.g. ["harn-decide", "harn-council"] when the host keeps its own richer versions. The injected AGENTS.md block points at --help instead of an excluded skill
Field Type Default Description
hostAddendumFile string none Repo-relative path to a markdown file holding this project’s own coordination policy. init splices its contents into a second managed region in AGENTS.md, init --check reports drift against it, and deinit (or deleting this key) removes the region. Harnery never parses the content

The path must be repo-relative and resolve inside the project, and the file must exist and be non-empty; anything else fails the run before the first write. Delete the key and re-run init to take the region back out.

{ "instructions": { "hostAddendumFile": ".agents/host-instructions.md" } }
Field Type Default Description
enabled bool true Cross-machine presence over git refs (refs/harnery/presence/<machine> on origin). On by default when an origin remote exists; every operation is fail-silent
relay string unset Optional live upgrade: a wss:// relay URL (public reference: wss://relay.harnery.com; self-host via harn relay serve or relay/worker/). When set, hooks keep a per-machine daemon connected for seconds-latency presence; git refs stay on as the floor

Env overrides per process: HARNERY_PRESENCE=1|0 (whole feature), HARNERY_PRESENCE_RELAY=<url|0> (relay only), HARNERY_PRESENCE_FETCH_INTERVAL=<secs> (git-refs fetch throttle). A committed .harnery/presence-salt file rotates the relay room (it is NOT a secret; see decision record 0016). Full behavior: harn presence.

Field Type Default Description
port number 9000 Listen port for harn web up
bind string 127.0.0.1 Bind address. Localhost-only by default

Override via flags: harn web up --port 4000.

Field Type Default Description
repo string ~/.cache/harnery/restic-repo restic repository path or URL
password_file string ~/.config/harnery/restic-password File containing the restic repo password
keep_daily number 7 Daily snapshots to keep on harn backup prune
keep_weekly number 4 Weekly snapshots to keep
keep_monthly number 6 Monthly snapshots to keep

Env overrides: HARNERY_RESTIC_REPO, HARNERY_RESTIC_PASSWORD_FILE.

Field Type Default Description
remote string none rclone remote name (e.g. gdrive)
prefix string harnery Subpath under the remote root

Env overrides: HARNERY_SYNC_REMOTE, HARNERY_SYNC_PREFIX.

Sync subset is fixed: identities/, journal/archived/, councils/. Heartbeats and event logs are intentionally machine-local and won’t sync.

Web file-viewer path-serving policy (the universal file viewer in harn web). The shipped secret denylist is a non-removable floor baked into code; these knobs are additive only: they extend the floor, never shrink it.

Field Type Default Description
deny_globs string[] [] Extra **/-anchored deny patterns on top of the shipped floor (treated as hard-tier: never overridable)
allow_overrides string[] [] Rescue globs consulted only when a deny came from a soft-tier floor pattern; naming a hard secret family is dropped at load

Every section above is read from config.jsonc (both the user-global and project files, merged project-over-user). Env vars and CLI flags override the config value per invocation:

Section Config keys Env override Other
coord freshness_seconds HARNERY_AGENT_COORD_FRESHNESS (alias HARNERY_AGENT_FRESHNESS) (none)
artifacts default_retention_days HARNERY_ARTIFACT_RETENTION_DAYS artifacts create --days
backup repo, password_file, keep_* HARNERY_RESTIC_REPO, HARNERY_RESTIC_PASSWORD_FILE --keep-* flags override the prune policy per run
sync remote, prefix HARNERY_SYNC_REMOTE, HARNERY_SYNC_PREFIX ~/.config/harnery/sync.json (written by harn sync init) is a lower-precedence fallback than the sync config section
files deny_globs, allow_overrides (none) read by the web layer, not the core reader

Full precedence for a sync remote, highest first: HARNERY_SYNC_REMOTE env → project sync.remote → user-global sync.remote~/.config/harnery/sync.json.

{
"$schema": "https://harnery.com/schemas/config.schema.json",
"project_name": "my-monorepo",
"binName": "mycli",
"coord": {
"freshness_seconds": 900
},
"artifacts": {
"default_retention_days": 3
},
"web": {
"port": 9000
},
"tools": {
"ripgrep": { "autoInstall": true }
},
"workflow": {
"subscriptionOnly": true
},
"presence": {
"relay": "wss://relay.harnery.com"
},
"sync": {
"remote": "gdrive",
"prefix": "harnery/my-monorepo"
}
}

The schema lives at schemas/config.schema.json in the Harnery repo. v1 covers the fields above; future fields land additively with semver minor bumps. Breaking schema changes require a major bump and a migration note.