skill-up employs a multi-layered configuration system designed to provide sensible defaults while allowing granular overrides for specific projects or single command invocations. This system manages OpenTelemetry (OTEL) settings, ambient environment variables, and runtime-specific parameters (runtime_kwargs) [docs/guide/user-config.md:1-9].
The configuration is resolved by merging four layers in order of increasing precedence. Higher-precedence layers overlay non-zero fields onto lower layers; map fields (like env or runtime_kwargs) are merged key-wise rather than replaced [internal/userconfig/loader.go:1-11].
| Layer | Source / Path | Behavior if Missing |
|---|---|---|
| 1. Embed | Internal Config{} struct | Always present (empty) [internal/userconfig/loader.go:68-68] |
| 2. User | $SKILL_UP_CONFIG or $XDG_CONFIG_HOME/skill-up/config.yaml | Skipped with warning [internal/userconfig/loader.go:74-74] |
| 3. Project | $PWD/.skill-up.yaml | Skipped with warning [internal/userconfig/loader.go:75-75] |
| 4. Explicit | CLI flag --config <path> | Hard Error [internal/userconfig/loader.go:77-87] |
Sources: [internal/userconfig/loader.go:1-11], [docs/guide/user-config.md:13-38], [internal/userconfig/loader.go:24-34]
The LoadEffective function in internal/userconfig/loader.go orchestrates this discovery. While user and project layers (handled by mergeOptionalLayer) downgrade parsing errors to warnings to avoid blocking the CLI, the explicit layer (via opts.ExplicitPath) requires a valid file and returns a fatal error if missing or corrupt [internal/userconfig/loader.go:56-87], [internal/userconfig/loader.go:108-122].
The following diagram illustrates how the userconfig.LoadEffective function traverses filesystem locations and environment variables to build the final configuration.
"Configuration Discovery Flow"
Sources: [internal/userconfig/loader.go:56-103], [internal/userconfig/loader.go:124-155]
The configuration file uses YAML and follows a versioned schema (v1alpha1) defined in the Config struct [docs/guide/user-config.md:43-45].
Sources: [docs/guide/user-config.md:43-63], [internal/cli/init.go:125-171]
${VAR} in the env section are expanded from the process environment during loading, allowing secrets to remain out of the configuration file [docs/guide/user-config.md:70-72].run command based on the environment.type (e.g., opensandbox, docker). Values defined in a specific eval.yaml will always override these defaults [internal/userconfig/apply_test.go:70-81].The ApplyEnv and MergeKwargs functions bridge the static configuration to the active runtime environment.
The ApplyEnv function iterates through the Telemetry and Env structs, mapping them to standard OTEL_* variables and custom keys. It returns a list of keys that were actually modified [internal/userconfig/apply_test.go:10-42]. If Telemetry.Verbose is enabled, it automatically sets OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_CONTENT, and OTEL_LOG_TOOL_DETAILS to 1 [internal/userconfig/apply_test.go:11-42].
When an evaluator starts, it calls MergeKwargs to combine project-level defaults from Config.RuntimeKwargs with case-specific overrides from eval.yaml.
"Kwargs Merging Logic"
Sources: [internal/userconfig/apply_test.go:70-100]
Beyond the YAML config file, skill-up respects specific environment variables that influence internal behavior:
SKILL_UP_BASHOverrides the bash interpreter used for .sh script judges and shell commands [docs/guide/user-config.md:129-133].
bash on PATH. On Windows, it probes well-known Git Bash locations such as C:\Program Files\Git\bin\bash.exe [docs/guide/windows.md:23-32].PATH lookup or well-known path probing [docs/guide/user-config.md:140-142].C:\Windows\System32\bash.exe is explicitly rejected even if specified here because it expects Linux-format paths and fails on Windows-style paths [docs/guide/windows.md:38-43].Sources: [docs/guide/user-config.md:129-163], [docs/guide/windows.md:23-43]
skill-up init CommandThe init command is the primary tool for bootstrapping configuration files. It can generate a commented template or copy an existing configuration into the standard discovery paths [internal/cli/init.go:18-32].
skill-up init: Writes a template to the user-level XDG path (~/.config/skill-up/config.yaml) [internal/cli/init.go:28-32], [internal/cli/init.go:111-120].skill-up init --local: Writes a template to $PWD/.skill-up.yaml [internal/cli/init.go:29], [internal/cli/init.go:98-106].skill-up init --print: Dumps the template to stdout without writing to disk [internal/cli/init.go:30], [internal/cli/init.go:52-55].skill-up init --force: Overwrites an existing target file [internal/cli/init.go:37], [internal/cli/init.go:67-69].skill-up init --config <source> --local: Reads <source>, validates it using userconfig.LoadFile, and copies it to the project-level config file, preserving comments and formatting [internal/cli/init.go:23-25], [internal/cli/init.go:84-96].If no --config source is provided, init uses the initTemplateContent constant, which contains a fully commented-out YAML structure. This ensures that a newly initialized config is a "no-op" until the user explicitly enables features [internal/cli/init.go:85-87], [internal/cli/init.go:125-171].
The command uses resolveUserConfigTarget and resolveProjectConfigTarget to determine the destination path, ensuring compatibility with XDG standards on Linux/macOS [internal/cli/init.go:100-120].
Sources: [internal/cli/init.go:1-120], [internal/cli/init_test.go:22-38], [e2e/userconfig_test.go:32-56]
Refresh this wiki