Config File Reference

Every configuration option, organized by section.

When a change takes effect

Every setting the dashboard offers applies to the running node immediately (so does the same setting edited in this file, followed by POST /api/admin/config/reload). You do not need to restart for a resource limit, a contribution level, an auto-manage threshold, or a batching setting to matter.

A setting that exists only in this file applies without a restart where its row below says so; otherwise restart the node after changing it — several are read once, when something is built at startup (a listener, a rate limiter, the network).

Two of the dashboard's settings are also decided once, when the node starts, and keep their startup value until it starts again:

SettingWhy
[network] max_peers (and the contribution level it derives from)Connection limits are fixed when the peer-to-peer network is built
[resources] max_cpu_threads for an already-loaded modelThreads are handed to a model's worker when it loads; taking them back would interrupt whatever it is answering. The next model to load uses the new value

Before v0.3.88 none of the dashboard's settings were live: a setting would save, report success, show its new value, and leave the running node on the value it booted with.

[node] — Basic Node Settings

OptionTypeDefaultDescription
listen_portinteger8800Port for web dashboard and P2P networking
data_dirpathPlatform-specificWhere SwarmLLM stores data
contributionstring"minimal"Resource contribution: "minimal", "moderate", "maximum". Applies without a restart, except for the two startup-fixed items noted above
contribution_autobooleantrueWhen a shard is already held by many other computers, let this node delete its copy sooner to free space. It never raises your contribution level. Applies without a restart
anchor_modebooleanfalseRun as a pure bootstrap / relay / reachability-probe node. Skips all inference — no models load, no HuggingFace polling, no shard acquisition, no auto-manage — and binds the dashboard to loopback only. The node still participates fully in the peer-to-peer network

[resources] — Resource Limits

