Skip to content

Configuration reference

netclaw reads one JSON file, netclaw.json, plus a few overlays. This page lists every key, with its type, default and allowed values, so you can find a setting or confirm what a default is. It describes netclaw 0.28.2. A key that isn’t in your file uses the default shown here, and netclaw init writes only the settings it asks you about.

WhatWhere
Settings~/.netclaw/config/netclaw.json, or $NETCLAW_HOME/config/netclaw.json
Secrets (tokens, API keys)config/secrets.json beside it. Write them with netclaw secrets set so they’re encrypted
Webhook routesOne file each under config/webhooks/, not in netclaw.json

The file needs "configVersion": 1 at the top level. Everything else is a section, and the section names below are the top-level keys.

Later sources win:

  1. Defaults compiled into netclaw (the Default column below)
  2. netclaw.json
  3. secrets.json
  4. NETCLAW_ environment variables

Prefix the key path with NETCLAW_ and join the path segments with __ (two underscores). Lists take a zero-based index per item, and a map key is just another segment.

Terminal window
# Daemon.Port
NETCLAW_Daemon__Port=5200
# Tools.WebFetch.HttpAllowList, an array of two hosts
NETCLAW_Tools__WebFetch__HttpAllowList__0=localhost
NETCLAW_Tools__WebFetch__HttpAllowList__1=host.docker.internal
# Slack.ChannelAudiences, a map: the channel ID is the key
NETCLAW_Slack__ChannelAudiences__C0123ABCD=team

In Docker Compose these go under environment:. Don’t set the same list in the file and in the environment. A list from one source and a plain value from the other stops startup.

A list you configure is the whole list. Before 0.27.1 netclaw added your items to the built-in ones, so you couldn’t narrow a grant. This applies to AllowedTools, the Roots lists, GlobalReadRoots, ChannelAttachments.AllowedCategories and WebFetch.HttpAllowList:

{
"Tools": {
"AudienceProfiles": {
"Team": { "AllowedTools": ["file_read", "file_list", "tool_output_read"] }
}
}
}

That Team profile now has three tools and nothing else. [] gives an empty list. A null or {} value gives an empty list and a startup warning. A value that isn’t a list stops the daemon at startup with Configuration key '...' must be a list, but it has a scalar value. If you narrow a Public or Team list, keep tool_output_read, because spilled tool output tells the model to call it. netclaw doctor warns when it’s missing.

An older list that exactly matches a default from an earlier release is treated as the current default, and netclaw doctor --fix deletes it so the audience follows future defaults. An older list you edited is applied as written.

The daemon restarts itself, after draining sessions, whenever netclaw.json changes. That includes Daemon.Port, Daemon.Host and Daemon.ExposureMode. Nothing else triggers it. A change to secrets.json or to an environment variable needs a manual restart: docker restart <container> in Docker, systemctl --user restart netclaw for the systemd unit, or netclaw daemon stop then netclaw daemon start natively.

Run netclaw doctor after every edit. It validates netclaw.json against the schema, checks secrets.json, and reports tool profile problems with the exact key. The daemon’s check before a restart doesn’t catch a malformed Tools list, so such a file restarts the daemon and then crashes it at startup. In Docker the entrypoint retries with a growing delay and the container keeps running while the daemon doesn’t, so docker logs <container> shows the error.

These stop startup:

CauseMessage starts with
A Tools list that isn’t a list, or an invalid enum item in oneConfiguration key 'Tools...
A Persistence sectionPersistence configuration is not supported
Inline Models.Main mixed with Models.Definitions and Models.RolesModels configuration mixes legacy inline roles
An unknown Daemon.ExposureMode or Daemon.UpdateChannelUnknown ExposureMode value or Unknown UpdateChannel value
A Telemetry.Otlp.Endpoint that isn’t an absolute URITelemetry:Otlp:Endpoint must be an absolute URI
An invalid Models or Providers section: a bad role reference, a provider with no credential or endpoint, an unknown type, a MaxOutputTokens that isn’t below ContextWindow, or a Thinking level the provider dialect can’t sendOne line naming the key. The daemon exits 1, and a running daemon refuses to reload such a file and keeps its config. Models lists each case
  • A dotted path is the JSON nesting: Memory.Recall.VectorWeight is { "Memory": { "Recall": { "VectorWeight": 0.7 } } }.
  • <name>, <server> and <audience> stand for a key you choose or one of Public, Team and Personal. [] marks an array item.
  • unset means the key is absent or null and netclaw picks the behavior described. required means netclaw or the schema rejects the entry without it.
  • Keys marked secret go in secrets.json, not netclaw.json.

The Slack adapter. Set up Slack walks through the app manifest and tokens.

KeyTypeDefaultAllowed valuesDescription
Slack.Enabledbooleanfalse-Start this channel adapter. Needs the bot token in secrets.json.
Slack.BotTokenstring (secret)unset-Bot token, xoxb-. Lives in secrets.json: netclaw secrets set Slack.BotToken <token>.
Slack.AppTokenstring (secret)unset-App-level token, xapp-, for Socket Mode. Lives in secrets.json.
Slack.SocketModebooleantrue-Connect over Slack Socket Mode. Needs the app-level token (Slack.AppToken).
Slack.DefaultChannelIdstring (nullable)unset-Default channel for messages the bot starts itself, such as reminder deliveries. It also counts as an allowed channel.
Slack.DefaultChannelNamestring (nullable)unset-A channel name the daemon resolves to an ID at startup when DefaultChannelId is unset. An unresolved name logs a warning. The netclaw config Slack editor deletes it and writes the ID.
Slack.MentionOnlybooleantrue-Respond in channels only when the bot is mentioned.
Slack.AllowDirectMessagesbooleanfalse-Accept direct messages. DMs use the audience mapped to the dm key in ChannelAudiences.
Slack.MentionRequiredInDmbooleanfalse-Require a mention in DMs too. Applies only when AllowDirectMessages is true.
Slack.MentionRequiredInThreadByChannelmap of boolean{}-Per-channel switch, keyed by channel ID. true requires a mention in thread replies even when the thread already has an active session. A channel with no entry doesn’t.
Slack.AllowedChannelIdsarray of string[]-Channel IDs the bot responds in, in addition to DefaultChannelId. Messages from any other channel are denied.
Slack.AllowedUserIdsarray of string[]-User IDs allowed to talk to the bot. An empty list allows every user in an allowed channel. A listed user is treated as a trusted internal principal.
Slack.ChannelAudiencesmap of string{}values: personal, team, publicAudience per channel, keyed by channel ID or dm. Unmapped channels fall back to the ACL heuristic. The audience picks the Tools.AudienceProfiles entry that applies.

The Discord adapter. Set up Discord covers the bot, intents and tokens.

KeyTypeDefaultAllowed valuesDescription
Discord.Enabledbooleanfalse-Start this channel adapter. Needs the bot token in secrets.json.
Discord.BotTokenstring (secret)unset-Bot token. Lives in secrets.json: netclaw secrets set Discord.BotToken <token>.
Discord.DefaultChannelIdstring (nullable)unset-Default channel for messages the bot starts itself, such as reminder deliveries. It also counts as an allowed channel.
Discord.AllowDirectMessagesbooleanfalse-Accept direct messages. DMs use the audience mapped to the dm key in ChannelAudiences.
Discord.MentionOnlybooleantrue-Respond in channels only when the bot is mentioned.
Discord.MentionRequiredInDmbooleanfalse-Require a mention in DMs too. Applies only when AllowDirectMessages is true.
Discord.MentionRequiredInThreadByChannelmap of boolean{}-Per-channel switch, keyed by channel ID. true requires a mention in thread replies even when the thread already has an active session. A channel with no entry doesn’t.
Discord.AllowedChannelIdsarray of string[]-Channel IDs the bot responds in, in addition to DefaultChannelId. Messages from any other channel are denied.
Discord.AllowedUserIdsarray of string[]-User IDs allowed to talk to the bot. An empty list allows every user in an allowed channel. A listed user is treated as a trusted internal principal.
Discord.ChannelAudiencesmap of string{}values: personal, team, publicAudience per channel, keyed by channel ID or dm. Unmapped channels fall back to the ACL heuristic. The audience picks the Tools.AudienceProfiles entry that applies.

The Mattermost adapter. Set up Mattermost covers the bot account and callback URL.

KeyTypeDefaultAllowed valuesDescription
Mattermost.Enabledbooleanfalse-Start this channel adapter. Needs the bot token in secrets.json.
Mattermost.BotTokenstring (secret)unset-Bot access token. Lives in secrets.json: netclaw secrets set Mattermost.BotToken <token>.
Mattermost.ServerUrlstring (nullable)unset-Base URL of the Mattermost server, for example https://mm.example.com.
Mattermost.CallbackUrlstring (nullable)unset-URL Mattermost can reach for interactive button callbacks, for example http://netclaw-host:5199/api/mattermost/actions. When unset, approvals fall back to text replies, except for a subagent’s approval request, which needs buttons: the binding refuses it and the session withdraws it.
Mattermost.DefaultChannelIdstring (nullable)unset-Default channel for messages the bot starts itself, such as reminder deliveries. It also counts as an allowed channel.
Mattermost.AllowDirectMessagesbooleanfalse-Accept direct messages. DMs use the audience mapped to the dm key in ChannelAudiences.
Mattermost.MentionOnlybooleantrue-Respond in channels only when the bot is mentioned.
Mattermost.MentionRequiredInDmbooleanfalse-Require a mention in DMs too. Applies only when AllowDirectMessages is true.
Mattermost.MentionRequiredInThreadByChannelmap of boolean{}-Per-channel switch, keyed by channel ID. true requires a mention in thread replies even when the thread already has an active session. A channel with no entry doesn’t.
Mattermost.AllowedChannelIdsarray of string[]-Channel IDs the bot responds in, in addition to DefaultChannelId. Messages from any other channel are denied.
Mattermost.AllowedUserIdsarray of string[]-User IDs allowed to talk to the bot. An empty list allows every user in an allowed channel. A listed user is treated as a trusted internal principal.
Mattermost.ChannelAudiencesmap of string{}values: personal, team, publicAudience per channel, keyed by channel ID or dm. Unmapped channels fall back to the ACL heuristic. The audience picks the Tools.AudienceProfiles entry that applies.

Daemon log level and console output. Logs go to daemon-<date>.log under the data directory regardless of these keys, rolling into numbered segments at 10 MiB.

KeyTypeDefaultAllowed valuesDescription
Logging.LogLevel.Defaultstring"Information"Trace, Debug, Information, Warning, Error, Critical, NoneMinimum level written to daemon-<date>.log. An unset or unrecognized value gives Information. Other keys under Logging.LogLevel (for example Microsoft) set per-category levels.
Logging.Console.Enabledbooleanfalse-Also write single-line log output to the console. Docker and systemd capture it.

OpenTelemetry export. OpenTelemetry shows how to wire a collector.

KeyTypeDefaultAllowed valuesDescription
Telemetry.Enabledbooleanfalse-Export metrics and logs over OTLP. netclaw has no tracing exporter.
Telemetry.Otlp.Endpointstring"http://127.0.0.1:4317"-OTLP collector base URL. Must be an absolute URI. Over HTTP/protobuf netclaw posts to v1/logs and v1/metrics under it, and reduces a full signal URL to its base. gRPC uses the URL unchanged.

Per-conversation timeouts, compaction and memory-capture timing. The timeout keys take whole seconds, IdleTimeout takes HH:mm:ss. Sessions explains the lifecycle these keys tune.

KeyTypeDefaultAllowed valuesDescription
Session.MaxToolIterationsPerTurninteger601 to 500Legacy key kept so existing files still load. It is validated (1 to 500) but no longer limits a turn. netclaw refuses a call that repeats the same work, and the watchdog timeouts bound the rest.
Session.MemoryObserverIdleSecondsinteger9010 or moreSeconds of quiet before the memory observer distills the conversation into memories.
Session.IdleTimeoutstring"01:00:00"-How long a session sits idle before it saves a snapshot and passivates. Format HH:mm:ss. 00:00:00 disables passivation. Background jobs owned by the session are killed when it passivates.
Session.TurnLlmTimeoutSecondsinteger1801 or moreTimeout for the main per-turn model call. Also feeds the FirstTokenTimeoutSeconds fallback.
Session.ToolExecutionTimeoutSecondsinteger901 or moreInactivity budget per tool call. The call must produce its first result within this time and each later streamed item resets it. A stuck tool fails alone without affecting the others in the batch. Background shell jobs aren’t bound by it.
Session.SidecarLlmTimeoutSecondsinteger901 or moreTimeout for background model calls: title generation, memory distillation and compaction notes. Raise it for slow models.
Session.FirstTokenTimeoutSecondsinteger60010 to 1800Maximum silence between streamed deltas once the first one arrives. Subagent runs use it too, since agent definitions no longer carry timeoutSeconds. If unset, it uses TurnLlmTimeoutSeconds when you changed that, otherwise 600.
Session.PrefillTimeoutSecondsinteger180060 to 7200Maximum wait for the first streamed delta. Covers queue wait and prompt prefill, which can take minutes on self-hosted backends.
Session.NoProgressTimeoutSecondsinteger120060 to 7200Hard ceiling on time without a real output token. Keepalive heartbeats don’t reset it, so a backend that heartbeats forever without producing a token is killed when it elapses. The value also sets the thinking cap: one model call that streams only thinking, with no answer text and no tool call, stops at three times this value.
Session.CompactionThresholdnumber0.750.1 to 1Fraction of the context window that triggers compaction. Same as Session.Tuning.CompactionThreshold. The Tuning value wins when both are set.
Session.SnapshotIntervalinteger201 or moreTurns between persistence snapshots. Same as Session.Tuning.SnapshotInterval.
Session.KeepRecentToolResultsinteger30 or moreRecent tool call and result pairs kept in full when compaction clears older results. Same as Session.Tuning.KeepRecentToolResults.
Session.MaxInlineToolResultCharsinteger12000100 or moreLargest tool result placed inline in the conversation. For longer output the last this-many characters stay inline, the rest is dropped from the inline text, and the full output goes to a session file the model reads with tool_output_read. shell_execute has its own smaller budget of 2,000. Same as Session.Tuning.MaxInlineToolResultChars.
Session.DiscoveredToolRetentionTurnsinteger30 or moreUser turns a tool loaded with load_tool stays available. 0 makes the model load it again every turn. Same as Session.Tuning.DiscoveredToolRetentionTurns.
Session.DiscoveredToolMaxCountinteger120 or moreMost loaded deferred or MCP tools kept across turns. The oldest are evicted first. Same as Session.Tuning.DiscoveredToolMaxCount.
Session.KeepRecentMessagesinteger61 or moreRecent messages kept verbatim after compaction summarizes the rest. Counts raw messages, not turn pairs. Same as Session.Tuning.KeepRecentMessages.
Session.TitleGenerationIntervalinteger100 or moreTurns between session title refreshes. The title is always generated on turn 1. 0 disables refreshes. Same as Session.Tuning.TitleGenerationInterval.
Session.DeterministicRetrievalEnabledbooleantrue-Plan automatic memory recall deterministically on each turn. Scheduled for removal, leave it on. Same as Session.Tuning.DeterministicRetrievalEnabled.
Session.MemoryDistillationTurnIntervalinteger50 or moreSame as Session.Tuning.MemoryDistillationTurnInterval.
Session.MinimumRecallCompositeScorenumber (nullable)unset0 or moreSame as Session.Tuning.MinimumRecallCompositeScore.
Session.MaxToolDescriptionCharsinteger20480 or moreSame as Session.Tuning.MaxToolDescriptionChars.
Session.MaxToolSchemaWarnCharsinteger80000 or moreSame as Session.Tuning.MaxToolSchemaWarnChars.
Session.Tuningobject--Internal tuning. Every key here has a same-named key directly under Session, and the Tuning value wins.
Session.Tuning.CompactionThresholdnumber0.750.1 to 1See Session.CompactionThreshold.
Session.Tuning.SnapshotIntervalinteger201 or moreSee Session.SnapshotInterval.
Session.Tuning.KeepRecentToolResultsinteger30 or moreSee Session.KeepRecentToolResults.
Session.Tuning.MaxInlineToolResultCharsinteger12000100 or moreSee Session.MaxInlineToolResultChars.
Session.Tuning.DiscoveredToolRetentionTurnsinteger30 or moreSee Session.DiscoveredToolRetentionTurns.
Session.Tuning.DiscoveredToolMaxCountinteger120 or moreSee Session.DiscoveredToolMaxCount.
Session.Tuning.KeepRecentMessagesinteger61 or moreSee Session.KeepRecentMessages.
Session.Tuning.TitleGenerationIntervalinteger100 or moreSee Session.TitleGenerationInterval.
Session.Tuning.DeterministicRetrievalEnabledbooleantrue-See Session.DeterministicRetrievalEnabled.
Session.Tuning.MemoryDistillationTurnIntervalinteger50 or moreCompleted turns between memory distillation passes, regardless of idle state, so memories form during long active sessions. 0 leaves distillation to MemoryObserverIdleSeconds.
Session.Tuning.MaxToolDescriptionCharsinteger20480 or moreLongest MCP tool description kept at registration. Longer ones are truncated to protect the context window. 0 turns truncation off.
Session.Tuning.MaxToolSchemaWarnCharsinteger80000 or moreSize of an MCP tool’s JSON schema that triggers a warning in the log. The schema itself is never truncated, so this only reports bloated tool definitions. 0 turns the warning off.
Session.Tuning.MinimumRecallCompositeScorenumber (nullable)unset0 or moreMinimum composite score for a memory to be injected by automatic recall. Unset uses the coordinator’s built-in floor. Lower values let weaker matches through, 0 removes the floor.
Session.Tuning.MaxRecallInjectedCharsinteger20000 or moreCharacter budget for memory text injected by automatic recall in one turn. Whole items are dropped rather than truncated. 0 removes the budget.
Session.Tuning.StreamingRetryPolicyobject--Retry policy for transient streaming LLM failures (HTTP 408, 429 and 5xx). It applies only before the first streamed data arrives.
Session.Tuning.StreamingRetryPolicy.MaxRetriesinteger30 or moreMaximum number of retries after the first attempt.
Session.Tuning.StreamingRetryPolicy.BaseDelaystring"00:00:01"HH:mm:ssDelay before the first retry in HH:mm:ss format. The delay doubles on each retry, with jitter.
Session.Tuning.StreamingRetryPolicy.MaxDelaystring"00:00:30"HH:mm:ssUpper limit on the delay between retries in HH:mm:ss format.

