ur-agent 1.68.18 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,195 +0,0 @@
1
- # 05 — Providers & Models
2
-
3
- Source of truth: `src/services/providers/providerRegistry.ts`, `src/utils/model/*`,
4
- `src/services/agents/{modelPool,modelRouter,escalation}.ts`, `src/commands/{model,provider,connect,effort,fast}`.
5
-
6
- ## Provider registry (`PROVIDERS` in providerRegistry.ts)
7
-
8
- | Provider id | Display name | Access | Credential | Status |
9
- |---|---|---|---|---|
10
- | `ollama` | Ollama | local runtime | none (localhost:11434) | **default local backend** |
11
- | `llama.cpp` | llama.cpp | local/server | OpenAI-compatible endpoint (localhost:8080/v1) | enabled |
12
- | `vllm` | vLLM | server | OpenAI-compatible endpoint (localhost:8000/v1) | enabled |
13
- | `openai-compatible` | OpenAI-compatible | server/api | any base URL + optional `OPENAI_COMPATIBLE_API_KEY` | enabled |
14
- | `openai-api` | OpenAI API | api | `OPENAI_API_KEY` | enabled |
15
- | `anthropic-api` | Claude API | api | `ANTHROPIC_API_KEY` | enabled |
16
- | `gemini-api` | Gemini API | api | `GEMINI_API_KEY` | enabled |
17
- | `openrouter` | OpenRouter | api | `OPENROUTER_API_KEY` | enabled |
18
- | `subscription` | Subscription | subscription login | OAuth | placeholder |
19
- | `codex-cli` | Codex CLI | subscription via official CLI | `codex login` | `disabled: true` in registry |
20
- | `claude-code-cli` | Claude Code | subscription via official CLI | `claude auth login` | `disabled: true` |
21
- | `gemini-cli` | Gemini CLI | subscription via official CLI (Code Assist Std/Ent only) | — | `disabled: true` |
22
- | `antigravity-cli` | Antigravity | subscription via official CLI | — | `disabled: true` |
23
- | `lmstudio` | LM Studio | local server | OpenAI-compatible (localhost:1234/v1) | `disabled: true` |
24
-
25
- Provider aliases are normalized by provider commands and interactive pickers (e.g.
26
- `chatgpt`, `codex`, `openai codex` → `codex-cli`). Raw `settings.json` is stricter:
27
- `provider.active` and `provider.fallback` must use canonical registry IDs. Each definition
28
- declares capability metadata (native tool calls, native streaming, safety boundary label)
29
- used by the runtime and `/provider` UI. UR-native adapters—including LM Studio—use the
30
- UR-native request/tool boundary and never inherit an external subscription-CLI capability
31
- record.
32
-
33
- ### How to use
34
-
35
- ```
36
- /provider # interactive picker
37
- /provider ollama # switch provider
38
- /connect status # show all provider connection states
39
- /connect openrouter --key sk-or-… # store an API key (keychain-backed)
40
- /connect logout openrouter
41
- ur provider models openrouter # list models a provider serves
42
- ur provider doctor ollama # diagnose connectivity
43
- ```
44
-
45
- ## Ollama Cloud and the deployment enum
46
-
47
- **Authentication.** The Ollama client sends `Authorization: Bearer` when
48
- `OLLAMA_API_KEY` is set, and nothing otherwise. A local daemon needs no
49
- credential — it holds the account itself, which is how `:cloud` model suffixes
50
- resolve locally. A direct connection to the hosted API does need one, which is
51
- why CI (with no signed-in daemon) previously could not use Ollama at all. The
52
- key is trimmed, so a pasted trailing newline cannot corrupt the header, and
53
- read per request so a rotated key applies without restarting.
54
-
55
- Base-URL precedence: session override → `OLLAMA_HOST` / `OLLAMA_BASE_URL` →
56
- `ollama.host` setting → `https://ollama.com` when a key is set with no host →
57
- `http://localhost:11434`. An explicit host always wins, so self-hosted
58
- gateways that require a key are unaffected.
59
-
60
- `OLLAMA_API_KEY` is on the Agentic CI provider-credential allowlist, so it
61
- reaches the isolated agent while platform write tokens do not.
62
-
63
- **`APIProvider` is not the provider registry.** It is a deployment enum for
64
- request shaping, narrowed to `'foundry' | 'ollama'` — the only values
65
- `getAPIProvider()` can return. Comparisons against `'firstParty'`, `'bedrock'`
66
- or `'vertex'` were silently false and disabled advertised features; the
67
- typechecker now rejects them. Where such a branch is genuinely wanted, use the
68
- named predicates `isFirstPartyRuntime()`, `isBedrockRuntime()` and
69
- `isVertexRuntime()` (all currently `false`) so the intent stays greppable.
70
- `DeploymentKey` widens the type for legacy per-deployment lookup tables in
71
- `configs.ts`, `deprecation.ts` and `modelStrings.ts`, which carry rows for
72
- deployments this build cannot select.
73
-
74
- ## Model selection
75
-
76
- ```
77
- /model # interactive model picker for current provider
78
- /model qwen2.5-coder:7b
79
- ur --model llama3.3 # per-session
80
- ur --ollama-host http://gpu-box:11434 # remote Ollama server
81
- ur --discover-ollama # scan the LAN for Ollama servers (ollamaDiscovery.ts)
82
- ```
83
-
84
- - `startupModelSelection.ts` distinguishes deliberate model sources from
85
- silent defaults. With no project/local/flag/managed, CLI/environment, agent,
86
- or restored-session model, interactive startup requires
87
- `ProviderFirstModelPicker`; headless startup exits before model execution.
88
- - The startup picker validates the provider/model pair through the provider
89
- registry and persists it to `.ur/settings.local.json`. User-global model
90
- settings are intentionally insufficient for a new workspace.
91
- - `settings.json → model`, `provider.active`, top-level `availableModels`, and top-level
92
- `modelOverrides` persist choices per scope.
93
- - `src/utils/model/aliases.ts` maps friendly aliases; `validateModel.ts` checks against the
94
- provider's discovered list; `ollamaTuning.ts` adjusts context/params for local models.
95
- - Deprecation warnings and 1M-context upgrade checks live in `deprecation.ts` /
96
- `check1mAccess.ts`.
97
- - Ollama remains the default provider endpoint, but no model is silently chosen
98
- for a fresh workspace. Configured Ollama base URLs are honored consistently.
99
- - OpenAI-compatible endpoints use a dedicated credential key so an OpenAI API
100
- key is never forwarded to an arbitrary compatible base URL. Provider switches
101
- clear stale endpoint/command overrides.
102
- - Request adapters preserve system prompts, tools, images, stops, sampling,
103
- reasoning, metadata, and structured-output settings supported by each
104
- provider. Provider error payloads, empty responses, and truncated streams fail
105
- instead of becoming synthetic empty successes.
106
- - OpenAI API keeps Chat Completions as the default. Setting
107
- `provider.openaiTransport` through
108
- `ur config set openai_transport responses` selects the native Responses
109
- adapter with `store=false` by default, semantic SSE, background
110
- retrieve/poll/cancel, WebSocket continuation, compaction, deferred tool
111
- search, and bounded private cursor state. Compacted context persistence
112
- requires a 32-byte `UR_OPENAI_RESPONSES_STATE_KEY`.
113
- - `ollama.ts` selects timeouts from explicit request options, then
114
- `API_TIMEOUT_MS`, then runtime defaults. Remote sessions and ordinary
115
- `:cloud` models use 120 seconds; local models and Kimi K2.7 Cloud use 300
116
- seconds because large Kimi coding turns can legitimately take longer than
117
- two minutes before completing. The same model-aware value is applied while
118
- waiting for `/api/chat` response headers and as the absolute deadline in
119
- `readOllamaChunks`.
120
- - `ur.ts` identifies an Ollama Cloud runtime from both the selected provider and
121
- the `:cloud` suffix. It disables shared automatic request retries for that
122
- route, applies the same model-aware bound to any permitted non-streaming
123
- fallback, and skips fallback entirely when the Ollama stream deadline itself
124
- caused the failure. Explicit `API_TIMEOUT_MS` remains authoritative, and
125
- remote-session safety keeps its 120-second ceiling.
126
-
127
- ## Capability-aware routing
128
-
129
- ### Model pools (`src/services/agents/modelPool.ts`)
130
- Pools named `cheap` / `strong` / `default`, loaded in priority order:
131
- 1. `.ur/model-pool.json` in the repo — e.g. `{"cheap":["gemma2:2b"],"strong":["gpt-5.5"]}`
132
- 2. Env: `UR_MODEL_POOL_CHEAP`, `UR_MODEL_POOL_STRONG`, `UR_MODEL_POOL_DEFAULT` (comma lists)
133
- 3. Defaults: cheap `qwen2.5-coder:1.5b, gemma2:2b`; strong `qwen2.5-coder:32b, codex,
134
- claude-3-5-sonnet, gpt-4o`; default `qwen2.5-coder`.
135
-
136
- ### `/model-route` (modelRouter.ts)
137
- Classifies a task and recommends a model + strategy:
138
- ```
139
- /model-route "port this service to Rust" --strategy strong
140
- /model-route "rename a variable" --strategy auto --json
141
- ```
142
-
143
- ### `/escalate` (escalation.ts)
144
- Run on a fast model, auto-escalate hard steps to an "oracle":
145
- ```
146
- /escalate plan "design a consensus protocol" # show the split
147
- /escalate run "…" --fast qwen2.5-coder:7b --oracle gpt-5.5
148
- /escalate policy # view escalation policy
149
- ```
150
-
151
- ### `/model-doctor` (ollamaModels.ts + modelCapabilities.ts)
152
- Probes an installed Ollama model: tool-call support, context length, speed class, and
153
- reports "likely agent capabilities":
154
- ```
155
- /model-doctor llama3.3 --json
156
- ```
157
-
158
- ### Automatic learning loop (learning.ts)
159
- Every ci-loop, arena, escalation, test-first, and completed **local** cloud
160
- best-of-N run
161
- **automatically** records its pass/fail outcome (per task category and model) into
162
- `.ur/learning/stats.json` — a pure JSON fold, no model calls. The `auto` routing strategy
163
- and `/escalate`'s difficulty bias consume this evidence: a model with ≥3 recorded runs and
164
- a ≥60% success rate for the task's category is preferred when selectable; thin evidence
165
- falls back to the static heuristics unchanged. The store is idempotent (outcome keys
166
- dedupe) and best-effort (a broken store never fails a run). `/learn` remains for
167
- inspection and the optional LLM reflection pass:
168
- ```
169
- /learn stats # view what the agent has learned
170
- /learn run --reflect # optional: distill failures into lessons (uses a model)
171
- ```
172
- Disable automatic learning with `automaticLearningEnabled: false` or
173
- `UR_CODE_DISABLE_AUTO_LEARNING=1`.
174
-
175
- ## Session behavior knobs
176
-
177
- | Feature | Command | Notes |
178
- |---|---|---|
179
- | Effort level | `/effort low·medium·high·max·auto` | low/medium/high persist as `effortLevel`; max is session-only in the external build; auto clears the override |
180
- | Fast mode | `/fast` source exists but reports unavailable | requires the hosted first-party serving tier, which the standard npm build does not use; setting `fastMode` cannot manufacture that tier |
181
- | Advisor model | `/advisor` is hidden in the standard build | requires first-party beta headers plus an enabled runtime feature configuration; `advisorModel` alone does not enable it |
182
- | Always thinking | `alwaysThinkingEnabled` setting | force extended thinking |
183
- | Thinking summaries | `showThinkingSummaries` setting | UI display of thinking |
184
- | Fallback model | `--fallback-model` (print mode) | on overload |
185
-
186
- ## Offline / local-first
187
-
188
- - `ur --offline` or `offline` setting: no cloud APIs, telemetry, auto-update, remote control.
189
- - Offline dispatch permits only loopback local/server endpoints; cloud,
190
- subscription, remote Ollama, and remote compatible endpoints are blocked.
191
- - `/local-first` reports readiness for no-cloud/private/lab/edge deployment: which features
192
- degrade, which local deps (Ollama, ripgrep, playwright, ffmpeg…) are present.
193
- - `--bare` forces the minimal local pipeline (`UR_CODE_SIMPLE=1`) and always uses Ollama.
194
- - Ollama config: `ollama.host` and `ollama.lanDiscovery` settings; per-session
195
- `--ollama-host`; router in `ollamaRouter.ts` load-balances across discovered hosts.
@@ -1,428 +0,0 @@
1
- # 06 — Configuration
2
-
3
- Source of truth: `src/utils/settings/{types.ts,constants.ts,settings.ts}`,
4
- `src/utils/hooks/`, `src/keybindings/`, `src/utils/permissions/`.
5
-
6
- ## Settings scopes (later overrides earlier)
7
-
8
- | Scope | File | Notes |
9
- |---|---|---|
10
- | user | `~/.ur/settings.json` | global |
11
- | project | `.ur/settings.json` | shared, committed |
12
- | local | `.ur/settings.local.json` | gitignored |
13
- | flag | `--settings <file-or-json>` | per-invocation |
14
- | managed/policy | managed-settings.json or remote org settings | read-only, always loaded |
15
-
16
- `--setting-sources user,project,local` restricts which editable scopes load.
17
- Schema URL for editors: `https://json.schemastore.org/ur-settings.json`.
18
-
19
- Edit interactively with `/config`, by natural language with `/update-config`
20
- (bundled skill), or directly in the JSON files.
21
-
22
- Model selection has one intentional exception to ordinary merged precedence:
23
- a user-global model alone does not initialize a fresh workspace. Interactive
24
- startup requires a provider/model choice and writes it to
25
- `.ur/settings.local.json`; fresh headless startup requires `--model`, a model
26
- environment variable, or project/flag/managed configuration. Resumed sessions
27
- restore their session model without showing the picker.
28
-
29
- ## settings.json keys (from `SettingsSchema`, `src/utils/settings/types.ts`)
30
-
31
- ### Model & provider
32
- ```jsonc
33
- {
34
- "model": "qwen2.5-coder:7b",
35
- "provider": {
36
- "active": "ollama",
37
- "model": "qwen2.5-coder:7b",
38
- "baseUrl": "http://localhost:11434",
39
- "timeoutMs": 30000,
40
- "fallback": "disabled",
41
- "openaiTransport": "responses", // chat-completions (default) | responses
42
- "responses": {
43
- "store": false,
44
- "compactThreshold": 20000,
45
- "toolSearch": "hosted" // off (default) | hosted
46
- },
47
- "preferences": {}
48
- },
49
- "ollama": { "host": "http://localhost:11434", "lanDiscovery": true },
50
- "offline": false,
51
- "effortLevel": "high",
52
- "fastMode": false, "fastModePerSessionOptIn": false,
53
- "advisorModel": "qwen2.5-coder:32b",
54
- "alwaysThinkingEnabled": false, "showThinkingSummaries": true,
55
- "availableModels": [], "modelOverrides": {}
56
- }
57
- ```
58
-
59
- ### Permissions & safety
60
- ```jsonc
61
- {
62
- "permissions": {
63
- "allow": ["Bash(git:*)", "Read", "WebFetch(domain:docs.example.com)"],
64
- "deny": ["Bash(rm -rf:*)", "mcp__untrusted-server"],
65
- "ask": ["Bash(git push:*)"],
66
- "additionalDirectories": ["../lib"],
67
- "defaultMode": "acceptEdits", // default | plan | acceptEdits | autoApprove | bypassPermissions
68
- "profiles": { // named rule sets, appended when active
69
- "reviewing": { "deny": ["Edit", "Write", "Bash"], "description": "read-only" },
70
- "trusted": { "allow": ["Bash(git:*)"] }
71
- },
72
- "activeProfile": "reviewing" // switch with /permission-profile use <name>
73
- },
74
- "agents": { // subagent fan-out limits (doc 09)
75
- "maxDepth": 3, // default 3, hard ceiling 10
76
- "maxConcurrent": 20 // default 20, hard ceiling 100
77
- },
78
- "voice": { // end-of-turn speech, off by default
79
- "speakResponses": false,
80
- "name": "Samantha", "rate": 210
81
- },
82
- "memory": { // end-of-turn suggestions, off by default
83
- "suggest": false,
84
- "suggestMinConfidence": 0.75
85
- },
86
- "sandbox": { /* SandboxSettingsSchema — OS sandbox for shell commands */ },
87
- "tasks": {
88
- "requireBeforeChanges": {
89
- "enabled": true, // default: true
90
- "freeReads": 3 // calls allowed before ordinary mutations require a plan
91
- }
92
- },
93
- "disableAutoMode": "disable",
94
- "skipDangerousModePermissionPrompt": false,
95
- "allowManagedPermissionRulesOnly": false
96
- }
97
- ```
98
- Profiles are appended to the base `allow`/`deny`/`ask` lists from the same
99
- settings source, so a profile can only narrow or extend — `deny` still beats
100
- `allow`. A missing or misnamed `activeProfile` contributes nothing rather than
101
- failing open. `/permission-profile use <name>` writes the switch to whichever
102
- source defines the profile, so it lands beside its definition.
103
-
104
- Fan-out limits clamp rather than disable: out-of-range, negative and
105
- non-numeric values fall back to the default or the ceiling, so a settings file
106
- cannot switch the governor off.
107
-
108
- ### Global app compaction controls
109
-
110
- `autoCompactEnabled` and `compaction.autoThreshold` are global app controls
111
- managed by `/config` or the `Config` tool and persisted in the global UR
112
- configuration (`~/.ur.json`, or `.config.json` in a legacy UR config home).
113
- They are not keys in the project `settings.json` schema.
114
-
115
- ```text
116
- autoCompactEnabled = true
117
- compaction.autoThreshold = 80
118
- ```
119
-
120
- The threshold accepts an inclusive percentage from 50 through 95. It is
121
- applied to the effective model context window and retains a 3,000-token manual
122
- compaction reserve. `UR_AUTOCOMPACT_PCT_OVERRIDE` has higher precedence for
123
- the current process; `DISABLE_AUTO_COMPACT` or `DISABLE_COMPACT` disables the
124
- proactive trigger. `/context` and the prompt notification report an
125
- approximate percentage left to this same resolved threshold; the active query
126
- may free additional context through bounded pruning immediately before the
127
- trigger.
128
-
129
- Rule syntax: `ToolName` (blanket) or `ToolName(specifier)` — e.g. `Bash(npm run *)`,
130
- `Edit(src/**)`, `mcp__server__tool`. Managed via `/permissions` UI as well.
131
-
132
- Permission modes:
133
- - `default`: normal permission checks; operations that need review ask first.
134
- - `plan`: planning-only mode until the user approves execution.
135
- - `acceptEdits`: auto-approve safe in-workspace file edits and safe commands.
136
- - `autoApprove`: auto-approve command/tool permission approvals, while
137
- user-input dialogs still ask and explicit denials remain enforced.
138
- - `bypassPermissions`: bypass permission prompts after the separate dangerous-mode
139
- acknowledgement/CLI opt-in; use only in an external sandbox with no sensitive access.
140
-
141
- `autoMode`, `useAutoModeDuringPlan`, `skipAutoPermissionPrompt`, and
142
- `permissions.disableAutoMode` exist only in builds compiled with
143
- `TRANSCRIPT_CLASSIFIER`; `classifierPermissionsEnabled` is additionally internal-only.
144
- The standard npm build accepts `autoApprove`, which is deterministic permission approval,
145
- not model-based classification.
146
-
147
- ### Hooks
148
- ```jsonc
149
- {
150
- "hooks": {
151
- "PreToolUse": [
152
- { "matcher": "Bash",
153
- "hooks": [ { "type": "command", "command": "./scripts/lint-command.sh" } ] }
154
- ],
155
- "PostToolUse": [], "UserPromptSubmit": []
156
- },
157
- "disableAllHooks": false,
158
- "allowManagedHooksOnly": false,
159
- "allowedHttpHookUrls": [], "httpHookAllowedEnvVars": []
160
- }
161
- ```
162
- Hook events (`src/entrypoints/sdk/coreTypes.ts:HOOK_EVENTS`): `PreToolUse`, `PostToolUse`,
163
- `PostToolUseFailure`, `Notification`, `UserPromptSubmit`, `SessionStart`, `SessionEnd`,
164
- `Stop`, `StopFailure`, `SubagentStart`, `SubagentStop`, `PreCompact`, `PostCompact`,
165
- `PermissionRequest`, `PermissionDenied`, `Setup`, `TeammateIdle`, `TaskCreated`,
166
- `TaskCompleted`, `Elicitation`, `ElicitationResult`, `ConfigChange`, `WorktreeCreate`,
167
- `WorktreeRemove`, `InstructionsLoaded`, `CwdChanged`, `FileChanged`, `BeforeEdit`,
168
- `AfterEdit`, `BeforeCommand`, `AfterCommand`, `BeforeCommit`, `OnFailure`.
169
- Hook types: `command` (shell), plus prompt/agent hooks (`execPromptHook.ts`,
170
- `execAgentHook.ts` — run a model prompt or subagent as the hook). View with `/hooks`.
171
-
172
- ### MCP policy
173
- ```jsonc
174
- {
175
- "enableAllProjectMcpServers": false,
176
- "enabledMcpjsonServers": [], "disabledMcpjsonServers": [],
177
- "allowedMcpServers": [], "deniedMcpServers": [],
178
- "allowManagedMcpServersOnly": false
179
- }
180
- ```
181
-
182
- Server definitions do not live under `mcpServers` in `settings.json`; configure them through
183
- `ur mcp` / `.mcp.json`. The keys above are approval and enterprise-policy controls.
184
-
185
- ### Git & attribution
186
- ```jsonc
187
- {
188
- "attribution": {
189
- "commit": "Co-authored-by: UR-Nexus <noreply@example.invalid>",
190
- "pr": "Generated with UR-Nexus"
191
- },
192
- "includeCoAuthoredBy": true,
193
- "includeGitInstructions": true
194
- }
195
- ```
196
-
197
- ### UI & terminal
198
- ```jsonc
199
- {
200
- "statusLine": { "type": "command", "command": "./scripts/status.sh", "padding": 1 },
201
- "language": "en",
202
- "spinnerTipsEnabled": true, "spinnerVerbs": { "mode": "append", "verbs": [] },
203
- "spinnerTipsOverride": { "excludeDefault": false, "tips": [] },
204
- "syntaxHighlightingDisabled": false,
205
- "terminalTitleFromRename": true,
206
- "prefersReducedMotion": false,
207
- "outputStyle": "…", // output style name (src/outputStyles)
208
- "promptSuggestionEnabled": true,
209
- "showClearContextOnPlanAccept": true,
210
- "feedbackSurveyRate": 1
211
- }
212
- ```
213
-
214
- `theme` is global application config managed by `/theme`, not a `SettingsSchema` key.
215
-
216
- ### Memory & verification
217
- ```jsonc
218
- {
219
- "autoMemoryEnabled": true, "autoMemoryDirectory": "~/.ur/project-memory",
220
- "autoMemoryExtractionInterval": 1, // run extraction every N turns (token dial)
221
- "automaticLearningEnabled": true, // local outcome stats, no model calls
222
- "verifier": { "askBeforeGates": true }, // one approval request per user turn
223
- "autoDreamEnabled": false,
224
- "plansDirectory": ".ur/plans"
225
- }
226
- ```
227
-
228
- ### Plugins & marketplaces
229
- ```jsonc
230
- {
231
- "enabledPlugins": { "fmt@acme": true },
232
- "pluginConfigs": {},
233
- "extraKnownMarketplaces": {},
234
- "strictKnownMarketplaces": [
235
- { "source": "github", "repo": "acme/approved-plugins" }
236
- ],
237
- "blockedMarketplaces": [],
238
- "strictPluginOnlyCustomization": false
239
- }
240
- ```
241
-
242
- ### Auth, org & misc
243
- ```jsonc
244
- {
245
- "apiKeyHelper": "./get-key.sh",
246
- "awsCredentialExport": "./scripts/aws-env.sh",
247
- "awsAuthRefresh": "./scripts/aws-refresh.sh",
248
- "gcpAuthRefresh": "gcloud auth application-default login",
249
- "forceLoginMethod": "urai",
250
- "forceLoginOrgUUID": "00000000-0000-0000-0000-000000000000",
251
- "otelHeadersHelper": "./scripts/otel-headers.sh",
252
- "env": { "FOO": "bar" }, // extra env for the session
253
- "companyAnnouncements": [],
254
- "remote": { "defaultEnvironmentId": "dev-lab" },
255
- "autoUpdatesChannel": "stable",
256
- "minimumVersion": "1.65.6",
257
- "cleanupPeriodDays": 30,
258
- "fileSuggestion": { "type": "command", "command": "./scripts/files.sh" },
259
- "respectGitignore": true,
260
- "defaultShell": "bash",
261
- "skipWebFetchPreflight": false,
262
- "voiceEnabled": false,
263
- "sshConfigs": [
264
- { "id": "lab", "name": "Lab server", "sshHost": "dev@lab.example" }
265
- ],
266
- "agent": "reviewer" // default agent config
267
- }
268
- ```
269
-
270
- `xaaIdp` is conditional on `UR_CODE_ENABLE_XAA`; when enabled,
271
- `callbackPort` is optional but must be a positive integer. The
272
- `disableDeepLinkRegistration: "disable"` key exists only in LODESTONE builds.
273
- `assistantName` is KAIROS-only. There are no top-level `environment`,
274
- `marketplace`, or `plugin` objects in the standard settings schema.
275
-
276
- ## Supported environment variables
277
-
278
- These tables cover user-facing runtime controls. Platform-detection variables,
279
- CI-provider metadata, test fixtures, and compile-time-only/internal branches
280
- are not presented as supported configuration merely because source code reads
281
- them.
282
-
283
- ### Providers
284
-
285
- | Variable | Effect |
286
- |---|---|
287
- | `OLLAMA_API_KEY` | Bearer token for Ollama's hosted API. With no host set, also switches the base URL to `https://ollama.com` — a local daemon needs no key, a direct connection does. Allowlisted through the Agentic CI env scrub |
288
- | `OLLAMA_HOST` / `OLLAMA_BASE_URL` | Explicit Ollama endpoint; always wins over the key-implied cloud default |
289
- | `OLLAMA_CONTEXT_TOKENS` | Override the detected context window |
290
- | `API_TIMEOUT_MS` | Explicit Ollama request timeout in milliseconds; overrides the model-aware runtime default |
291
- | `UR_API_TIMEOUT_MS` | Default provider HTTP-client timeout where supported |
292
- | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY` | Provider credentials; also allowlisted for Agentic CI |
293
-
294
- ### Core behavior
295
- | Variable | Effect |
296
- |---|---|
297
- | `UR_CODE_SIMPLE=1` | Minimal tool set (Bash/Read/Edit); set by `--bare` |
298
- | `UR_CODE_REMOTE=true` | Remote/CCR container mode (raises heap to 8GB) |
299
- | `UR_CODE_DISABLE_BACKGROUND_TASKS=1` | Remove background mode from the Bash, PowerShell, and Agent tools. It does not disable the separate public `ur bg` command |
300
- | `UR_CODE_DISABLE_AUTO_MEMORY=1` | Disable auto-memory |
301
- | `UR_CODE_DISABLE_COMMAND_INJECTION_CHECK=1` | Skip bash injection analysis (not recommended) |
302
- | `UR_CODE_MAX_OUTPUT_TOKENS` | Cap model output tokens |
303
- | `UR_CODE_MAX_RETRIES` | API retry cap |
304
- | `UR_CODE_EXTRA_BODY` | Extra JSON merged into API requests |
305
- | `UR_CODE_EXPERIMENTAL_AGENT_TEAMS=1` | Opt into agent teams/swarm mode in external builds (also available through hidden `--agent-teams`); the runtime kill-switch still applies |
306
- | `UR_CODE_USE_POWERSHELL_TOOL=1` | Enable the PowerShell tool on Windows |
307
- | `UR_CODE_INDEX=1` | Force-enable the semantic code index + CodeSearch tool; an existing built index enables it automatically, while `0`, `false`, or `off` force-disable it |
308
- | `UR_CODE_ENABLE_TASKS=1` | Use structured TaskCreate/Get/Update/List tools in headless/SDK sessions; interactive sessions use them by default |
309
- | `UR_CODE_MAX_TOOL_USE_CONCURRENCY` | Cap concurrent-safe tools in the ordinary agent loop (default 10, clamped to 1–32) |
310
- | `UR_MAX_CONCURRENT_TOOLS` | Cap concurrent-safe tools in the streaming executor (default 8, clamped to 1–32); set both concurrency variables when one limit is desired across both paths |
311
- | `ENABLE_LSP_TOOL=1` | LSP tool |
312
- | `UR_BROWSER_TOOL=1` / `WEB_BROWSER_TOOL=1` | Enable the model-invocable Browser tool. Its guarded `fetch` action is runtime-independent; interactive actions require `playwright-core` and an installed Chromium/Chrome executable |
313
- | `UR_CODE_SYNTAX_HIGHLIGHT=0` | Disable syntax highlighting |
314
- | `UR_CODE_ACCESSIBILITY=1` | Accessibility rendering |
315
- | `UR_CODE_SHELL_PREFIX` | Prefix every shell command |
316
- | `UR_CODE_TAGS` | Add one opaque `tags` value to analytics environment metadata; it does not tag a conversation for `/resume` |
317
- | `UR_CODE_OVERRIDE_DATE` | Fake "today" (testing) |
318
- | `UR_CODE_DISABLE_AUTO_LEARNING=1` | Disable automatic local pass/fail outcome recording |
319
-
320
- ### Providers & auth
321
- | Variable | Effect |
322
- |---|---|
323
- | `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` / `OPENROUTER_API_KEY` | API-key providers |
324
- | `UR_MODEL_POOL_CHEAP/STRONG/DEFAULT` | Model pools for routing |
325
- | `UR_CODE_OAUTH_TOKEN` / `UR_CODE_OAUTH_REFRESH_TOKEN` / `UR_CODE_OAUTH_SCOPES` | OAuth token injection |
326
- | `UR_CODE_SESSION_ACCESS_TOKEN` | Remote session token |
327
- | `URHQ_DEFAULT_MODELO_MODEL` / `URHQ_DEFAULT_MODELS_MODEL` / `URHQ_DEFAULT_MODELH_MODEL` | Default model tiers (opus/sonnet/haiku-class) |
328
- | `MCP_CLIENT_SECRET` | OAuth client secret for `ur mcp add` |
329
- | `UR_OPENAI_RESPONSES_STATE_KEY` | 32-byte hex/base64 key required to persist encrypted compacted Responses context |
330
-
331
- ### Protocol, skill, and telemetry controls
332
- | Variable | Effect |
333
- |---|---|
334
- | `UR_MCP_HTTP_TOKEN` / `UR_MCP_HTTP_*` | Authenticate and bound the opt-in stateless MCP 2026 Tasks/Apps server |
335
- | `UR_A2A_TOKEN` / `UR_A2A_DELEGATION_SECRET` / `UR_A2A_*` | Authenticate, scope, and bound A2A v0.3/v1 serving |
336
- | `UR_ACP_STDIO_*` | Bound ACP durable sessions, prompts, output, and runtime |
337
- | `UR_SKILLS_STRICT_SPEC=true` | Reject file skills that violate the Agent Skills specification |
338
- | `UR_SKILLS_REQUIRE_TRUSTED_SIGNATURE=true` | Require a trusted Ed25519 skill signature at load and invocation |
339
- | `UR_SKILL_TRUSTED_KEYS_FILE` | Override the trusted **public** skill-key store used to verify signatures |
340
- | `OTEL_TRACES_EXPORTER` / `OTEL_METRICS_EXPORTER` / `OTEL_LOGS_EXPORTER` | Explicitly enable `otlp` or `console`; unset/`none` is off |
341
- | `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true` | Opt into bounded prompt/tool/memory content attributes (off by default) |
342
- | `OTEL_SDK_DISABLED=true` | Disable all OpenTelemetry SDK export |
343
-
344
- ### Internal / build
345
- `USER_TYPE=ant` (internal commands/tools), `IS_DEMO`, `NODE_OPTIONS`,
346
- `COREPACK_ENABLE_AUTO_PIN=0` (forced), `UR_CODE_ENTRYPOINT`, `UR_CODE_WORKER_EPOCH`,
347
- `UR_CODE_ENVIRONMENT_KIND`, `UR_CODE_IS_COWORK`, `UR_CODE_BRIEF`, `UR_CODE_PROACTIVE`,
348
- `UR_CODE_EAGER_FLUSH`, `UR_CODE_STREAMLINED_OUTPUT`, `UR_CODE_DEBUG_REPAINTS`,
349
- `UR_CODE_EXIT_AFTER_FIRST_RENDER`, `UR_CODE_TEST_FIXTURES_ROOT`.
350
-
351
- Names found only in dead feature branches are not runtime switches. In particular,
352
- `UR_CODE_REPL`, `UR_CODE_VERIFY_PLAN`, `UR_CODE_USE_BEDROCK`,
353
- `UR_CODE_USE_VERTEX`, `UR_CODE_DISABLE_CRON`, `UR_CODE_COORDINATOR_MODE`, and
354
- `UR_CODE_ABLATION_BASELINE` do not enable their named backend/tool/mode in the standard
355
- build. The last three are read only inside `AGENT_TRIGGERS`, `COORDINATOR_MODE`, and
356
- `ABLATION_BASELINE` compile-time branches respectively; none of those features is enabled
357
- by `scripts/bundle.mjs`.
358
-
359
- ## Keybindings
360
-
361
- `~/.claude`-style keybindings live at `~/.ur/keybindings.json`; open with `/keybindings`,
362
- get help with `/keybindings-help`. Managed by `src/keybindings/` (chords supported,
363
- global + command-scoped bindings; see `useGlobalKeybindings.tsx` / `useCommandKeybindings.tsx`).
364
-
365
- ## Output styles
366
-
367
- `outputStyle` setting selects a style; custom styles load from an output-styles directory
368
- (`src/outputStyles/loadOutputStylesDir.ts`). `/output-style` is deprecated in favor of
369
- `/config`. Built-in styles (`src/constants/outputStyles.ts`) are Explanatory,
370
- Game Designer, Learning, Concise, JSON-strict (every response a parseable JSON object),
371
- Debug-verbose (hypothesis-driven diagnostics), and Release-notes (changelog tone).
372
-
373
- ## Settings not covered above
374
-
375
- These keys exist in `SettingsSchema` (`src/utils/settings/types.ts`) and were
376
- previously undocumented — the gap that let several releases ship settings no
377
- one could discover. `test/settingsDocCoverage.test.ts` now fails if any schema
378
- key is missing from this file.
379
-
380
- | Key | What it does |
381
- |---|---|
382
- | `$schema` | JSON Schema URL for editor completion in `settings.json`. Not a UR setting; ignored at runtime. |
383
- | `worktree.symlinkDirectories` | Directories symlinked from the main repository into each worktree instead of being copied, to avoid disk bloat. Nothing is symlinked unless listed; `node_modules`, `.cache` and `.bin` are the usual candidates. |
384
- | `worktree.sparsePaths` | Paths to materialize when creating a worktree, via `git sparse-checkout` in cone mode. In a large monorepo only the listed paths are written to disk, which is dramatically faster. |
385
- | `channelsEnabled` | Teams/Enterprise opt-in for channel notifications from MCP servers that declare the capability. Off unless set. |
386
- | `allowedChannelPlugins` | Allow-list of `{ marketplace, plugin }` pairs permitted to deliver channel notifications. Used with `channelsEnabled` to bound which plugins can notify. |
387
- | `urMdExcludes` | Glob patterns or absolute paths of `UR.md` files to skip when loading project memory. Use it to keep vendored or generated `UR.md` files out of context. |
388
- | `pluginTrustMessage` | Extra text appended to the plugin trust warning shown before installation, for organizations that need to state their own policy at that moment. |
389
-
390
- ## Tool-result pruning (`context.pruneToolResults`)
391
-
392
- Superseded tool results — old file reads, greps, shell output — are cleared
393
- from context once doing so would free a worthwhile amount, keeping the most
394
- recent ones untouched.
395
-
396
- | Key | Default | What it does |
397
- |---|---|---|
398
- | `context.pruneToolResults.enabled` | `true` | Master switch. |
399
- | `context.pruneToolResults.minTokensFreed` | `20000` | Prune only when it would free at least this many tokens. Clearing invalidates the cached prefix, so a small cleanup costs more in cache misses than it reclaims; short sessions are never touched. |
400
- | `context.pruneToolResults.keepRecent` | `8` | Protected zone. The most recent N compactable tool results are never cleared, so the model keeps the working set it is reasoning about. Floored at 1. |
401
-
402
- Why it is on by default: the alternative when context fills is autocompact,
403
- which replaces the entire history with a summary. Dropping a superseded file
404
- read is strictly less destructive than losing the conversation.
405
-
406
- Compactable tools are `Read`, shell, `Grep`, `Glob`, `WebSearch`, `WebFetch`,
407
- `Edit` and `Write`. Cleared results are replaced with a marker, not deleted, so
408
- the tool call itself remains visible in the transcript.
409
-
410
- This is separate from the time-based trigger (`tengu_slate_heron`), which fires
411
- only after an hour of idling and is configured through GrowthBook — a service a
412
- local install never reaches, so it is effectively always off.
413
-
414
- ## Memory integrity signing (`UR_MEMORY_INTEGRITY_KEY`)
415
-
416
- Unsigned, the manifest defends against accident and unaware tampering only:
417
- anyone who can write a memory file can also rewrite the manifest to match, and
418
- verification passes. Setting `UR_MEMORY_INTEGRITY_KEY` adds an HMAC over the
419
- file digests, so a forged manifest is detected even when every digest matches
420
- the file beside it.
421
-
422
- Off by default, deliberately. A key has to live somewhere, and a key stored
423
- next to the data it protects adds no security — enable this only when the key
424
- comes from somewhere the memory directory is not (password manager, CI secret).
425
-
426
- `ur memory-integrity verify` exits non-zero on an invalid signature, and also
427
- when a manifest is signed but no key is available: an unverifiable signature is
428
- not a pass.