OptionTypeDefaultDescription
max_gpu_vram_mbinteger0Max GPU memory in MB. 0 = auto: the card's size, minus what other programs are using, minus a safety margin set by [node] contribution (10% of the card at minimal, 7% at moderate, 5% at maximum, never under 512 MB or over 2 GB) — on an idle 8000 MB card at the default level, 7200 MB
max_ram_mbinteger0Max system RAM in MB for models loaded on the CPU. 0 = auto, set by [node] contribution: at the default (minimal) about 31% of system RAM on a machine whose graphics card runs the models and 50% on a CPU-only node; moderate about 41% / 65%; maximum 50% / 80% (where serving models is the machine's purpose). An explicitly configured value is clamped to what is actually free, so a figure larger than the machine cannot push it into swap. A model that does not fit is refused with a 503 rather than loaded
max_disk_mbinteger50000Max disk space in MB for model storage
max_bandwidth_mbpsinteger0Max upload bandwidth for serving model files to peers, and nothing else. Inference traffic and the background gossip that keeps this node connected are outside it, so this is not a cap on everything the node sends — a user who found it at 1 Mbps and then measured 11 was seeing traffic it never covered. 0 = auto, from [node] contribution — 10 Mbps at minimal, 50 at moderate, unlimited at maximum (the Settings slider calls it Automatic). 1 is read as 0: up to 0.3.230, choosing "Unlimited" in Settings stored 1 by mistake, so the smallest cap is 2. To see what the node is actually sending, run swarmllm status or read the Network tile on the dashboard
max_cpu_threadsinteger0CPU threads used for inference. 0 = auto, from [node] contribution — half / three-quarters / all of the physical cores. More threads than physical cores makes this slower: quantised inference is limited by memory bandwidth, so two threads sharing a core contend rather than add (measured on an 8-core/16-thread laptop: 6 threads 2.36 tok/s, 16 threads 1.49). An explicit value is honoured up to the logical core count.

[resources.schedule] — Usage Schedule

OptionTypeDefaultDescription
enabledbooleanfalseEnable scheduled resource reduction
reduced_hours_startinteger22Hour (0-23) to start reduced mode
reduced_hours_endinteger8Hour (0-23) to end reduced mode
reduced_contributionstring"minimal"Contribution level during reduced hours
prune_aggressivenessstring"normal"Shard pruning during reduced hours: "normal", "aggressive", "conservative"

[network] — Networking

OptionTypeDefaultDescription
bootstrap_peerslistbuilt-in anchorPeer addresses to dial on startup. An empty list means "not configured" and falls back to the built-in anchors
disable_default_bootstrapbooleanfalseGenuinely start with no bootstrap peers (private / air-gapped swarm). Implied by node.anchor_mode
enable_mdnsbooleantrueLAN peer discovery
gossip_network_idstringnonePut a group of nodes on their own announcement topics and their own gossip key, so they discover each other's models separately from the public swarm. Not an isolation boundary on its own — which nodes hold which shards is also learned through the shared DHT, so a node can still route work outside the group. To keep work in, use a pool with private_mode and private_mode_allow_lan = false. Leave unset to join the public network
peer_exchangebooleantrueShare peer lists with connected nodes
enable_relaybooleantrueAct as relay for peers behind firewalls
enable_relay_clientbooleantrueLet THIS node route its own traffic through someone else's relay when it is not directly reachable. Turning it off leaves the node able to reach others but generally unreachable from the internet. The opposite role — relaying for others — is enable_relay
max_peersinteger(from contribution)Max simultaneous peer connections. Unset it follows [node] contribution — minimal 150, moderate 300, maximum 500. An explicit value wins in either direction.
auto_relaybooleantrueAuto-use relay when NAT detected
relay_max_circuit_duration_secsinteger3600Max relay circuit duration
relay_max_circuitsinteger128Max relay circuits to serve
enable_encryptionbooleantrueEncrypt tensor forwards and control messages between computers. Protects against anyone watching the network; the receiving computer decrypts in order to do the work, so this is not end-to-end
enable_autonatbooleantrueNAT detection. Disable on WSL2 to reduce noise
enable_dcutrbooleantrueHole punching. Disable on WSL2 to reduce noise
tensor_compressionbooleantrueZstd compression for tensor payloads
prefix_kv_compressionbooleanfalseZstd compression for cross-node prefix-KV snapshot wire frames. Default off — meaningful win on WAN where wire size is the bottleneck; roughly neutral on localhost. Receivers always decompress regardless of this flag.
tensor_compress_levelinteger1Zstd compression level (1-22, 1 = fastest). Shared between tensor and prefix-KV.
tensor_compress_thresholdinteger1024Min payload bytes before compression. Shared between tensor and prefix-KV.
listen_addressstring"0.0.0.0"Address to bind peer-to-peer listeners on. Set to 127.0.0.1 on WSL2 to avoid binding unreliable NAT adapters
enable_quicbooleantrueQUIC transport. Disabling it on WSL2 avoids a race where the faster QUIC handshake displaces the TCP connection
enable_upnpbooleantrueAsk the home router to open the peer-to-peer ports automatically, and confirm the resulting public address with the swarm. The zero-configuration path to being reachable from the internet
external_addresseslist[]Addresses this node is reachable at from the internet, for a port-forwarded computer, a server or a dynamic-DNS name — IP or DNS multiaddrs without /p2p/<id> (the node appends its own), e.g. ["/dns4/node.example.net/tcp/8810", "/dns4/node.example.net/udp/8800/quic-v1"]. Advertised to peers and put in invite codes. Empty leaves it to UPnP, AutoNAT and the relay. external_address is accepted too
max_connections_per_peerinteger3Simultaneous connections to a single peer. Must be at least 2 for NAT hole punching: the upgrade dials a direct connection while the relayed one is still open, so 1 kills one of them
relay_forwardingbooleanfalseCarry inference messages between two peers that cannot reach each other. Distinct from enable_relay, which carries the connection itself
relay_forwarding_autobooleantrueDonate that relay capacity automatically once this node is confirmed reachable from the open internet

[inference] — AI Model Inference

OptionTypeDefaultDescription
default_modelstring""The model a request for "auto" gets. Empty = the model auto answered with last time (so a conversation stays on one model), else one this node holds whole, else one the swarm can serve; ties go alphabetically. Applies from v0.3.209 — earlier releases ignored it
session_timeout_secondsinteger600Chat session memory lifetime (10 min)
max_concurrent_requestsinteger10Request concurrency budget: half of it (5 by default) of this node's own requests run at once, the rest queue
model_pathpathnonePath to a GGUF model file
gpu_layersinteger-1Device placement. -1 = auto: the whole model on the card when it fits, and when it does not, as many of its first layers as do with the rest on the processor (since v0.3.145; SWARMLLM_HYBRID_OFFLOAD=0 turns the split off and falls back to processor-only). 0 = processor only. >0 = for a whole model file given with --model / model_path (run by llama.cpp), put that many layers on the card and the rest on the processor; for a model loaded from its parts, any positive value means the same as -1 (only 0 is special there). Architectures allowed to split (code-checked): Llama, Llama 4, Qwen2, Gemma, Gemma 2, Gemma 3, Gemma 4 (the 26B-A4B mixture of experts too; the E2B and E4B split between the card and the processor of one computer, never between computers), Qwen 3.5 (dense and mixture of experts), Phi-3, Mistral, Starcoder2 (listed, but the family itself is refused — FUTURE_WORK #118), GLM-4 — Llama 4 is allowed but has not been run on a real model; others load on one device as before
kv_cache_ttl_secsinteger600KV-cache lifetime
max_batch_sizeinteger8How many requests run through the model together, amortising the weight reads that dominate a decode step. Measured on an RTX 3070 with llama-3.2-3b using per-request rates: no cost at any concurrency, about 3% at eight concurrent requests and about 16% at twelve — the gain grows with load. Neutral on a processor (6-core i5-10500T, llama-3.2-1b). Set to 1 to disable
batch_timeout_msinteger50Ms to wait for additional requests before dispatching a partial batch. 0 = dispatch immediately (purely opportunistic batching)
speculative_decodingbooleantrueEnable speculative decoding (on its own it enables only decentralized_spec_decoding's path; the llama.cpp paths also need draft_model_path)
speculative_gammainteger4Draft tokens per verification step; values above 16 are treated as 16, the most another computer accepts in one check with room to spare. With a model split across computers this is only the starting point — the count is then chosen each round from what checks and guesses actually cost
draft_model_pathpathnonePath to draft model
draft_modelstringnoneA model this node holds (its id) to guess ahead with when a request is split across computers (decentralized_spec_decoding), run from its own parts in SwarmLLM's engine. Unset: the largest held model that shares the target's vocabulary and is at most a quarter of its size (a mixture-of-experts model's size counts all its experts); of copies of one model at different precisions, the one that reads the fewest bytes a guess
max_split_model_memory_mbintegernoneMax GPU memory for split model cache
tensor_parallelbooleanfalseSplit single layers across LAN peers via per-layer AllReduce. Off by default — over Ethernet the two round trips per layer cost more than the compute they split, and a node that holds every layer never forms a group regardless
tp_max_latency_msinteger5Max physical round trip (ms) to a peer for tensor parallelism groups (only consulted when tensor_parallel = true)
local_embedding_privacybooleanfalseEmbed tokens locally before sending to first segment. Remote nodes never see raw token IDs. They still receive hidden states, which published attacks can turn back into much of the text
encrypted_pipelinebooleanfalse"Start and finish on this computer" (the "boomerang"): run the first and last steps on this computer, so no other computer is handed the prompt as text or picks the reply's words. Structural, not cryptographic — middle computers still compute on hidden states in plaintext, which published attacks invert to roughly 81% of the input. Adds ~1 RTT/token. Per-model override via API. Requires shard 0 + final shard locally; see encrypted_pipeline_auto
privacy_modebooleanfalseNever write user prompts to disk — KV-cache sessions stay in memory only
parallax_routingbooleantrueUse Parallax shortest-path DP for segment assignment; falls back to greedy on any failure
persistent_pipeline_streambooleanfalseOne long-lived libp2p stream per request and peer for a split, instead of a request/response per token — 2.4x faster on a long link (2026-09-27), off until a stalled-read case is explained
max_seq_len_overrideintegernoneContext length this node serves per conversation. Unset = the model's declared length, capped at 8192; a number replaces that cap — raise it (e.g. 32768) for agents with long prompts, or lower it so a long-context model fits a small card. Raising it no longer costs a model its place on a node: admission on both CPU and GPU charges KV cache for a typical 4096-token conversation, and a worker refuses a conversation that would outgrow its memory budget at run time (a 503 that re-routes to a peer) rather than swapping. A model without grouped-query attention such as phi-3.5-mini still costs 0.75 MB per token of KV cache, so how long a conversation a CPU node can hold is set by its free RAM (resources.max_ram_mb), and the node's log says how many tokens fit when the model loads.
draft_gpu_layersintegernoneDevice placement for the draft model. Unset = inherit gpu_layers
force_standard_attnbooleanfalseRoute every attention call through standard_attention instead of the fused kernel. Diagnostic; auto-enabled while SWIFT is on
shard_rangetuplenoneAdvanced/dev: claim only this shard index range for split inference. Normal nodes auto-detect their local shards

[inference] — batching

OptionTypeDefaultDescription
continuous_batchingbooleantrueCoalesce concurrent decode requests for the same model into one fused worker forward. 1.34–1.55× on GPU at batch 2–8; neutral-to-loss on CPU, where the worker falls back to sequential
max_concurrent_decode_batchinteger8Maximum decode slots fused into one batch
batch_collection_msinteger5How long the scheduler waits for more arrivals after the first request lands in an empty batch. WSL2 timer resolution is ~15 ms, so smaller values dispatch immediately there
prefill_chunk_tokensinteger128Sarathi-style chunked prefill size. Each Prefilling slot advances by this many prompt tokens per decode tick, bounding how long one admission can stall active decodes
batched_prefill_forwardbooleantrueFuse concurrent same-shape prefill chunks into one forward. Set false to isolate this from continuous batching in A/B benchmarks

[inference] — prefix cache

OptionTypeDefaultDescription
prefix_cache_enabledbooleantrueReuse prefill KV across requests sharing a prompt prefix — covers both multi-turn and the same system prompt from different users
prefix_cache_max_entriesinteger16Cached prefix snapshots retained per model
prefix_cache_max_mbinteger2048Max megabytes of prefix KV retained per model, 0 for no byte bound. This is the bound that expresses memory: prefix_cache_max_entries caps how many entries are kept, which says nothing about their weight, since an entry scales with its prompt. One snapshot is sized to fit it — a longer prompt keeps its opening — so this bounds both one entry and the model's total
prefix_cache_max_prompt_tokensinteger0Most tokens of one prompt kept; a longer prompt keeps its opening. 0 = no token ceiling, prefix_cache_max_mb decides
prefix_cache_block_tokensinteger64Block alignment for the chained-hash manifest, and the granularity of a partial hit
prefix_cache_min_tokensinteger32Shortest prefix worth caching
cross_node_prefix_trust_minfloat0.5Minimum peer trust score before accepting a prefix-KV snapshot fetched from that peer. 0.0-1.0; a value outside that range stops the node starting
share_prefix_cache_with_peersboolfalseOffer this node's prompt prefix cache to other nodes. Off by default: turning it on announces hashes of the prompts this node caches to the whole swarm, and serves those prompts' token IDs and key/value cache to any peer that asks. Your own local prefix cache works either way

[inference] — speculative decoding

OptionTypeDefaultDescription
speculative_distributedbooleanfalseSpeculative decoding on the distributed path. Needs speculative_decoding + a loaded draft model
decentralized_spec_decodingbooleantrueDSD: guess ahead when a request is split across computers. Engages only where this node holds a small model sharing the target's vocabulary, and stops guessing where it does not pay
swift_self_speculativebooleanfalseSWIFT (arXiv 2410.06916) — draft by skipping layers of the target model, so no separate draft model is needed
swift_calibration_tokensinteger32Warm-up tokens before SWIFT's calibrator pins a skip pattern
swift_gammainteger4Draft tokens proposed per SWIFT verification round
swift_skip_ratiofloat0.45Fraction of layers skipped in the SWIFT draft pass
ngram_lookup_enabledbooleantrueSWARM-SPEC Layer 1: draft from n-grams already present in the prompt, no draft model required. Large win on input-grounded workloads (RAG, coding, summarisation) — measured +45% at a 77% hit rate
ngram_max_sizeinteger4Longest n-gram matched against the prompt
ngram_num_pred_tokensinteger10Tokens proposed per n-gram hit

[inference] — SWARM-SPEC prefetch

OptionTypeDefaultDescription
prefetch_enabledbooleanfalseLayer 3: predict the next turn in a conversation and warm state during idle time
prefetch_min_turns_for_predictioninteger2Turns observed before a session is predictable enough to prefetch for
prefetch_min_idle_msinteger2000Idle time before prefetch may use the device
prefetch_max_candidatesinteger3Candidate continuations considered per prediction

[inference] — activation transfer

OptionTypeDefaultDescription
activation_compressionbooleantrueQuantise intermediate hidden states to Q8_0 before sending to the next peer (~3.76× smaller, group-32 + f16 scale). Receivers auto-dispatch on the dtype tag, so this is safe to toggle per node
streaming_chunked_sendbooleanfalseSplit a segment-boundary activation into K chunks sent on one stream, overlapping encrypt with transfer. Off by default: on LAN the send is already sub-millisecond and per-chunk cost dominates. The win is WAN-only (roughly <30 Mbps). Requires persistent_pipeline_stream
streaming_chunk_size_bytesinteger262144Chunk size for the above. 256 KiB matches the age STREAM default and the TokenWeave K=2–4 sweet spot
streaming_min_activation_bytesinteger65536Activations below this ship as a single frame regardless of the flag
streaming_chunk_assembly_ttl_secsinteger30Receiver-side TTL for an incomplete chunk assembly before it is swept
prefill_target_msinteger200Wall-time budget for one tick of prompt processing while more than one request is active — the same limit as prefill_chunk_tokens but expressed in what a waiting request actually feels
encrypted_pipeline_autobooleantrueTurn "Start and finish on this computer" on automatically for any model where this node holds both the first and last shard, which is the only condition under which it can work. An explicit per-model or global encrypted_pipeline setting always wins
parallax_partial_rangesbooleanfalseLet the router use only PART of a node's shard range, so a node holding a whole model can serve just one end of it. Off by default: the cost model charges a remote hop once per segment rather than per token, so it cannot see the round-trip penalty and over-splits
pipeline_chainingbooleantrueChain consecutive remote pipeline segments peer to peer instead of returning every hop to the coordinator. Unchained, an N-segment pipeline costs N coordinator round trips per token; a chained run costs one trip out and one back however long it is, so per-token network cost stops scaling with shard count. A local segment ends a chain, so "Start and finish on this computer" is unaffected — with encrypted_pipeline the first and last segments stay local and only the middle is chained. On by default since v0.3.109, validated end to end on two machines; every reason not to chain falls back to the old behaviour rather than failing, a chained run that fails is re-run unchained for that request, and peers on earlier versions are never chained to. Set to false to send every segment through the coordinator as before. See docs/plans/direct_peer_chaining.md
max_chain_hopsinteger8Longest run of peer-to-peer hops in one chain. Bounds how much of a request rides on nobody checking in: the coordinator hears nothing between handing a chain over and its tail reporting back, so a longer chain means a slower failure
shed_load_when_busybooleanfalseLet a busy node hand a request it could serve locally to the router, so a peer can take it. A node holding a complete model otherwise serves it locally without consulting the router at all: measured 2026-08-20, eight concurrent requests all stayed on one GPU (36 → 7.5 tok/s per request) while a peer advertising 20 tok/s sat idle. Off by default because the benefit is unproven — aggregate throughput kept RISING with concurrency on that GPU, so degrading per-request is not the same as needing to stop taking work
shed_load_thresholdinteger4How many requests must already be in flight before shed_load_when_busy offers one to the router. One in flight is not busy: the second request shares a GPU that is mostly idle between token launches, which is what batching exploits

[logging] — Log Output

OptionTypeDefaultDescription
levelstring"info"Log level: "error", "warn", "info", "debug", "trace"
formatstring"pretty"Log format: "pretty" or "json". Not applied yet — logs always go to the console in the readable format
filepathlogs/swarmllm.logThe log is written here as well as to the window. A relative path is under the data directory; "off" keeps it to the window only. The file starts over at 50 MB, keeping three older ones (.1 the newest). --log-file <path> overrides it for one run

[ui] — Web Interface

OptionTypeDefaultDescription
open_browser_on_startbooleantrueOpen dashboard on launch — not when an update restarted the node, and not beside a dashboard that was already open and reconnects

[api] — API Authentication

OptionTypeDefaultDescription
api_keystringnoneBearer token. Empty = auto-generated
rate_limit_rpminteger60Rate limit for /v1/ endpoints (requests/min)
rate_limit_admin_rpminteger200Rate limit for /api/admin/ endpoints (requests/min)
metrics_auth_requiredbooleanfalseRequire Bearer auth on /metrics even from loopback. Read at startup — restart after changing it
dashboard_trust_overlaybooleantrueHand the dashboard its access key over a Tailscale-style overlay, when this node is on one too. Read at startup — restart after changing it
dashboard_trust_lanbooleanfalseHand the dashboard its access key to any private/LAN address

The dashboard fetches its own access key on page load. These two options decide which networks that happens on — loopback always does, and anywhere else the page asks you to paste the key once instead of failing silently.

dashboard_trust_overlay only takes effect when this node itself holds an overlay address. The IPv4 range Tailscale uses (100.64.0.0/10) is shared carrier-grade NAT space that some ISPs also hand out, so a peer's address alone does not prove a tailnet.

dashboard_trust_lan exists for the case where you reach a node through a Tailscale subnet router or a container publish. Those rewrite the source address by default, so the request arrives from the router's private address and is indistinguishable from any other LAN client. It can be toggled from Settings → Identity & Access and applies immediately, without restarting the node.

On a network this node trusts, anything that can reach the API port can obtain the access key, and with it admin and inference. That is the intended bargain for a tailnet — devices you authorised — which is why the LAN case stays opt-in. See Tailscale / WAN.

[model] — Model Storage

OptionTypeDefaultDescription
shard_size_mbinteger512Shard size in MB. Range: 64-2048

[auto_manage] — Automatic Shard Management

OptionTypeDefaultDescription
enabledbooleantrueAuto-download popular shards (only for models at DemandVerified+ or Pinned trust level)
max_storage_mbinteger0Cap on shard storage held. 0 = a share of max_disk_mb by contribution level (25% minimal / 50% moderate / 75% maximum); a set value is honoured as written, up to max_disk_mb (1 is read as 0: up to 0.3.230 the settings API stored 1 for 0). Either way the node never takes the last 10% of the filesystem it is on (since v0.3.228)
interval_minutesinteger5Check interval for new shards
interval_secondsintegernoneTesting override for interval_minutes. Takes precedence when set
model_policiestable{}Per-model overrides keyed by model id, e.g. [auto_manage.model_policies."llama-3.1-8b"], each with enabled (default true: auto-manage may download its parts), max_shards (default 0: no per-model limit) and prune_enabled (default true: auto-manage may delete extra copies)
max_shardsinteger0Max shards. 0 = unlimited
max_concurrent_downloadsinteger3Max parallel downloads
prune_enabledbooleantrueAuto-remove over-replicated shards. Since v0.3.241 a model this computer holds whole keeps every part unless the storage set aside for models is 95% full, a part fetched in the last 30 minutes is not removed while that storage is under 80% full, and parts are trimmed against the highest copy count the swarm wanted in the last 24 hours, so a short dip in demand does not delete parts that are then downloaded again
min_replicasinteger2Min network replicas before pruning
prune_cooldown_secsinteger300Seconds between prune actions per model
max_holder_load_for_pruneinteger3Block pruning if holders are busy
hf_watcher_enabledbooleantrueBackground poll of HF trending GGUF feed (hourly). Disable for air-gapped / bandwidth-constrained nodes
wishlist_gossip_publishbooleanfalseOpt-in: publish your wishlist as cross-pool demand gossip (R130)
auto_switch_quantsbooleantrueR141 default flip: auto-acquire the recommended quant variant when the recommender (R133) suggests a better one. Set false on metered links to keep the current quant
on_metered_connectionstring"auto"What this node holds back on a metered connection (a phone's hotspot, a mobile plan): downloads it would start on its own, and new work and model parts for other computers. "auto" pauses while the system says the connection is metered (NetworkManager on Linux, the connection's cost on Windows and under WSL2; nothing on macOS yet), "pause" always pauses, "allow" never does. Downloads you ask for, the repair of parts already held, your own requests and work already running for another computer are never paused
parallax_auto_rebalancebooleantrueBias scoring toward Parallax allocator recommendations (C.2)
default_model_shard_capinteger0Max shards auto-manage acquires per model. 0 = unlimited. Set this if you want to add capacity rather than redundancy — see below
idle_unload_secsinteger300Free a loaded model's GPU memory after this long with no local requests AND little demand for it elsewhere in the network. Shards stay on disk, so the model reloads on the next request

Contributing capacity vs. contributing redundancy

default_model_shard_cap = 0 (the default) lets auto-manage take every shard of a model it decides to host. With min_replicas = 2 and a small number of participants, the usual outcome is that every node ends up holding every model in full — measured on a two-node setup as ~20 GB and ~18 GB of near-identical content.

That is the right default: it maximises availability, and a model nobody holds completely cannot be served at all.

It is not always what an operator wants. Holding a full copy of a model your neighbour already holds adds a spare, not throughput. If you are joining to add capacity — more machines able to serve different parts of more models — set a cap:

[auto_manage]
default_model_shard_cap = 2   # at most 2 shards of any one model

Rough guidance:

GoalSettingEffect
Survive nodes going offline0 (default)Full copies everywhere; any node can serve alone
Host more distinct models on limited disksmall cap (1-3)Partial coverage, requests span several nodes
Dedicated always-on node0Be the copy others fall back to

A cap only limits what auto-manage acquires on its own. Shards you download explicitly, and shards pinned to this node by a pool owner, are unaffected.

One caveat worth knowing before you tune this: holding fewer shards spreads storage, not necessarily load. A node that holds a model in full still serves requests for it locally rather than sharing them out, so capping shards is about what gets stored where, not about how work is distributed.

[pool] — Device Pool

OptionTypeDefaultDescription
max_pool_sizeinteger10Max devices in a pool
invitation_ttl_hoursinteger24Invitation validity period
rate_limit_per_hourinteger10Max pool operations per hour
gossip_interval_secsinteger600Pool state gossip interval
private_modeboolfalseRestrict inference to pool members only. Toggleable at runtime via API/UI
private_mode_allow_lanbooltrueAlso allow LAN peers (mDNS-discovered) when private mode is on
offline_modeboolfalseAir-gapped: no bootstrap peers, no HF downloads, mDNS-only discovery
state_diff_gossipbooleanfalseSend pool membership changes as signed differences between full broadcasts, instead of always resending the whole member list
share_model_catalogbooleanfalseLet the pool owner advertise which models the pool can serve, so other pools can discover it
share_model_catalog_min_membersinteger3Anonymity floor for the above: a pool smaller than this never publishes its catalog, whatever the flag says
allow_cross_pool_inferencebooleanfalseWith private_mode also on, allow routing to another pool's members for a model that pool has advertised. Off means private mode stays strictly within your own devices

[pool.credit_rates] — Credit Rates

Credits are recorded but dormant — they gate nothing: no balance affects who is served or how fast, and there is no token or payment. These rates only change numbers in the internal ledger.

OptionTypeDefaultDescription
inference_serveinteger10Credits earned per token served
inference_consumeinteger10Credits spent per token consumed
shard_hostinginteger1Credits per GB per hour hosting
shard_seedinginteger5Credits per GB seeding
relay_serviceinteger2Credits per connection hour relaying
penalty_serve_failureinteger50Credits deducted per failure

[updates] — Auto-Update

OptionTypeDefaultDescription
modestring(unset → "install")What the node does when a newer release exists: "off" (never checks), "notify" (tells you), "download" (downloads; you click to install), "install" (downloads, installs and restarts itself when idle). Updates are signed, and a node refuses one it cannot verify. Applies without a restart: the running node reads it before every check, so a change lands within check_interval_hours (Check now in Settings acts at once)
auto_updatestring"disabled"Legacy setting kept so old config files load. It no longer changes anything — unless mode is set, every value means mode = "install". Use mode
check_interval_hoursinteger1Update check frequency
include_prereleasesbooleantrueOffer pre-release builds. Defaults on because every release so far is tagged -alpha, so excluding them would mean never seeing an update at all

swarmllm run --no-update-check turns update checking off for that run, whatever mode says, and nothing — a settings save included — switches it back on; start the node without the flag to restore it. (Until v0.3.205 the flag changed nothing: it set the legacy auto_update, which no longer decides anything.)

[identity] — Your Identity

OptionTypeDefaultDescription
regionstringnoneCountry code for network map (e.g., "US")

[providers] — Cloud Providers

Set from the dashboard (Settings → Cloud Providers) or PUT /api/admin/providers, which write this section for you. Keys can also come from the environment or a .env file in the data directory, under the standard names (OPENAI_API_KEY, ANTHROPIC_API_KEY, …).

OptionTypeDefaultDescription
key_sourcestring"auto"Which key wins when both exist: auto (the dashboard's, then the environment's), env (the environment always wins) or dashboard (the environment is ignored)
anthropic, openai, deepseek, mistral, groq, nvidia_nim, cerebras, sambanova, fireworks, together, deepinfra, moonshottablenoneOne per provider: api_key, and an optional default_model
customlist[]Any other OpenAI-compatible service: name, base_url, api_key, optional default_model

[providers.claude_subscription] — Claude Subscription (feature-gated)

Requires --features claude-subscription at build time. Managed via the dashboard or PUT /api/admin/providers.

OptionTypeDefaultDescription
enabledbooleanfalseRoute claude-* model requests through the local CLI
claude_binarystring"claude"Path to the claude binary
default_modelstringnoneOverride model for all requests
max_concurrentinteger3Maximum concurrent subprocess invocations
timeout_secsinteger300Per-request timeout in seconds
working_dirstring(temp dir)Working directory for the subprocess. Empty or "none" uses system temp dir (recommended for API proxy use). Set to a project path for context-aware responses.