A value below a key’s minimum fails netclaw doctor schema validation. The daemon itself enforces a 1 second minimum on TurnLlmTimeoutSeconds, ToolExecutionTimeoutSeconds and SidecarLlmTimeoutSeconds.

Deployment posture and shell mode, which choose the default tool profiles. Security model explains the three postures.

KeyTypeDefaultAllowed valuesDescription
Security.DeploymentPosturestring (nullable)unsetPublic, Team, PersonalWho talks to this install: Personal (you), Team or Public. netclaw init writes it. When it’s unset and StrictDefaults is true, netclaw behaves as Public and denies shell_execute. It selects the default tool profiles and shell mode, and it narrows the audience of every turn: a channel mapped to Personal under a Team posture runs as Team.
Security.ShellExecutionModestring (nullable)unsetOff, SandboxOnly, HostAllowedWhether shell_execute can run. Unset gives HostAllowed for a Personal posture and Off for the others. Tools.ShellMode overrides it. SandboxOnly denies every shell call with shell_requires_sandbox_backend.
Security.StrictDefaultsbooleantrue-Fail closed when posture or shell mode is unset. Set false only to get Personal and HostAllowed as the implicit defaults.

Tool grants per audience, file roots, approval policy and web_fetch limits. A configured list replaces the default list, so a list with one tool grants one tool. Built-in tools lists the tools and defaults, and How tool approvals work covers ApprovalPolicy.

