Skip to content

Configuration Scopes

Z-M-Huang edited this page Apr 27, 2026 · 4 revisions

Configuration Scopes

contractVersion: 1.0.0

The three-layer system that resolves which extensions, MCP servers, and settings are active in a session. Layers are fixed by core — extensions do not introduce new scopes.


The three layers

flowchart LR
    B[bundled<br/>in package] --> Merge[merged configuration]
    G[global<br/>~/.stud/] --> Merge
    P[project<br/>cwd/.stud/] --> Merge
    Merge --> Session[session manifest]
Loading
Layer Location Mutability Trust
Bundled Inside the stud-cli package Immutable at runtime Trusted by install.
Global ~/.stud/ User-owned Trusted by install-time acceptance.
Project <cwd>/.stud/ (cwd only — no walk-up) User-owned per project Requires Project Trust on first entry.

Later layers override or extend earlier ones.


Per-category merge rules

Extension categories fall into unordered or ordered groups for merge purposes.

Unordered categories

Providers, Tools, UI, Loggers, State Machines, Commands, Session Stores, Context Providers.

Merge rule: name-based override, later-layer wins.

flowchart LR
    B["bundled: X, Y, Z"] --> M
    G["global: X', W"] --> M
    P["project: X'', V"] --> M
    M[merged] --> Final[X'' from project<br/>Y from bundled<br/>Z from bundled<br/>W from global<br/>V from project]
Loading
  • Same name → highest-priority layer wins; lower-priority hidden.
  • New name → added to the merged set.
  • A layer can also disable an inherited entry by name (disable: true in its config).

Ordered categories

Hooks (ordered by stage × position × sequence).

Merge rule: concatenation with ordering-manifest rewrite.

  • Bundled hooks at a stage × position load in bundled order.
  • Global hooks for the same slot append after bundled.
  • Project hooks append after global.
  • A layer's ordering manifest may rewrite the full order for that category — overriding the default concat.

A project ordering-manifest rewrite emits an OrderingRewrite warning event and is control-plane-sensitive — trusting the project trusts any ordering it ships. See Project Trust.


Settings layering

settings.json exists at each layer (bundled defaults, ~/.stud/settings.json, <cwd>/.stud/settings.json). Merge rule: deep merge with later-layer-wins on scalar values, later-layer-replace on arrays (unless the field is explicitly additive per its schema).

Common fields:

Field Layered? Special notes
env Yes Project env is a commit footgun for secrets. See Secrets Hygiene.
securityMode Yes Session-fixed; resolved at session start.
securityMode.allowlist Yes Merged lists; project can extend.
providers Yes Override by id.
logging Yes Deep merge.

mcp.json layering

MCP server lists at global (~/.stud/mcp.json) and project (<cwd>/.stud/mcp.json). Merged as unordered entries by server id. Project can override a global server's command; project can disable a global server; project can add new servers. See MCP and MCP Trust.


Project root is cwd only

No walk-up. If the session starts in /a/b/c/, core looks for /a/b/c/.stud/, not /a/b/.stud/ or /a/.stud/. This is load-bearing for trust — developers working in nested projects are not silently loading a parent's extensions.

See Project Root.


Origin tracking

Every loaded extension's origin layer is reported by Extension Discovery and surfaced via /tools, /health, and the audit/event stream — not persisted in the slim session manifest. Readers (user, audit, /tools, /health) can see:

  • Where an extension came from (bundled / global / project).
  • Which layer's configuration is active for it.
  • Whether it shadows an inherited extension.

Project-scope override validation fallback (Q-3)

When a project-scope extension override fails validation, core validates the override before replacement and retains the global version of the plugin rather than leaving the slot empty:

  1. The Validation Pipeline validates the project-scope contract.
  2. On failure, the override is disabled and its structured outcome is recorded for the TUI startup diagnostics surface.
  3. If a matching global extension was already valid, that global extension remains in the registered set. The project override never replaces it.
  4. If no matching global extension exists, the project extension is simply disabled.

This override-then-fallback rule ensures that a misconfigured project override does not break tools or providers that were working before the override was added.


Disabling inherited entries

A layer disables a name from a lower layer by setting disable: true in its config for that name:

  • Bundled tool Bash → global settings.json sets tools.Bash.disable: true → the tool is not registered.
  • Global logger fileLogger → project settings.json sets loggers.fileLogger.disable: true → not registered.

Disabling is distinct from overriding. An override supplies a replacement; disabling removes without replacement. Both are reversible by removing the directive.


Shadowing consequences

Same-name override across layers is called shadowing:

  • For tools, shadowing means the allowlist / SM / interactor see the new tool under the old name. The user's project-trust prompt is the primary guard.
  • For providers, shadowing means /provider now points at the override; capability negotiation re-runs.
  • For commands, shadowing changes what /name does.

/tools, /health, and /providers surface shadowing.


Example resolution

Walk through a session where:

  • Bundled ships: tool:Bash, tool:Edit, logger:stdout, cp:repoSummary.
  • Global ~/.stud/ adds: provider:openai-proxy; disables logger:stdout; adds logger:fileDebug.
  • Project .stud/ adds: hook:pre-tool-audit (with ordering-manifest rewrite); overrides tool:Bash with a stricter wrapper.

Resolution:

Extension Origin Active?
tool:Bash Project (overrides bundled) Yes. Bundled hidden.
tool:Edit Bundled Yes.
logger:stdout Bundled No — disabled by global.
logger:fileDebug Global Yes.
cp:repoSummary Bundled Yes.
provider:openai-proxy Global Yes.
hook:pre-tool-audit Project Yes; ordering-manifest rewrite warning emitted.

See Scope Layering flow.


Related pages


Changelog

1.0.0 — initial

  • Three-layer scopes (bundled, global, project); per-category merge rules; unordered name-based override; ordered-category concatenation with optional rewrite; mcp.json layering.
  • Project-scope override validation fallback: a failed project override leaves the previously valid global extension active and counts as a warning, not an error. The override is validated before it replaces the global; if it fails, the global stays.
  • Origin tracking on every loaded extension (surfaced via Extension Discovery and /tools / /providers / /health, not persisted in the session manifest).

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally