Skip to content

config:set, config:get & config:unset

CLI commands for safely reading, modifying, and deleting keys in workspace.yaml with schema validation. Keys must be fully qualified from the workspace root (e.g., software_delivery.gates.minCoverage, not gates.minCoverage). config:set supports complete JSON replacement of the kernel lanes array and security object; config:unset validates deletions under security and policies before writing.

When you provide a key, config:set, config:get, and config:unset route it based on its first segment:

config:set and config:unset refuse any dotpath containing __proto__, constructor, or prototype before changing configuration. Unknown root keys are refused with the valid writable roots listed in the error. Every writable root needs an explicit validated handler.

First segment matchesBehaviorExample key
Writable subkeyWrites/reads a validated subkey at the workspace rootcontrol_plane.sync_interval
Complete kernel rootconfig:set replaces the root from strict JSON; lanes retains managed reads, security is readable, and unset protects required roots/fieldslanes, security
Pack config keyWrites/reads under the pack’s config block, validated against the pack schemasoftware_delivery.gates.minCoverage
Governed subkeyWrites or removes a validated policy subkey; unset may remove optional security keyspolicies.*
Managed root keyError with guidance: “use <command> instead”packs, id, name
Unknown keyError with did-you-mean suggestion if possiblegates.minCoverage

These roots support validated subkey writes:

  • control_plane — Control plane connection and sync settings
  • policies — Workspace policy entries

Kernel lanes and security use complete-root JSON replacement through config:set, not dotted subkey writes.

Pack config keys are declared by domain packs in their manifest.yaml via the config_key field. For example, the Software Delivery pack declares config_key: software_delivery, making its schema-supported software_delivery.* paths writable via config:set. The kernel is domain-agnostic; Software Delivery is one pack, and other packs declare their own roots.

For an installed pack other than Software Delivery, config:set replaces its config_key as a whole section only. The value must be a complete object supplied with --json-value and validated against the pack’s config_schema. A pack that declares no config_schema rejects every write to its root. Software Delivery keeps nested-key writes such as software_delivery.gates.conditional_commands.

Writes to pack config keys are validated against the pack’s config schema if one is provided. Pack validation uses the kernel’s bounded JSON-Schema-to-Zod subset, not full JSON Schema conformance. Unknown assertion keywords, constraint intersections, and exact oneOf semantics are not guaranteed.

Use config:set to replace the complete kernel lanes array or security object. Supply explicit operator-chosen scopes; no grants are inferred. These roots reject partial dotted writes and unknown nested scope keys. The write is schema-validated before the micro-worktree starts, revalidated in the worktree, and read back after the surgical write. Packs and software_delivery.lanes remain untouched. For example:

pnpm config:set --key lanes --json-value '[{"id":"engineering","title":"Engineering","allowed_scopes":[{"type":"path","pattern":"src/**","access":"write"}]}]'
pnpm config:set --key security --json-value '{"allowed_scopes":[{"type":"path","pattern":"src/**","access":"write"}],"deny_overlays":[".git/**"]}'
pnpm config:unset --key policies.example_policy

Partial lanes.* and security.* writes are refused. lane:edit keeps its existing behavior, including edits to Software Delivery lane definitions. config:unset cannot remove required kernel roots or required schema fields. The root-level id, name, and packs remain managed. Use lumenflow:init to establish missing or new identity and pack:install for pack pins. Initialization preserves existing id and name; it does not rename a workspace. config:get continues to refuse managed lanes reads.

If you use an unqualified key that matches a known pack sub-key, the error includes a suggestion:

[config:set] Unknown root key "gates".
  Did you mean "software_delivery.gates.minCoverage"?

Safely updates a value in workspace.yaml.

pnpm config:set --key <dotpath> (--value <value> | --json-value <json>)
FlagRequiredDescription
--keyYesFully qualified config key in dot notation (e.g., software_delivery.gates.minCoverage)
--valueOne value flagScalar value or comma-separated array append
--json-valueOne value flagStructured JSON value, still schema validated
--helpNoShow usage information
# Set methodology testing mode
pnpm config:set --key software_delivery.methodology.testing --value test-after

# Set minimum coverage threshold
pnpm config:set --key software_delivery.gates.minCoverage --value 85

# Disable coverage gate
pnpm config:set --key software_delivery.gates.enableCoverage --value false

config:set requires exactly one of --value and --json-value. The JSON flag parses a structured value and does not bypass schema validation. --value coerces scalar strings and comma-separated array values:

Input ValueExisting TypeCoerced To
"true"anytrue (boolean)
"false"anyfalse (boolean)
"42"number42 (number)
"A,B,C"arrayappend A, B, C
"hello"string"hello" (string)

If the value fails Zod schema validation, the command exits with a descriptive error and no changes are written. Complete kernel root values are validated before micro-worktree creation and read back after the write:

[config:set] Validation failed for software_delivery.methodology.testing=invalid-value:
  Invalid enum value. Expected 'tdd' | 'test-after' | 'none', received 'invalid-value'

If you use an unqualified key, you get a routing error:

[config:set] Unknown root key "gates".
  Did you mean "software_delivery.gates.minCoverage"?

If you try to write a managed key:

[config:set] Key "packs" is managed by a dedicated command. Use `pnpm pack:install` instead.

Reads and displays raw values from writable or declared pack roots in workspace.yaml. It uses the same routing logic as config:set and refuses managed roots (id, name, packs, lanes) and unknown roots. Reading does not validate a write.

pnpm config:get --key <dotpath>
FlagRequiredDescription
--keyYesFully qualified config key in dot notation (e.g., software_delivery.methodology.testing)
--helpNoShow usage information
# Read a pack config value
pnpm config:get --key software_delivery.methodology.testing
# Output: tdd

# Read a numeric value
pnpm config:get --key software_delivery.gates.minCoverage
# Output: 90

# Read an object (outputs as YAML)
pnpm config:get --key software_delivery.methodology
# Output:
#   testing: tdd
#   architecture: hexagonal

# Read a writable root key
pnpm config:get --key control_plane
# Output:
#   sync_interval: 60
#   endpoint: https://api.lumenflow.dev

# Read a missing key
pnpm config:get --key software_delivery.nonexistent.key
# Output: [config:get] Key "software_delivery.nonexistent.key" is not set (undefined)

Safely deletes a key from workspace.yaml. The delete inverse of config:set — use it to remove stale config blocks (e.g., a decommissioned agent client) without hand-editing YAML.

pnpm config:unset --key <dotpath>
FlagRequiredDescription
--keyYesFully qualified config key in dot notation (e.g., software_delivery.agents.clients.gemini-cli)
--helpNoShow usage information
# Remove a stale agent client block
pnpm config:unset --key software_delivery.agents.clients.gemini-cli

# Remove a policy entry
pnpm config:unset --key policies.example_policy

# Remove a deprecated or stale control-plane setting
pnpm config:unset --key control_plane.policy_mode
  1. Routes the key with the same prefix rules as config:set, including validated security and policies subkeys
  2. Errors if the key does not exist (nothing to unset)
  3. Deletes the key, then validates the complete affected object against its owning schema
  4. If validation passes, writes through the governed configuration writer

Unknown-key detection is deliberately not applied to the deleted path: removing a key the schema no longer recognizes is exactly what config:unset is for (stale config blocks). Only the complete remaining affected object must validate; unrelated retired keys do not block sequential cleanup. Surgical writes preserve non-target comments, ordering, and quoting, and rejected deletions leave the file unchanged.

Limitations: setting a value changes only the edited span, so it refuses, with a CONFIG_ERROR and no change to the file, any path through an alias, a map with a << merge key, or an anchored value. It also refuses a path that runs through a non-null scalar, a sequence index that does not exist or would need inserting, a sequence item that would change kind, and any edit that would not parse back to the requested value. Duplicate keys were already refused. Deleting a key still re-serializes the whole file, so byte-level details outside the deleted key are not guaranteed to survive a delete. A flow map or flow sequence (empty {} and [] included) that is the target or sits on the path is converted to block style, only that one node, and the edit then applies; comments inside it are not kept, and one holding an alias or an anchor is refused. config:set and lane:edit both use this writer.

[config:unset] Key "software_delivery.agents.clients.codex-cli" not found in workspace — nothing to unset.
[config:unset] Key "packs" is managed by a dedicated command. Use `pnpm pack:install` instead.

Deleting an entire pack config block (software_delivery), control_plane, or required kernel root (lanes or security) is refused. Deletions that would leave the remaining config schema-invalid (including removal of required security scopes) are rejected before commit.

Software Delivery pack (software_delivery.*)

Section titled “Software Delivery pack (software_delivery.*)”
DotpathTypeValues
software_delivery.methodology.testingenumtdd, test-after, none
software_delivery.methodology.architectureenumhexagonal, layered, none
software_delivery.gates.minCoveragenumber0-100
software_delivery.gates.enableCoveragebooleantrue, false
software_delivery.gates.maxEslintWarningsnumberNon-negative integer
software_delivery.git.requireRemotebooleantrue, false
software_delivery.git.declaresClaimRefProtectionbooleantrue, false
software_delivery.cleanup.triggerenumon_done, on_init, manual
software_delivery.external_work_items.*objectProvider close-out/readback adapters and audit settings
software_delivery.agents.methodology.principlesstring[]Array of methodology names
DotpathTypeDescription
control_plane.sync_intervalnumberSeconds between control plane syncs
control_plane.endpointstringControl plane API URL

memory_namespace and event_namespace are retired root keys. Remove them from existing workspace.yaml files; they cannot be re-added through current config routes. Run the native cleanup sequentially before rerunning init:

pnpm config:unset --key security.network_default
# Remote-enabled mode only: synchronize the local checkout before the next mutation
pnpm git:sync-main
pnpm config:unset --key memory_namespace
# Remote-enabled mode only: synchronize the local checkout before the next mutation
pnpm git:sync-main
pnpm config:unset --key event_namespace
# Remote-enabled mode only: synchronize the local checkout before the next mutation
pnpm git:sync-main
pnpm config:unset --key control_plane.policy_mode
# Remote-enabled mode only
pnpm git:sync-main

The exact namespace-root deletion exception applies only when no pinned pack declares that root. Pack-owned roots retain normal pack routing and validation. Initialization does not automatically clean legacy inputs. security.network_default is also retired: configure network posture on the relevant entries in security.allowed_scopes instead.

control_plane.policy_mode is temporarily accepted as a deprecated input for backward compatibility. It is ignored when the runtime parses configuration, and lumenflow:doctor warns while the key remains. Remove it with pnpm config:unset --key control_plane.policy_mode. It will be removed after at least one release. A provided value is enum validated and stripped from effective workspace configuration. The programmatic SDK Mock policy mode and Cloud database/wire contracts are unchanged.