KeyTypeDefaultAllowed valuesDescription
Tools.ShellModestring (nullable)unsetOff, SandboxOnly, HostAllowedOverrides Security.ShellExecutionMode for the shell tools. Unset follows the security setting.
Tools.MaxOutputCharsinteger2560001 or moreMost output a tool call captures in memory for the spill file. It isn’t what the model sees inline, which is Session.MaxInlineToolResultChars. Output past the ceiling is discarded.
Tools.AudienceProfilesobject--Per-audience tool, file and MCP grants. Public, Team and Personal share one shape. A list you set replaces the default list and doesn’t merge with it.
Tools.AudienceProfiles.<audience>object--One entry each for Public, Team and Personal.
Tools.AudienceProfiles.<audience>.ToolsModestringAllowlist (Personal: All)Allowlist, AllAllowlist grants only the tools in AllowedTools. All grants every profile-managed tool.
Tools.AudienceProfiles.<audience>.AllowedToolsarray of stringPublic and Team defaults, see Built-in tools-Profile-managed tools this audience can call. Tools outside the profile-managed set are always available. Setting the key replaces the default list, and a value that isn’t a list stops startup.
Tools.AudienceProfiles.<audience>.McpServersModestringAllowlist (Personal: All)Allowlist, AllAllowlist exposes only the servers in AllowedMcpServers. All exposes every configured server.
Tools.AudienceProfiles.<audience>.AllowedMcpServersarray of string[]-MCP server names this audience can use when McpServersMode is Allowlist. MCP stays off for Public and Team until you add a server.
Tools.AudienceProfiles.<audience>.McpServerToolGrantsmap of array (nullable)unset-Per-server tool allowlists. A server listed here exposes only the named tools. A server not listed exposes all of its tools. Ignored when McpServersMode is All.
Tools.AudienceProfiles.<audience>.ReadFiles.ModestringRoots (Personal: All)None, Roots, AllNone blocks it, Roots limits it to Roots, All allows any path that isn’t protected. For the Personal audience, file_read, file_list, file_search and attach_file reach at least as far as WriteFiles does.
Tools.AudienceProfiles.<audience>.ReadFiles.Rootsarray of string["{session_dir}"]-Directories used when Mode is Roots. Tokens: {session_dir}, {skills_dir}, {identity_dir}, {workspaces_dir}.
Tools.AudienceProfiles.<audience>.WriteFiles.ModestringRoots (Personal: All)None, Roots, AllSame values as ReadFiles.Mode, for file_write and file_edit.
Tools.AudienceProfiles.<audience>.WriteFiles.Rootsarray of string["{session_dir}"]-Directories used when Mode is Roots. Same tokens as ReadFiles.Roots.
Tools.AudienceProfiles.<audience>.AttachFiles.ModestringRoots (Personal: All)None, Roots, AllSame values as ReadFiles.Mode, for attach_file.
Tools.AudienceProfiles.<audience>.AttachFiles.Rootsarray of string["{session_dir}"]-Directories used when Mode is Roots. Same tokens as ReadFiles.Roots.
Tools.AudienceProfiles.<audience>.ApprovalPolicyobjectunset (Personal posture: shell_execute is Approval)-Which tools need a human to approve each call. See How tool approvals work.
Tools.AudienceProfiles.<audience>.ApprovalPolicy.DefaultModestring"Auto"Auto, Approval, DenyMode for tools with no override.
Tools.AudienceProfiles.<audience>.ApprovalPolicy.ToolOverridesmap of string{}values: Auto, Approval, DenyMode per tool. Keys are tool names (shell_execute) or MCP tools as server/tool (or server__tool), matched without regard to case. If two keys differ only by case, the more restrictive mode wins. A key that contains : or has no value is ignored, so the tool keeps the audience default, and netclaw doctor reports it. Writes to the config directory are denied before any approval mode is read.
Tools.AudienceProfiles.<audience>.ApprovalPolicy.McpServerDefaultsmap of string{}values: Auto, Approval, DenyMode for every tool of one MCP server, keyed by server name and matched without regard to case. An exact ToolOverrides entry wins. A key that contains : is ignored and netclaw doctor reports it.
Tools.AudienceProfiles.<audience>.ChannelAttachmentsobject--Which files from chat messages this audience can send in.
Tools.AudienceProfiles.<audience>.ChannelAttachments.AllowedCategoriesarray of stringPublic: Image. Team: Image, Pdf, Document, Archive, Media. Personal: those plus Other.items: Image, Pdf, Document, Archive, Media, OtherAttachment categories accepted. An empty list rejects every attachment.
Tools.AudienceProfiles.<audience>.ChannelAttachments.MaxFileBytesinteger262144000 or moreLargest file accepted, in bytes (25 MiB). Must be above 0 when any category is allowed.
Tools.AudienceProfiles.<audience>.ChannelAttachments.MaxFilesPerMessageinteger100 or moreMost files accepted on one message. A message over the limit loses all its attachments. Must be above 0 when any category is allowed.
Tools.AudienceProfiles.GlobalReadRootsarray of string["{skills_dir}", "{identity_dir}", "{workspaces_dir}"]-Directories every audience can read, so skill loading, identity files and project discovery work under Team and Public. Setting the key replaces the list.
Tools.WebFetch.RequireHttpsbooleantrue-Reject plain http:// URLs in web_fetch unless the host is in HttpAllowList.
Tools.WebFetch.HttpAllowListarray of string["localhost", "127.0.0.1", "::1", "[::1]"]-Hosts that may use plain HTTP when RequireHttps is true. Setting the key replaces the list, so keep the loopback entries if you still need them.
Tools.HardDenyPatternsarray of string[]-Extra shell verb-chain prefixes that are always blocked and can’t be approved. They add to the built-in hard-deny list, they don’t replace it.

Where each model is served. Managed providers and self-hosted providers have one example per provider type.

KeyTypeDefaultAllowed valuesDescription
Providersmap of object{}-LLM provider connections keyed by a name you choose. Models.Definitions entries refer to these names.
Providers.<name>object--One provider connection. The name is yours to choose and Models.Definitions entries refer to it.
Providers.<name>.Typestring"ollama"-Provider type: anthropic, deepseek, github-copilot, ollama, openai, openai-compatible, openrouter or veniceai.
Providers.<name>.Endpointstring"" (the provider type supplies its own default URL)-Base URL of the provider API.
Providers.<name>.AuthMethodstring"None"None, ApiKey, OAuthDevice, OAuthPkceHow netclaw authenticates to the provider.
Providers.<name>.ApiKeystring (secret)unset-API key. Lives in secrets.json: netclaw secrets set Providers.<name>.ApiKey <key>.
Providers.<name>.OAuthAccessTokenstring (secret)unset-OAuth access token. netclaw writes it to secrets.json when you sign in with an OAuth auth method.
Providers.<name>.OAuthRefreshTokenstring (secret)unset-OAuth refresh token. netclaw writes it to secrets.json when you sign in with an OAuth auth method.
Providers.<name>.OAuthAccountIdstring (secret)unset-OAuth account identifier. netclaw writes it to secrets.json when you sign in with an OAuth auth method.
Providers.<name>.OAuthTokenExpirystring (secrets.json, unencrypted)unset-Expiry time of the OAuth access token, ISO 8601. netclaw writes it to secrets.json beside the tokens when you sign in with an OAuth auth method. It is the one value there that isn’t encrypted. A key left in netclaw.json is retired: netclaw doctor reports it and netclaw doctor --fix moves it, after a backup.
Providers.<name>.VendorOptionsobjectunset-Provider-specific non-secret options, for example GitHubHost and GitHubApiBase for github-copilot, ThinkingDialect for openai-compatible, DisableThinking for ollama, ExcludeReasoning for openrouter and IncludeVeniceSystemPrompt for veniceai. Each provider type defines its own keys.
Providers.<name>.VendorOptions.ThinkingDialectstringunsetChatTemplateKwargs, ReasoningEffort, DeepSeek, Noneopenai-compatible only. How netclaw sends a thinking level to the server. Without it only the output limit works. netclaw model set saves ReasoningEffort when it detects llama.cpp. Set it by hand for vLLM, SGLang or a proxy.

