Config
Using the hordecode JSON config.
You can configure hordecode using a JSON config file.
Format
hordecode supports both JSON and JSONC (JSON with Comments) formats.
{ "$schema": "https://hordecode.com/config.json", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, "server": { "port": 4096, },}Locations
You can place your config in a couple of different locations and they have a different order of precedence.
Configuration files are merged together, not replaced. Settings from the following config locations are combined. Later configs override earlier ones only for conflicting keys. Non-conflicting settings from all configs are preserved.
For example, if your global config sets autoupdate: true and your project config sets model: "anthropic/claude-sonnet-4-5", the final configuration will include both settings.
Precedence order
Config sources are loaded in this order (later sources override earlier ones):
- Remote config (from
.well-known/hordecode) - organizational defaults - Global config (
~/.config/hordecode/hordecode.json) - user preferences - Custom config (
HORDECODE_CONFIGenv var) - custom overrides - Project config (
hordecode.jsonin project) - project-specific settings .hordecodedirectories - agents, commands, plugins- Inline config (
HORDECODE_CONFIG_CONTENTenv var) - runtime overrides - Managed config files (
/Library/Application Support/hordecode/on macOS) - admin-controlled - macOS managed preferences (
.mobileconfigvia MDM) - highest priority, not user-overridable
This means project configs can override global defaults, and global configs can override remote organizational defaults. Managed settings override everything.
Remote
Organizations can provide default configuration via the .well-known/hordecode endpoint. This is fetched automatically when you authenticate with a provider that supports it.
Remote config is loaded first, serving as the base layer. All other config sources (global, project) can override these defaults.
For example, if your organization provides MCP servers that are disabled by default:
{ "mcp": { "jira": { "type": "remote", "url": "https://jira.example.com/mcp", "enabled": false } }}You can enable specific servers in your local config:
{ "mcp": { "jira": { "type": "remote", "url": "https://jira.example.com/mcp", "enabled": true } }}Global
Place your global hordecode config in ~/.config/hordecode/hordecode.json. Use global config for user-wide server/runtime preferences like providers, models, and permissions.
For TUI-specific settings, use ~/.config/hordecode/tui.json.
Global config overrides remote organizational defaults.
Per project
Add hordecode.json in your project root. Project config has the highest precedence among standard config files - it overrides both global and remote configs.
For project-specific TUI settings, add tui.json alongside it.
When hordecode starts up, it first looks for a config file in the current directory, then traverses up to the nearest Git directory.
This is also safe to be checked into Git and uses the same schema as the global one.
Custom path
Specify a custom config file path using the HORDECODE_CONFIG environment variable.
export HORDECODE_CONFIG=/path/to/my/custom-config.jsonhorde run "Hello world"Custom config is loaded between global and project configs in the precedence order.
Custom directory
Specify a custom config directory using the HORDECODE_CONFIG_DIR
environment variable. This directory will be searched for agents, commands,
modes, and plugins just like the standard .hordecode directory, and should
follow the same structure.
export HORDECODE_CONFIG_DIR=/path/to/my/config-directoryhorde run "Hello world"The custom directory is loaded after the global config and .hordecode directories, so it can override their settings.
Managed settings
Organizations can enforce configuration that users cannot override. Managed settings are loaded at the highest priority tier.
File-based
Drop an hordecode.json or hordecode.jsonc file in the system managed config directory:
| Platform | Path |
|---|---|
| macOS | /Library/Application Support/hordecode/ |
| Linux | /etc/hordecode/ |
| Windows | %ProgramData%\hordecode |
These directories require admin/root access to write, so users cannot modify them.
macOS managed preferences
On macOS, hordecode reads managed preferences from the ai.hordecode.managed preference domain. Deploy a .mobileconfig via MDM (Jamf, Kandji, FleetDM) and the settings are enforced automatically.
hordecode checks these paths:
/Library/Managed Preferences/<user>/ai.hordecode.managed.plist/Library/Managed Preferences/ai.hordecode.managed.plist
The plist keys map directly to hordecode.json fields. MDM metadata keys (PayloadUUID, PayloadType, etc.) are stripped automatically.
Creating a .mobileconfig
Use the ai.hordecode.managed PayloadType. The hordecode config keys go directly in the payload dict:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>PayloadContent</key> <array> <dict> <key>PayloadType</key> <string>ai.hordecode.managed</string> <key>PayloadIdentifier</key> <string>com.example.hordecode.config</string> <key>PayloadUUID</key> <string>GENERATE-YOUR-OWN-UUID</string> <key>PayloadVersion</key> <integer>1</integer> <key>server</key> <dict> <key>hostname</key> <string>127.0.0.1</string> </dict> <key>permission</key> <dict> <key>*</key> <string>ask</string> <key>bash</key> <dict> <key>*</key> <string>ask</string> <key>rm -rf *</key> <string>deny</string> </dict> </dict> </dict> </array> <key>PayloadType</key> <string>Configuration</string> <key>PayloadIdentifier</key> <string>com.example.hordecode</string> <key>PayloadUUID</key> <string>GENERATE-YOUR-OWN-UUID</string> <key>PayloadVersion</key> <integer>1</integer></dict></plist>Generate unique UUIDs with uuidgen. Customize the settings to match your organization’s requirements.
Deploying via MDM
- Jamf Pro: Computers > Configuration Profiles > Upload > scope to target devices or smart groups
- FleetDM: Add the
.mobileconfigto your gitops repo undermdm.macos_settings.custom_settingsand runfleetctl apply
Verifying on a device
Double-click the .mobileconfig to install locally for testing (shows in System Settings > Privacy & Security > Profiles), then run:
horde debug configAll managed preference keys appear in the resolved config and cannot be overridden by user or project configuration.
Schema
The server/runtime config schema is defined in hordecode.com/config.json.
TUI config uses hordecode.com/tui.json.
Your editor should be able to validate and autocomplete based on the schema.
TUI
Use a dedicated tui.json (or tui.jsonc) file for TUI-specific settings.
{ "$schema": "https://hordecode.com/tui.json", "scroll_speed": 3, "scroll_acceleration": { "enabled": true }, "diff_style": "auto", "cursor": { "style": "block", "blinking": true }, "mouse": true, "attention": { "enabled": true, "notifications": true, "sound": true, "volume": 0.4 }}Use HORDECODE_TUI_CONFIG to point to a custom TUI config file.
When cursor.style is "default", the terminal default cursor is restored, so cursor.blinking has no effect.
Set attention.enabled to turn on TUI desktop notifications and sounds. See TUI attention.
Legacy theme, keybinds, and tui keys in hordecode.json are deprecated and automatically migrated when possible.
Server
You can configure server settings for the horde serve and horde web commands through the server option.
{ "$schema": "https://hordecode.com/config.json", "server": { "port": 4096, "hostname": "0.0.0.0", "mdns": true, "mdnsDomain": "myproject.local", "cors": ["http://localhost:5173"] }}Available options:
port- Port to listen on.hostname- Hostname to listen on. Whenmdnsis enabled and no hostname is set, defaults to0.0.0.0.mdns- Enable mDNS service discovery. This allows other devices on the network to discover your hordecode server.mdnsDomain- Custom domain name for mDNS service. Defaults tohordecode.local. Useful for running multiple instances on the same network.cors- Additional origins to allow for CORS when using the HTTP server from a browser-based client. Values must be full origins (scheme + host + optional port), eghttps://app.example.com.
Learn more about the server here.
Shell
You can configure the shell used for the interactive terminal using the shell option. Compatible shells are also used for agent tool calls.
{ "$schema": "https://hordecode.com/config.json", "shell": "pwsh"}If not specified, hordecode will automatically discover and use a sensible default based on your operating system (e.g. pwsh or cmd.exe on Windows, /bin/zsh or /bin/bash on macOS/Linux). You can provide an absolute path or a short name.
Tools
You can manage the tools an LLM can use through the tools option.
{ "$schema": "https://hordecode.com/config.json", "tools": { "write": false, "bash": false }}Models
You can configure the providers and models you want to use in your hordecode config through the provider, model and small_model options.
{ "$schema": "https://hordecode.com/config.json", "provider": {}, "model": "anthropic/claude-sonnet-4-5", "small_model": "anthropic/claude-haiku-4-5"}model also accepts a model group name such as standard, and then uses that group’s default member. Group names also work in agent models, command models, supervisor spawns, compaction and titles. An unknown group name logs a warning and the normal default applies.
The small_model option configures a separate model for lightweight tasks like title generation. By default, hordecode tries to use a cheaper model if one is available from your provider, otherwise it falls back to your main model.
Provider options can include timeout, chunkTimeout, and setCacheKey:
{ "$schema": "https://hordecode.com/config.json", "provider": { "anthropic": { "options": { "timeout": 600000, "chunkTimeout": 30000, "setCacheKey": true } } }}timeout- Request timeout in milliseconds (default: 300000). Set tofalseto disable.chunkTimeout- Timeout in milliseconds between streamed response chunks. If no chunk arrives in time, the request is aborted.setCacheKey- Ensure a cache key is always set for designated provider.
You can also configure local models. Learn more.
Policies
Use the experimental.policies option to allow or deny hordecode actions on configured resources. Currently, policies can control which providers hordecode may use.
{ "$schema": "https://hordecode.com/config.json", "experimental": { "policies": [ { "effect": "deny", "action": "provider.use", "resource": "openai" } ] }}Learn more about policies here.
Image attachments
hordecode normalizes image attachments before sending them to the model. By default, images are resized when they exceed 2000x2000 pixels or 5242880 base64 bytes.
Configure image attachment limits with the attachment.image option:
{ "$schema": "https://hordecode.com/config.json", "attachment": { "image": { "auto_resize": true, "max_width": 2000, "max_height": 2000, "max_base64_bytes": 5242880 } }}auto_resize- Resize images that exceed the configured limits before provider requests. Set tofalseto reject oversized images instead.max_width- Maximum image width in pixels before resizing or rejection.max_height- Maximum image height in pixels before resizing or rejection.max_base64_bytes- Maximum encoded image payload size. This is the base64 payload size, not the original file size.
If an image still cannot fit after resizing, hordecode omits oversized tool-result images or fails oversized user-provided images with an image size error.
Provider-Specific Options
Some providers support additional configuration options beyond the generic timeout and apiKey settings.
Amazon Bedrock
Amazon Bedrock supports AWS-specific configuration:
{ "$schema": "https://hordecode.com/config.json", "provider": { "amazon-bedrock": { "options": { "region": "us-east-1", "profile": "my-aws-profile", "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" } } }}region- AWS region for Bedrock (defaults toAWS_REGIONenv var orus-east-1)profile- AWS named profile from~/.aws/credentials(defaults toAWS_PROFILEenv var)endpoint- Custom endpoint URL for VPC endpoints. This is an alias for the genericbaseURLoption using AWS-specific terminology. If both are specified,endpointtakes precedence.
Learn more about Amazon Bedrock configuration.
Themes
Set your UI theme in tui.json.
{ "$schema": "https://hordecode.com/tui.json", "theme": "tokyonight"}Agents
You can configure specialized agents for specific tasks through the agent option.
{ "$schema": "https://hordecode.com/config.json", "agent": { "code-reviewer": { "description": "Reviews code for best practices and potential issues", "model": "anthropic/claude-sonnet-4-5", "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", "tools": { // Disable file modification tools for review-only agent "write": false, "edit": false, }, }, },}You can also define agents using markdown files in ~/.config/hordecode/agents/ or .hordecode/agents/. Learn more here.
Default agent
You can set the default agent using the default_agent option. This determines which agent is used when none is explicitly specified.
{ "$schema": "https://hordecode.com/config.json", "default_agent": "plan"}The default agent must be a primary agent (not a subagent). This can be a built-in agent like "build" or "plan", or a custom agent you’ve defined. If the specified agent doesn’t exist or is a subagent, hordecode will fall back to "build" with a warning.
This setting applies across all interfaces: TUI, CLI (horde run), and GitHub Action.
Subagent depth
You can control how deeply subagents can invoke other subagents using the subagent_depth option.
{ "$schema": "https://hordecode.com/config.json", "subagent_depth": 5}The default is 3, which covers the supervision chain: the main agent, a coordinating supervisor, its workers, and helpers they run. Values from 0 to 8 are accepted; 1 lets primary agents launch subagents while keeping those subagents from launching more. Only subagent links count toward the depth.
Concurrent subagents
The supervisor tool runs up to 8 subagents at once in a session and the sessions under it. Raise this with supervisor.max_subagents, up to 16.
{ "$schema": "https://hordecode.com/config.json", "supervisor": { "max_subagents": 12 }}Workflow agents use their own limit, workflow.maxConcurrentAgents.
Commands
You can configure custom commands for repetitive tasks through the command option.
{ "$schema": "https://hordecode.com/config.json", "command": { "test": { "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.", "description": "Run tests with coverage", "agent": "build", "model": "anthropic/claude-haiku-4-5", }, "component": { "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.", "description": "Create a new component", }, },}You can also define commands using markdown files in ~/.config/hordecode/commands/ or .hordecode/commands/. Learn more here.
Keybinds
Customize TUI keyboard shortcuts in tui.json with keybinds.
{ "$schema": "https://hordecode.com/tui.json", "keybinds": { "command_list": "ctrl+p" }}keybinds is merged with built-in defaults, so you only need to configure the shortcuts you want to change.
Snapshot
hordecode uses snapshots to track file changes during agent operations, enabling you to undo and revert changes within a session. Snapshots are enabled by default.
For large repositories or projects with many submodules, the snapshot system can cause slow indexing and significant disk usage as it tracks all changes using an internal git repository. You can disable snapshots using the snapshot option.
{ "$schema": "https://hordecode.com/config.json", "snapshot": false}Note that disabling snapshots means changes made by the agent cannot be rolled back through the UI.
Autoupdate
hordecode checks for a newer version when it starts up and shows an update notice. The update installs when you confirm the notice or run horde upgrade. To turn the check off, set the autoupdate option to false.
{ "$schema": "https://hordecode.com/config.json", "autoupdate": false}Formatters
You can enable and configure code formatters through the formatter option. Omit it to keep formatters disabled.
{ "$schema": "https://hordecode.com/config.json", "formatter": true}Use an object to keep built-ins enabled while configuring overrides or custom formatters.
{ "$schema": "https://hordecode.com/config.json", "formatter": { "prettier": { "disabled": true }, "custom-prettier": { "command": ["npx", "prettier", "--write", "$FILE"], "environment": { "NODE_ENV": "development" }, "extensions": [".js", ".ts", ".jsx", ".tsx"] } }}Learn more about formatters here.
LSP Servers
You can enable and configure LSP servers through the lsp option. Omit it to keep LSP disabled.
{ "$schema": "https://hordecode.com/config.json", "lsp": true}Use an object to keep built-ins enabled while configuring overrides or custom LSP servers.
{ "$schema": "https://hordecode.com/config.json", "lsp": { "typescript": { "disabled": true } }}Learn more about LSP servers here.
Permissions
By default, hordecode allows all operations without requiring explicit approval. You can change this using the permission option.
For example, to ensure that the edit and bash tools require user approval:
{ "$schema": "https://hordecode.com/config.json", "permission": { "edit": "ask", "bash": "ask" }}Learn more about permissions here.
Compaction
You can control context compaction behavior through the compaction option.
{ "$schema": "https://hordecode.com/config.json", "compaction": { "auto": true, "prune": false, "reserved": 10000 }}auto- Automatically compact the session when context is full (default:true).prune- Remove old tool outputs to save tokens (default:false). Set totrueto enable pruning.reserved- Token buffer for compaction. Leaves enough window to avoid overflow during compaction.
Watcher
You can configure file watcher ignore patterns through the watcher option.
{ "$schema": "https://hordecode.com/config.json", "watcher": { "ignore": ["node_modules/**", "dist/**", ".git/**"] }}Patterns follow glob syntax. Use this to exclude noisy directories from file watching.
MCP servers
You can configure MCP servers you want to use through the mcp option.
{ "$schema": "https://hordecode.com/config.json", "mcp": {}}Plugins
Plugins extend hordecode with custom tools, hooks, and integrations.
Place plugin files in .hordecode/plugins/ or ~/.config/hordecode/plugins/. You can also load plugins from npm through the plugin option.
{ "$schema": "https://hordecode.com/config.json", "plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]}Instructions
You can configure the instructions for the model you’re using through the instructions option.
{ "$schema": "https://hordecode.com/config.json", "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]}This takes an array of paths and glob patterns to instruction files. Learn more about rules here.
Disabled providers
You can disable providers that are loaded automatically through the disabled_providers option. This is useful when you want to prevent certain providers from being loaded even if their credentials are available.
{ "$schema": "https://hordecode.com/config.json", "disabled_providers": ["openai", "gemini"]}The disabled_providers option accepts an array of provider IDs. When a provider is disabled:
- It won’t be loaded even if environment variables are set.
- It won’t be loaded even if API keys are configured through the
/connectcommand. - The provider’s models won’t appear in the model selection list.
Enabled providers
You can specify an allowlist of providers through the enabled_providers option. When set, only the specified providers will be enabled and all others will be ignored.
{ "$schema": "https://hordecode.com/config.json", "enabled_providers": ["anthropic", "openai"]}This is useful when you want to restrict hordecode to only use specific providers rather than disabling them one by one.
If a provider appears in both enabled_providers and disabled_providers, the disabled_providers takes priority for backwards compatibility.
Experimental
The experimental key contains options that are under active development.
{ "$schema": "https://hordecode.com/config.json", "experimental": {}}Switches
experimental.switches turns on hordecode features that are off by default. Set them in the global config file (the hordecode.jsonc in your global config directory).
{ "$schema": "https://hordecode.com/config.json", "experimental": { "switches": { "permission_audit": true, "sandbox": true, "hashline": true } }}| Key | Environment variable | Default | Effect |
|---|---|---|---|
workspaces | HORDECODE_EXPERIMENTAL_WORKSPACES | off | Workspaces and Warp, which moves a session into a git worktree |
orchestrator | HORDECODE_EXPERIMENTAL_ORCHESTRATOR | off | The orchestrator agent |
workflow_tool | HORDECODE_EXPERIMENTAL_WORKFLOW_TOOL | on | Workflow commands |
cron | HORDECODE_EXPERIMENTAL_CRON | on | Cron commands |
permission_audit | HORDECODE_PERMISSION_AUDIT | off | The permission audit log |
sandbox | HORDECODE_SANDBOX | off | The shell sandbox on Linux (true sets auto) |
hashline | HORDECODE_HASHLINE | off | The hashline edit tools |
workflow_tool and cron stay on unless they are set to false. The other switches are on only when set to true. An environment variable that is set wins over the config value. HORDECODE_SANDBOX=required is set in the environment only. HORDECODE_EXPERIMENTAL=true also turns on workspaces and orchestrator.
The switches are read once at startup, so restart hordecode after you change one. The Hordecode features dialog (ctrl+p, then System) edits these switches and the memory.embedding setting, and asks for a restart when you save. It shows the environment variable next to any row that an environment variable sets.
Advisor
The advisor is an optional second model that reviews the current task when the work looks risky. It is off by default. When a trigger fires, the advisor reads a compact transcript of the current turn and returns up to a few short notes, each marked nit, concern or blocker. The notes reach the agent in its next model call, and the cost of the advisor call is added to that step. The advisor runs in primary sessions only and cannot change files.
The triggers are checked at each step:
- files touched in the current turn
- failed tool calls, including a shell command that exits with a non-zero code
- the same error repeated
- context used, as a percentage of the model’s context window
{ "$schema": "https://hordecode.com/config.json", "experimental": { "advisor": { "enabled": true, "model": "anthropic/claude-sonnet-5-5", "sensitivity": "default", "min_severity": "concern", "triggers": { "files_touched": 8, "tool_failures": 3, "same_error": 2, "context_percent": 70 }, "max_notes": 4, "cooldown_steps": 3 } }}enabled-trueturns the advisor on.modelmust be set as well.model- Aprovider/modelvalue or a model group name.sensitivity-low,defaultorhigh. Sets the presets below.min_severity- The lowest note that is kept:nit,concern(the default) orblocker.triggers- Thresholds for the four triggers. An explicit value overrides the preset.max_notes- The most non-blocker notes kept per review (default4). Blockers are always kept.cooldown_steps- Steps to wait after a review before the next one. An explicit value overrides the preset.
| Sensitivity | files_touched | tool_failures | same_error | context_percent | cooldown_steps |
|---|---|---|---|---|---|
low | 12 | 4 | 3 | 85 | 6 |
default | 8 | 3 | 2 | 70 | 3 |
high | 5 | 2 | 2 | 60 | 2 |
A threshold of 0 turns that trigger off. Cooldown and repeat suppression reset on each new user message. Within a turn, a review does not repeat for the same triggers, only when a new trigger joins them.
You can also set all of this from the TUI with the Advisor command, where changes apply without a restart.
Unknown keys
Config keys that hordecode does not know are logged at startup with a did-you-mean suggestion, and the TUI shows a warning toast once after startup. Loading is unchanged. horde debug config lists them on stderr.
Variables
You can use variable substitution in your config files to reference environment variables and file contents.
Env vars
Use {env:VARIABLE_NAME} to substitute environment variables:
{ "$schema": "https://hordecode.com/config.json", "model": "{env:HORDECODE_MODEL}", "provider": { "anthropic": { "models": {}, "options": { "apiKey": "{env:ANTHROPIC_API_KEY}" } } }}If the environment variable is not set, it will be replaced with an empty string.
Files
Use {file:path/to/file} to substitute the contents of a file:
{ "$schema": "https://hordecode.com/config.json", "instructions": ["./custom-instructions.md"], "provider": { "openai": { "options": { "apiKey": "{file:~/.secrets/openai-key}" } } }}File paths can be:
- Relative to the config file directory
- Or absolute paths starting with
/or~
These are useful for:
- Keeping sensitive data like API keys in separate files.
- Including large instruction files without cluttering your config.
- Sharing common configuration snippets across multiple config files.