On this page
Config subsystem: file loading (JSON + TOML), value coercion, config fields, the --config/XDG path model, and five auto-registered `config` subcommands.
#typescript/src/config
#typescript/src/config
Config subsystem: file loading (JSON + TOML), value coercion, config fields, the --config/XDG path model, and five auto-registered config subcommands. The subcommands are show, set, path, edit, and init.
Parity sources: go/strictcli/config.go and the Python config sections; where they diverge, Python is the ground truth (per the port convention), pinned by conformance/cases/config*.json. Subcommand output strings that are inline fmt/f-strings in BOTH siblings stay inline here too (the values.ts precedent); genuinely new templates (TOML 1.0 gate, app-level config option validation) live in errors.ts.
Value model: config ints are bigint end-to-end (JSON int tokens and TOML integers), floats are number, dict-flag values coerce to Map. The JSON loader is a small strict parser (not JSON.parse) because the sibling behavior needs two things V8 cannot give: the int/float distinction from the source token, and 1-based line/column error positions for the "config file
#JsonLoadFailure
export class JsonLoadFailure extends ErrorA JSON config document failed to parse. line/column are 1-based; offset is 0-based.
#parseJsonConfig
export function parseJsonConfig(text: string): unknownMinimal strict JSON parser: objects become null-prototype records (insertion order preserved, no prototype pollution), integer tokens become bigint, fraction/exponent tokens become number. Error messages use the Python json vocabulary ("Expecting value", ...), since Python is the message ground truth and V8's messages carry no reliable position.
#nestedGet
export function nestedGet(Looks up a dot-separated key; ok=false when any segment is missing/non-map.
#nestedSet
export function nestedSet(Sets a dot-separated key, creating (or replacing non-map) intermediates.
#nestedDelete
export function nestedDelete(Deletes a dot-separated key, pruning now-empty intermediate maps.
#collectNestedKeys
export function collectNestedKeys(Flattens a nested record to dot-separated leaf key paths.
#configFilePath
export function configFilePath(The config file path for an app: the override (with ~ expanded, Python behavior) when present, else $XDG_CONFIG_HOME/
#ConfigFileResult
export interface ConfigFileResult#loadConfigFile
export function loadConfigFile(Loads the config file. Missing file with isRuntimeFlag (the user passed --config) is a hard error; missing file otherwise is soft (empty data). Malformed files are always hard errors with 1-based position info.
#configTypename
export function configTypename(v: unknown): stringPython _config_typename vocabulary for config-decoded values.
#coerceConfigValueForFlag
export function coerceConfigValueForFlag(value: unknown, f: AnyFlag): unknownCoerces a config value to a flag's type: dict flags take objects (-> Map), list flags take arrays, scalars take scalars. Throws a plain Error with the bare message; parse.ts wraps it as "--flag: config value error:
#ConfigFieldSpec
export interface ConfigFieldSpec<Out = unknown>Declares a typed config file field. Fields with no default are required (the config system errors when they are missing); fields with a default are optional. Dots in the field name form TOML sections.
#ConfigFieldRt
export interface ConfigFieldRtRuntime record of a declared config field.
#checkFlagConfigFieldDefault
export function checkFlagConfigFieldDefault(Registration-time agreement check for a flag colliding with a config field (a validation-only coexistence): explicit defaults on both sides must be equal. A flag default of undefined/null means "no default".
#registerConfigField
export function registerConfigField(Declares a typed config file field on the app (App.configField delegate).
#registerFrameworkField
export function registerFrameworkField(Declares an internal framework config field (underscore-prefixed names, never exposed to users). Framework fields are always required-shaped (no default) and exist for key-recognition only.
#validateConfigFieldsForCommand
export function validateConfigFieldsForCommand(Parse-time config-field validation (Python step 2.5): every bound required field must exist with the declared type, and every key in the config file must be known (a flag param name, config field, or framework field). Returns an error message, or undefined when all checks pass.
#collectAllFlags
export function collectAllFlags(app: AppImpl): AnyFlag[]All flags visible to the config system: global flags plus every command's flags across all groups (first occurrence per name wins), skipping the auto-generated config group itself.
#collidingConfigFields
export function collidingConfigFields(Config fields whose name equals a flag's param name, keyed by that name. Such fields are validation-only: they annotate the colliding flag and render once (on the flag), not as a separate config key.
#jsonDumpsPy
export function jsonDumpsPy(Python-json.dumps-shaped serialization: ", "/": " separators (or indented layout), bigint as bare integer tokens, floats in SCF, Maps as objects with sorted keys (the TS dict display rule), plain objects in insertion order unless sortKeys.
#formatConfigValue
export function formatConfigValue(v: unknown): string Formats a config value for config show output (Python _format_config_value).
#resolveFlagShowSource
export function resolveFlagShowSource(Effective value and source for a flag in the config show context. Precedence: env > config > default. "cli" is structurally impossible here (config show is a subcommand; the app's own flags were never passed).
#generateTomlTemplate
export function generateTomlTemplate(app: AppImpl): stringTOML template with comments (Python _generate_config_template_toml).
#generateJsonTemplate
export function generateJsonTemplate(app: AppImpl): stringJSON template (Python _generate_config_template_json).
#registerConfigGroup
export function registerConfigGroup(app: AppImpl): voidRegisters the config command group (path/show/set/edit/init) on the app. Commands are installed directly (bypassing the app-context collision checks), mirroring Python's direct Command construction -- user global flags named e.g. "json" must not collide with config subcommand flags.
#makeConfigProvider
export function makeConfigProvider(app: AppImpl): ConfigProviderThe ConfigProvider installed by app.dispatch: loads the config file per parse (recording data and parse errors on the app for the config subcommands), coerces raw config values to flag types, and runs the step-2.5 config-field validation.