Which model plays Main, Fallback and Compaction, and each definition’s context window, modalities, output limit and thinking level. Model configuration has examples. The older inline shape (Models.Main, Models.Fallback, Models.Compaction as objects) still loads. Mixing it with Definitions and Roles stops startup.

KeyTypeDefaultAllowed valuesDescription
Models.Definitionsobject--Model definitions keyed by a name you choose, at least one. Names are case-insensitive and must be unique.
Models.Definitions.<name>object--One model: which provider serves it and how it behaves.
Models.Definitions.<name>.Providerstringrequired-Key into Providers.
Models.Definitions.<name>.ModelIdstringrequired-Model identifier sent to the provider.
Models.Definitions.<name>.ContextWindowintegerdetected-Context window in tokens. When set, it caps the value the provider reports.
Models.Definitions.<name>.Provenancestring (nullable)unset-Where the model data came from: Live, Defaults or Manual. netclaw sets it. You don’t need to.
Models.Definitions.<name>.InputModalitiesstringdetectedcomma-separated Text, Image, Audio, VideoManual override for what the model accepts, comma-separated from Text, Image, Audio, Video. Turns off automatic detection.
Models.Definitions.<name>.OutputModalitiesstringdetectedcomma-separated Text, Image, Audio, VideoManual override for what the model produces. Same format as InputModalities.
Models.Definitions.<name>.MaxOutputTokensintegerunset1 or moreOutput limit in tokens for every call of this model. Thinking tokens count inside it. Must be below ContextWindow when that is set. Unset sends 32000, clamped per call to the model maximum and to the context window minus the estimated prompt.
Models.Definitions.<name>.ThinkingstringunsetOff, Low, Medium, High, MaxProvider-neutral thinking level for every call of this model. Max is the highest level the provider offers. A level the provider dialect can’t send fails startup. Unset uses the model’s default.
Models.Rolesobject--Which definition plays each role. Values are names from Definitions.
Models.Roles.Mainstringrequired-Model for all interactions.
Models.Roles.Fallbackstring (nullable)unset-Failover model. Falls back to Main when unset.
Models.Roles.Compactionstring (nullable)unset-Cheaper or faster model for compaction. Falls back to Main when unset.

Cross-session memory, embeddings and recall. Memory and embeddings explains how the pieces fit together. The embedding model downloads on first start unless Embeddings.AutoDownload is false.

KeyTypeDefaultAllowed valuesDescription
Memory.Enabledbooleantrue-When false, the entire cross-session memory subsystem is disabled.
Memory.RecallTimeoutMsinteger30050 to 10000Automatic recall timeout budget in milliseconds.
Memory.AutoRecallMaxItemsinteger31 to 10Maximum number of memory items auto-injected per turn.
Memory.Embeddingsobject--Local ONNX embedding model for semantic memory.
Memory.Embeddings.Enabledbooleantrue-When true, the daemon provisions the embedding model, computes embeddings, uses semantic curation nomination and hybrid recall, and enables the relevance gate unless explicitly disabled.
Memory.Embeddings.ModelIdstring"snowflake-arctic-embed-m-int8"-Embedding model to use. Allowed ids are snowflake-arctic-embed-m-int8, snowflake-arctic-embed-m and mxbai-embed-large-v1. An id outside the allowlist is a configuration error. Changing it re-embeds existing memories under the new id.
Memory.Embeddings.AutoDownloadbooleantrue-When true, downloads the model artifact at daemon startup if not already provisioned. When false, a missing model degrades loudly instead of fetching over the network.
Memory.Curationobject--How new memories are checked against existing ones before they’re saved.
Memory.Curation.NominatorSimilarityThresholdnumber0.860 to 1Embedding cosine similarity threshold above which an existing memory is nominated for the curation call to adjudicate.
Memory.Curation.NominatorKinteger51 to 50Maximum number of nearest-neighbor nominees the kNN nominator shortlists per proposal.
Memory.Curation.LlmMaxOutputTokensinteger40961 or moreMaximum output tokens for the curation LLM call. Sized generously: the token cap is a defense-in-depth bound, not the primary control.
Memory.Curation.LlmTimeoutSecondsinteger601 to 300Wall-clock timeout in seconds for the curation LLM call.
Memory.Recallobject--How automatic recall ranks and filters memories, mixing keyword and vector scores.
Memory.Recall.VectorWeightnumber0.70 to 1Weight applied to a candidate’s cosine similarity in the hybrid fusion score.
Memory.Recall.LexicalWeightnumber0.30 to 1Weight applied to a candidate’s squashed lexical selector score in the hybrid fusion score.
Memory.Recall.MinCosineSimilaritynumber (nullable)unset (follows the model, 0.24 for the default)0 to 1Cosine floor for automatic recall. Candidates below it are dropped before ranking. The meaning is specific to the active embedding model, so recalibrate before you set it.
Memory.Recall.RecencyHalfLifeDaysnumber301 to 3650Half-life in days for the recency-decay multiplier applied to a candidate’s fused score in hybrid mode, floor-bounded at 0.85.
Memory.Recall.RelevanceGateobject--Post-floor cross-encoder relevance gate settings (memory-relevance-gate).
Memory.Recall.RelevanceGate.Enabledboolean (nullable)unset (follows Memory.Embeddings.Enabled)-Run the cross-encoder relevance gate on recall candidates. Set it explicitly to turn the gate on or off independently of embeddings.
Memory.Recall.RelevanceGate.Thresholdnumber (nullable)unset (model default, 0.02)0 to 1Score below which the gate drops a candidate. Unset uses the calibrated value for the provisioned relevance model.

