Reference

Configuration

Configuration layers belong to the CLI, the environment, and config files rather than hidden defaults: one discovered base file < project .netsuke.toml and its extends chain < environment variables < CLI flags. Fetch grants, env() allow rules, and evaluation budgets are the deliberate exceptions.

Configuration

When neither --config nor NETSUKE_CONFIG selects a file, Netsuke layers configuration in this order, with later entries overriding earlier ones: one discovered base winner (user configuration, otherwise system configuration, otherwise built-in defaults) < project .netsuke.toml and its extends chain < NETSUKE_ environment variables < CLI flags. Automatic discovery picks exactly one base file rather than merging system and user scopes, then appends the project layer so project values can override it while fields present only in the winner remain available. An explicit selector bypasses discovery entirely: the selected file replaces the discovered base and project layers, and environment variables and flags still apply on top. A flag on the command line always wins, and project config files can be overridden per-invocation without editing them. Three security-sensitive settings do not follow this order; see security exceptions.

Note: The keys below mirror docs/sample-netsuke.toml in the repository as of v0.1.0-beta4. Netsuke is pre-1.0 — some key names and default values may still change before a stable release. Check the project repository for the latest status.

Config file discovery

An explicit selector bypasses discovery entirely. Selectors are checked in this order:

  1. --config /path/to/file.toml (CLI flag)
  2. NETSUKE_CONFIG=/path/to/file.toml (environment)

Without a selector, automatic discovery chooses one exclusive base winner from the platform's user scope (XDG base directories and the home directory on Unix; %APPDATA%\netsuke\config.toml on Windows), then the system scope, then built-in defaults, and appends .netsuke.toml from the project directory selected by -C/--directory. Discovery runs once and is cached for the rest of the command.

CLI-only controls such as --config, --directory, and subcommands are not read from configuration files. --directory does not rebase a relative --config or NETSUKE_CONFIG path; pass an absolute selector when it must not depend on the invoking directory.

When discovery finds no file, Netsuke uses its built-in defaults. When it finds a file that cannot be loaded — malformed TOML, for example — it reports the load error rather than treating the broken file as absent. An explicit --config or NETSUKE_CONFIG selection that is missing or invalid is likewise an error; Netsuke does not fall back to discovery.

Environment variables

Settings can be controlled via NETSUKE_-prefixed env vars:

NETSUKE_JOBS=8
NETSUKE_LOCALE=es-ES
NETSUKE_PROGRESS=never
NETSUKE_ACCESSIBILITY=on
NETSUKE_EMOJI=never
NETSUKE_JSON=1
NETSUKE_NO_INPUT=true
NETSUKE_DEFAULT_TARGETS__0=hello.txt
NETSUKE_NINJA=/opt/ninja/bin/ninja
NETSUKE_WINDOWS_SHELL=bash
NETSUKE_WHICH_WORKSPACE=0
NETSUKE_TRUST_PROJECT_FETCH_POLICY=true
NETSUKE_ENV_ALLOW_VAR='["CI"]'
NETSUKE_ENV_BLOCK_VAR='["GITHUB_TOKEN"]'
NETSUKE_MANIFEST_FUEL=50000000

Policy values are matched case-insensitively. NETSUKE_JSON accepts true/1 and false/0; anything else is a validation error rather than a silent fallback. NETSUKE_NINJA overrides the Ninja executable used by build and clean; empty or non-UTF-8 values fall back to ninja on PATH. NETSUKE_WHICH_WORKSPACE set to 0, false, or off switches off the explicit cwd_mode="workspace-recursive" search; it no longer governs a default fallback, because which has none. The two NETSUKE_ENV_*_VAR variables take serialized JSON arrays, not bare names.

Config keys

Build

Where the manifest lives and how hard Netsuke works: the path to the Netsukefile, how many jobs may run at once, and what a bare netsuke build should make.

Output

What Netsuke prints, and how. Progress, accessible mode, emoji, and colour each auto-detect the terminal; set one explicitly to override the guess. locale picks the language messages are written in.

Policy

What the fetch() and env() helpers may reach. Choose whether unlisted hosts are denied, name the hosts to allow or block, and list the environment variables a manifest may read. Allow entries belong in operator configuration: a project file cannot grant them on its own authority.

# Keys are flat; this mirrors docs/sample-netsuke.toml
# Manifest path override
file = "Netsukefile"
# Number of parallel jobs (1-64)
jobs = 8
# Default build targets when the CLI names none
default_targets = ["fmt", "lint", "test"]
# Netsuke never prompts; `no_input = false` is rejected
no_input = true
# Output policies
progress = "auto"       # auto | always | never
accessibility = "auto"  # auto | on | off
emoji = "auto"          # auto | always | never
color = "auto"          # auto | always | never (colour rendering not yet implemented)
locale = "en-US"
# One versioned JSON document per command; disables tracing on stderr
json = false
# Diagnostic tracing, timing summaries, and a final metrics snapshot
verbose = false
# Network policy for the fetch() helper
fetch_default_deny = false
# Allow entries in a project .netsuke.toml are ignored
# unless the operator enables trust_project_fetch_policy
fetch_allow_scheme = ["https"]
fetch_allow_host = ["*.example.com"]
fetch_block_host = ["metadata.internal"]
# Operator layers only; a project cannot set it for itself
trust_project_fetch_policy = false
# env() access: exact names, a block always wins
env_allow_var = ["CI", "PACKAGE_REGISTRY_TOKEN"]
env_block_var = ["AWS_SECRET_ACCESS_KEY"]

Security exceptions to precedence

Since v0.1.0-beta4

A checkout's own .netsuke.toml is a request, not an order. For three kinds of setting, the primary project file can tighten what the operator allows but never loosen it. System and user configuration, NETSUKE_ variables, and CLI flags are the operator layers. For fetch and env() policy, only the primary project file is quarantined this way; files pulled in through extends keep ordinary file-layer precedence. For evaluation budgets, though, a value from the extends chain counts as a project value too, so it can likewise only narrow a ceiling, never raise one.

Fetch policy

Project fetch_allow_scheme and fetch_allow_host are ignored unless an operator sets trust_project_fetch_policy. A project may turn fetch_default_deny on but not off, and its block entries always count. Network policy.

env() access

Project env_allow_var entries are removed before the policy is composed, so they can neither widen the allowlist nor switch on default-deny. Project env_block_var entries accumulate. Environment access.

Evaluation budgets

A project value, including one from its extends chain, may lower a manifest_* ceiling but cannot raise one set by the defaults, user configuration, the environment, or the CLI. Resource budgets.

Budget keys

Since v0.1.0-beta4

Seven keys bound manifest evaluation. They are not in docs/sample-netsuke.toml; the names and defaults below come from the upstream users' guide and the CLI definition. Each has a NETSUKE_ variable (the key in upper case) and a --manifest-* flag. Values must be positive integers.

# Defaults shown; set these in trusted configuration
manifest_evaluation_fuel = 1000000           # MiniJinja instructions per evaluation
manifest_fuel = 100000000                    # MiniJinja instructions per manifest
manifest_rendered_value_bytes = 1048576      # 1 MiB per rendered value
manifest_rendered_manifest_bytes = 16777216  # 16 MiB across all rendered values
manifest_source_bytes = 4194304              # 4 MiB of template source
manifest_foreach_cardinality = 10000         # values per foreach
manifest_expanded_entries = 50000            # targets and actions after expansion

A breach reports Manifest resource budget exhausted with the stage and limit, under the JSON code netsuke::runner::manifest_budget_exceeded.

Diagnose configuration selection

Pass --verbose to see how Netsuke chose its configuration. Structured events on stderr report whether --config, NETSUKE_CONFIG, or automatic discovery won, which environment lookups were attempted, and each layer as the merge applies it. File-layer events carry a bounded path_hash rather than the raw path; CLI events record only the overridden leaf keys, never their values. A rejected setting is reported with its key and a bounded reason.

What a broken file does

A discovered file that cannot be loaded — malformed TOML, or an extends parent that is missing — is reported as a load error, not treated as absent. An explicit selector that is missing or invalid is likewise an error; Netsuke never falls back to discovery from an explicit file. The warning records failure_kind as Missing or LoadError.

Metrics snapshot

With --verbose, Netsuke emits one final metrics snapshot debug event before exiting: bounded counters and histograms for configuration loading (config_load_total, config_load_duration_seconds), cached discovery, raw CLI path validation, and legacy recipe execution. Since v0.1.0-beta4 it also carries netsuke_runner_manifest_structures_total, which counts manifest structural summaries and records only integer collection sizes, and netsuke_manifest_env_lookups_total, which counts env() lookups by outcome (success, blocked, not_present, not_unicode) without naming a variable. It is an in-process diagnostic record, not a metrics endpoint. JSON mode suppresses all of this tracing so stderr stays a single machine-readable document.