Set Memory.Enabled to false and the memory tools and automatic recall disappear for every audience.

The web_search backend. Search providers covers Brave and SearXNG setup.

KeyTypeDefaultAllowed valuesDescription
Search.Enabledbooleantrue-When false, the web search subsystem is disabled.
Search.Backendstring"duckduckgo"duckduckgo, brave, searxngSearch backend identifier.
Search.BraveApiKeystring (nullable)unset-Brave Search API token. Required when Backend is brave. Lives in secrets.json: netclaw secrets set Search.BraveApiKey <token>.
Search.SearXngEndpointstring (nullable)unset-SearXNG instance base URL, for example http://searxng.local:8080. Required when Backend is searxng.

Switch for the skill index tools. Skills overview explains where skills come from.

KeyTypeDefaultAllowed valuesDescription
SkillSync.Enabledbooleantrue-When false, skill index tools are unavailable to the session.

Skill directories from other tools, such as Claude Code. External skills has the setup.

KeyTypeDefaultAllowed valuesDescription
ExternalSkills.Sourcesarray of object[]-Ordered list of external skill sources. Earlier entries win name collisions and native netclaw skills always win.
ExternalSkills.Sources[].Namestringrequired-Unique name for the source, for example claude-code.
ExternalSkills.Sources[].Pathstring (nullable)unset-Absolute path to the skill directory. Mutually exclusive with WellKnown.
ExternalSkills.Sources[].WellKnownstring (nullable)unsetclaude-code, open-codeWell-known source alias. Resolves to a standard path automatically.
ExternalSkills.Sources[].Enabledbooleantrue-Whether this source is active.
ExternalSkills.Sources[].AllowSymlinksbooleanfalse-Whether to follow symlinks in this directory. Resolved paths are still validated to stay within the source root.

Private skill servers that netclaw syncs from at startup and on a timer. Skill feeds has the setup.

KeyTypeDefaultAllowed valuesDescription
SkillFeeds.SyncIntervalMinutesinteger600 to 1440How often (in minutes) to re-check feeds for updated skills. 0 disables periodic sync.
SkillFeeds.Feedsarray of object[]-Ordered list of skill server feeds. Earlier feeds win name collisions.
SkillFeeds.Feeds[].Namestringrequiredpattern ^[a-z0-9-]+$Unique feed name, lowercase letters, digits and hyphens. Used as the directory name.
SkillFeeds.Feeds[].Urlstringrequired-Skill server base URL.
SkillFeeds.Feeds[].ApiKeystring (nullable)unset-Optional Bearer token for authenticated access. Supports ENC: prefix.
SkillFeeds.Feeds[].Enabledbooleantrue-Whether this feed is active.
SkillFeeds.Feeds[].TimeoutSecondsinteger301 to 300HTTP timeout in seconds for requests to this feed.

Switches and watchdogs for spawn_agent. Custom subagents shows how to define agents.

KeyTypeDefaultAllowed valuesDescription
SubAgents.Enabledbooleantrue-When false, the subagent subsystem is disabled.
SubAgents.PrefillTimeoutSecondsinteger18005 to 3600Longest wait for a subagent’s first streamed token, which covers queue wait and prompt prefill. Same idea as Session.PrefillTimeoutSeconds. After the first token the Session.FirstTokenTimeoutSeconds budget applies. An agent definition can override it with prefillTimeoutSeconds in its frontmatter.
SubAgents.NoProgressTimeoutSecondsinteger120060 to 7200Hard ceiling on a subagent run with no real output token. Keepalives don’t reset it. Like Session.NoProgressTimeoutSeconds, it also sets the thinking cap at three times the value.

Where operational alerts go. Operational alerts lists the alert types.

KeyTypeDefaultAllowed valuesDescription
Notifications.Webhooksarray of object[]-Targets that receive operational alerts by HTTP POST. Empty means alerts only go to the log.
Notifications.Webhooks[].Urlstringrequired-HTTP or HTTPS endpoint to POST alerts to.
Notifications.Webhooks[].Namestring (nullable)unset-Display name used in logs.
Notifications.Webhooks[].Headersmap of string (nullable)unset-Static headers sent with every POST, for example Authorization.
Notifications.Webhooks[].Formatstring"Generic"Generic, SlackPayload format: Generic is a JSON envelope, Slack is Slack Block Kit.
Notifications.DeduplicationWindowSecondsinteger3000 to 3600Minimum interval in seconds between duplicate alerts of the same type.
Notifications.MaxRetriesinteger20 to 10Number of delivery retries per webhook target before giving up.
Notifications.TimeoutSecondsinteger101 to 60HTTP timeout in seconds for each webhook POST attempt.

The inbound webhook endpoint. The routes themselves aren’t in netclaw.json: each one is a file under config/webhooks/, managed with netclaw webhooks or the webhook tools. Webhooks covers routes and verification.

KeyTypeDefaultAllowed valuesDescription
Webhooks.Enabledbooleanfalse-Register the inbound webhook endpoint and the set_webhook, list_webhooks and delete_webhook tools.
Webhooks.ExecutionTimeoutSecondsinteger3001 to 3600Longest a webhook-triggered run can take before the daemon marks it failed.

Switch for reminders and scheduled tasks. Reminders covers creating and running them.

KeyTypeDefaultAllowed valuesDescription
Scheduling.Enabledbooleantrue-When false, the scheduling subsystem is disabled. Reminder and scheduling tools are not registered.

Set Scheduling.Enabled to false and the five reminder tools aren’t registered.

How long the daemon keeps log files before a scheduled clean-up deletes them. Data retention explains what is and isn’t deleted.

KeyTypeDefaultAllowed valuesDescription
Retention.Logs.Daysinteger140 to 36500Days to keep daemon-yyyy-MM-dd.log, its numbered segments daemon-yyyy-MM-dd.N.log (the daemon starts a new segment at 10 MiB) and crash-*.log files in the logs directory. The daemon deletes older files 30 seconds after it starts and every 12 hours after that. The newest 3 daemon logs, segments counted as files, and the newest 3 crash logs are always kept. 0 keeps them forever. Per-session logs are never touched. See Data retention.

Bind address, port and how the daemon is exposed to the network. Changing any of these in netclaw.json restarts the daemon. Exposure modes explains each mode and Docker covers the container settings.

KeyTypeDefaultAllowed valuesDescription
Daemon.Hoststring"127.0.0.1"-IP address the daemon binds to. Defaults to loopback (127.0.0.1).
Daemon.Portinteger51991 to 65535TCP port the daemon listens on. Defaults to 5199.
Daemon.ExposureModestring"local"local, reverse-proxy, tailscale-serve, tailscale-funnel, cloudflare-tunnelTunnel infrastructure in front of the daemon. Defaults to local (loopback only, no tunnel).
Daemon.TrustedProxiesarray of string[]-Explicitly trusted reverse-proxy source IPs or CIDR ranges. Required for reverse-proxy mode.
Daemon.SkipTunnelProcessCheckbooleanfalse-When true, skips the local tunnel-process prerequisite check for tunnel-backed exposure modes. Use only for sidecar or host-managed tunnel topologies.
Daemon.DisableSelfUpdatebooleanfalse-When true, in-place binary self-update via ‘netclaw update’ is blocked. Update availability checks still run. Intended for container deployments where the image tag is the version.
Daemon.UpdateChannelstring"stable"stable, betaRelease channel the update check follows. stable only sees stable releases. beta also sees prereleases and moves to a stable release once one supersedes the beta.

The Docker image’s health check probes port 5199. A container with a different Daemon.Port reports unhealthy even though the daemon is up, so override the health check when you change the port.

In Local exposure mode the daemon answers 401 to a request whose Host isn’t localhost or a loopback IP literal (127.0.0.1, [::1]), or whose Origin, when present, isn’t http:// plus the same host. A client that reaches the daemon by another host name, or a browser app on another port, is refused. Daemon.Host as a bind value still accepts spellings such as 127.1.

Where netclaw looks for your project repositories. Context structure explains how projects feed the prompt.

KeyTypeDefaultAllowed valuesDescription
Workspaces.Directorystring~/.netclaw/workspaces-Root for project workspaces. Projects are Git repositories with an AGENTS.md, at any depth. A leading ~ expands to your home directory.

MCP server profiles keyed by name. Add them with netclaw mcp add or edit the file. MCP servers has the walkthrough and MCP tool permissions covers per-audience access.

KeyTypeDefaultAllowed valuesDescription
McpServers.<server>object--MCP server profiles keyed by name.
McpServers.<server>.Transportstring"stdio"stdio, sse, httpHow netclaw connects: stdio runs Command, sse and http connect to Url.
McpServers.<server>.Commandstring (nullable)unset-Executable to run for stdio.
McpServers.<server>.Argumentsarray of string (nullable)unset-Arguments for Command.
McpServers.<server>.Urlstring (nullable)unset-Endpoint for sse and http.
McpServers.<server>.EnvironmentVariablesmap of string (nullable)unset-Environment variables passed to the stdio process. Values stored in secrets.json are decrypted first.
McpServers.<server>.Headersmap of string (nullable)unset-HTTP headers for sse and http. Values stored in secrets.json are decrypted first.
McpServers.<server>.Enabledbooleantrue-Disabled servers are skipped at startup.
McpServers.<server>.GrantCategorystring (nullable)mcp:<server>-Tool metadata category for the server’s tools. Authorization doesn’t read it: use the audience’s AllowedMcpServers and McpServerToolGrants.
McpServers.<server>.OAuthClientIdstring (nullable)unset-Static OAuth client ID for servers without dynamic client registration.
McpServers.<server>.OAuthClientSecretstring (secret)unset-Client secret for a pre-registered confidential OAuth client. Vault only: the schema rejects it in netclaw.json, so doctor fails the Config Schema check. Set it with netclaw mcp add --client-id <id> --client-secret <secret> or netclaw secrets set, which store it in secrets.json. Needs OAuthClientId.
McpServers.<server>.OAuthScopestring (nullable)unset-Space-separated OAuth scopes to request, overriding the server’s defaults.

These keys no longer do anything. netclaw doctor reports each one as a disallowed property.

KeyRemoved inWhat to do
Persistence (the whole section)0.27.0Delete it. netclaw always uses its single SQLite database, and the daemon refuses to start while the section exists.
SkillSync.DisableSystemSkillSync0.27.0Delete it, or run netclaw doctor --fix. System skills now ship inside the binary and restore on every start.
Providers.<name>.OAuthTokenExpiry in netclaw.json0.28.0Run netclaw doctor --fix, which moves it to secrets.json after saving netclaw.json.retired-oauth-expiry.bak. Until then it still binds and logs a startup warning.
timeoutSeconds in a subagent definition0.28.0Delete it. The file still loads and the daemon logs a warning each time it reloads, but the key is ignored. Subagent runs use Session.FirstTokenTimeoutSeconds, 600 seconds by default, so a profile that used 60 to 180 seconds now waits longer.
Session.MaxToolIterationsPerTurn0.28.0Still valid and still validated, but no longer limits a turn.
Tools.ShellTimeoutSeconds0.24.0Delete it. A foreground shell call is bound by Session.ToolExecutionTimeoutSeconds, and a background job by the _timeout_seconds the model passes.