ur-agent 1.65.6 → 1.65.7
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.
- package/CHANGELOG.md +52 -0
- package/README.md +5 -4
- package/dist/cli.js +5432 -3076
- package/dist/sdk/index.cjs +189 -0
- package/dist/sdk/index.d.ts +68 -0
- package/dist/sdk/index.js +149 -0
- package/docs/VALIDATION.md +1 -1
- package/documentation/app.js +91 -0
- package/documentation/index.html +1 -1
- package/extensions/jetbrains-ur/build.gradle.kts +1 -1
- package/extensions/vscode-ur-inline-diffs/package.json +1 -1
- package/package.json +13 -2
- package/technical/01-architecture.md +146 -0
- package/technical/02-cli-reference.md +227 -0
- package/technical/03-slash-commands.md +318 -0
- package/technical/04-tools.md +119 -0
- package/technical/05-providers-and-models.md +192 -0
- package/technical/06-configuration.md +407 -0
- package/technical/07-memory-and-context.md +147 -0
- package/technical/08-skills-plugins-workflows.md +211 -0
- package/technical/09-multi-agent.md +249 -0
- package/technical/10-headless-automation-eval.md +441 -0
- package/technical/11-integrations.md +156 -0
- package/technical/12-security-sandbox-stability.md +271 -0
- package/technical/13-research.md +129 -0
- package/technical/14-sessions.md +177 -0
- package/technical/README.md +43 -0
|
@@ -0,0 +1,192 @@
|
|
|
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. `:cloud` models and remote sessions
|
|
115
|
+
use 120 seconds; local models use 300 seconds. The same model-aware value is
|
|
116
|
+
applied while waiting for `/api/chat` response headers and as the absolute
|
|
117
|
+
deadline in `readOllamaChunks`.
|
|
118
|
+
- `ur.ts` identifies an Ollama Cloud runtime from both the selected provider and
|
|
119
|
+
the `:cloud` suffix. It disables shared automatic request retries for that
|
|
120
|
+
route, applies the same 120-second bound to any permitted non-streaming
|
|
121
|
+
fallback, and skips fallback entirely when the Ollama stream deadline itself
|
|
122
|
+
caused the failure. Explicit `API_TIMEOUT_MS` remains authoritative.
|
|
123
|
+
|
|
124
|
+
## Capability-aware routing
|
|
125
|
+
|
|
126
|
+
### Model pools (`src/services/agents/modelPool.ts`)
|
|
127
|
+
Pools named `cheap` / `strong` / `default`, loaded in priority order:
|
|
128
|
+
1. `.ur/model-pool.json` in the repo — e.g. `{"cheap":["gemma2:2b"],"strong":["gpt-5.5"]}`
|
|
129
|
+
2. Env: `UR_MODEL_POOL_CHEAP`, `UR_MODEL_POOL_STRONG`, `UR_MODEL_POOL_DEFAULT` (comma lists)
|
|
130
|
+
3. Defaults: cheap `qwen2.5-coder:1.5b, gemma2:2b`; strong `qwen2.5-coder:32b, codex,
|
|
131
|
+
claude-3-5-sonnet, gpt-4o`; default `qwen2.5-coder`.
|
|
132
|
+
|
|
133
|
+
### `/model-route` (modelRouter.ts)
|
|
134
|
+
Classifies a task and recommends a model + strategy:
|
|
135
|
+
```
|
|
136
|
+
/model-route "port this service to Rust" --strategy strong
|
|
137
|
+
/model-route "rename a variable" --strategy auto --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `/escalate` (escalation.ts)
|
|
141
|
+
Run on a fast model, auto-escalate hard steps to an "oracle":
|
|
142
|
+
```
|
|
143
|
+
/escalate plan "design a consensus protocol" # show the split
|
|
144
|
+
/escalate run "…" --fast qwen2.5-coder:7b --oracle gpt-5.5
|
|
145
|
+
/escalate policy # view escalation policy
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `/model-doctor` (ollamaModels.ts + modelCapabilities.ts)
|
|
149
|
+
Probes an installed Ollama model: tool-call support, context length, speed class, and
|
|
150
|
+
reports "likely agent capabilities":
|
|
151
|
+
```
|
|
152
|
+
/model-doctor llama3.3 --json
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Automatic learning loop (learning.ts)
|
|
156
|
+
Every ci-loop, arena, escalation, test-first, and completed **local** cloud
|
|
157
|
+
best-of-N run
|
|
158
|
+
**automatically** records its pass/fail outcome (per task category and model) into
|
|
159
|
+
`.ur/learning/stats.json` — a pure JSON fold, no model calls. The `auto` routing strategy
|
|
160
|
+
and `/escalate`'s difficulty bias consume this evidence: a model with ≥3 recorded runs and
|
|
161
|
+
a ≥60% success rate for the task's category is preferred when selectable; thin evidence
|
|
162
|
+
falls back to the static heuristics unchanged. The store is idempotent (outcome keys
|
|
163
|
+
dedupe) and best-effort (a broken store never fails a run). `/learn` remains for
|
|
164
|
+
inspection and the optional LLM reflection pass:
|
|
165
|
+
```
|
|
166
|
+
/learn stats # view what the agent has learned
|
|
167
|
+
/learn run --reflect # optional: distill failures into lessons (uses a model)
|
|
168
|
+
```
|
|
169
|
+
Disable automatic learning with `automaticLearningEnabled: false` or
|
|
170
|
+
`UR_CODE_DISABLE_AUTO_LEARNING=1`.
|
|
171
|
+
|
|
172
|
+
## Session behavior knobs
|
|
173
|
+
|
|
174
|
+
| Feature | Command | Notes |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| 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 |
|
|
177
|
+
| 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 |
|
|
178
|
+
| 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 |
|
|
179
|
+
| Always thinking | `alwaysThinkingEnabled` setting | force extended thinking |
|
|
180
|
+
| Thinking summaries | `showThinkingSummaries` setting | UI display of thinking |
|
|
181
|
+
| Fallback model | `--fallback-model` (print mode) | on overload |
|
|
182
|
+
|
|
183
|
+
## Offline / local-first
|
|
184
|
+
|
|
185
|
+
- `ur --offline` or `offline` setting: no cloud APIs, telemetry, auto-update, remote control.
|
|
186
|
+
- Offline dispatch permits only loopback local/server endpoints; cloud,
|
|
187
|
+
subscription, remote Ollama, and remote compatible endpoints are blocked.
|
|
188
|
+
- `/local-first` reports readiness for no-cloud/private/lab/edge deployment: which features
|
|
189
|
+
degrade, which local deps (Ollama, ripgrep, playwright, ffmpeg…) are present.
|
|
190
|
+
- `--bare` forces the minimal local pipeline (`UR_CODE_SIMPLE=1`) and always uses Ollama.
|
|
191
|
+
- Ollama config: `ollama.host` and `ollama.lanDiscovery` settings; per-session
|
|
192
|
+
`--ollama-host`; router in `ollamaRouter.ts` load-balances across discovered hosts.
|
|
@@ -0,0 +1,407 @@
|
|
|
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
|
+
Rule syntax: `ToolName` (blanket) or `ToolName(specifier)` — e.g. `Bash(npm run *)`,
|
|
109
|
+
`Edit(src/**)`, `mcp__server__tool`. Managed via `/permissions` UI as well.
|
|
110
|
+
|
|
111
|
+
Permission modes:
|
|
112
|
+
- `default`: normal permission checks; operations that need review ask first.
|
|
113
|
+
- `plan`: planning-only mode until the user approves execution.
|
|
114
|
+
- `acceptEdits`: auto-approve safe in-workspace file edits and safe commands.
|
|
115
|
+
- `autoApprove`: auto-approve command/tool permission approvals, while
|
|
116
|
+
user-input dialogs still ask and explicit denials remain enforced.
|
|
117
|
+
- `bypassPermissions`: bypass permission prompts after the separate dangerous-mode
|
|
118
|
+
acknowledgement/CLI opt-in; use only in an external sandbox with no sensitive access.
|
|
119
|
+
|
|
120
|
+
`autoMode`, `useAutoModeDuringPlan`, `skipAutoPermissionPrompt`, and
|
|
121
|
+
`permissions.disableAutoMode` exist only in builds compiled with
|
|
122
|
+
`TRANSCRIPT_CLASSIFIER`; `classifierPermissionsEnabled` is additionally internal-only.
|
|
123
|
+
The standard npm build accepts `autoApprove`, which is deterministic permission approval,
|
|
124
|
+
not model-based classification.
|
|
125
|
+
|
|
126
|
+
### Hooks
|
|
127
|
+
```jsonc
|
|
128
|
+
{
|
|
129
|
+
"hooks": {
|
|
130
|
+
"PreToolUse": [
|
|
131
|
+
{ "matcher": "Bash",
|
|
132
|
+
"hooks": [ { "type": "command", "command": "./scripts/lint-command.sh" } ] }
|
|
133
|
+
],
|
|
134
|
+
"PostToolUse": [], "UserPromptSubmit": []
|
|
135
|
+
},
|
|
136
|
+
"disableAllHooks": false,
|
|
137
|
+
"allowManagedHooksOnly": false,
|
|
138
|
+
"allowedHttpHookUrls": [], "httpHookAllowedEnvVars": []
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
Hook events (`src/entrypoints/sdk/coreTypes.ts:HOOK_EVENTS`): `PreToolUse`, `PostToolUse`,
|
|
142
|
+
`PostToolUseFailure`, `Notification`, `UserPromptSubmit`, `SessionStart`, `SessionEnd`,
|
|
143
|
+
`Stop`, `StopFailure`, `SubagentStart`, `SubagentStop`, `PreCompact`, `PostCompact`,
|
|
144
|
+
`PermissionRequest`, `PermissionDenied`, `Setup`, `TeammateIdle`, `TaskCreated`,
|
|
145
|
+
`TaskCompleted`, `Elicitation`, `ElicitationResult`, `ConfigChange`, `WorktreeCreate`,
|
|
146
|
+
`WorktreeRemove`, `InstructionsLoaded`, `CwdChanged`, `FileChanged`, `BeforeEdit`,
|
|
147
|
+
`AfterEdit`, `BeforeCommand`, `AfterCommand`, `BeforeCommit`, `OnFailure`.
|
|
148
|
+
Hook types: `command` (shell), plus prompt/agent hooks (`execPromptHook.ts`,
|
|
149
|
+
`execAgentHook.ts` — run a model prompt or subagent as the hook). View with `/hooks`.
|
|
150
|
+
|
|
151
|
+
### MCP policy
|
|
152
|
+
```jsonc
|
|
153
|
+
{
|
|
154
|
+
"enableAllProjectMcpServers": false,
|
|
155
|
+
"enabledMcpjsonServers": [], "disabledMcpjsonServers": [],
|
|
156
|
+
"allowedMcpServers": [], "deniedMcpServers": [],
|
|
157
|
+
"allowManagedMcpServersOnly": false
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Server definitions do not live under `mcpServers` in `settings.json`; configure them through
|
|
162
|
+
`ur mcp` / `.mcp.json`. The keys above are approval and enterprise-policy controls.
|
|
163
|
+
|
|
164
|
+
### Git & attribution
|
|
165
|
+
```jsonc
|
|
166
|
+
{
|
|
167
|
+
"attribution": {
|
|
168
|
+
"commit": "Co-authored-by: UR-Nexus <noreply@example.invalid>",
|
|
169
|
+
"pr": "Generated with UR-Nexus"
|
|
170
|
+
},
|
|
171
|
+
"includeCoAuthoredBy": true,
|
|
172
|
+
"includeGitInstructions": true
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### UI & terminal
|
|
177
|
+
```jsonc
|
|
178
|
+
{
|
|
179
|
+
"statusLine": { "type": "command", "command": "./scripts/status.sh", "padding": 1 },
|
|
180
|
+
"language": "en",
|
|
181
|
+
"spinnerTipsEnabled": true, "spinnerVerbs": { "mode": "append", "verbs": [] },
|
|
182
|
+
"spinnerTipsOverride": { "excludeDefault": false, "tips": [] },
|
|
183
|
+
"syntaxHighlightingDisabled": false,
|
|
184
|
+
"terminalTitleFromRename": true,
|
|
185
|
+
"prefersReducedMotion": false,
|
|
186
|
+
"outputStyle": "…", // output style name (src/outputStyles)
|
|
187
|
+
"promptSuggestionEnabled": true,
|
|
188
|
+
"showClearContextOnPlanAccept": true,
|
|
189
|
+
"feedbackSurveyRate": 1
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`theme` is global application config managed by `/theme`, not a `SettingsSchema` key.
|
|
194
|
+
|
|
195
|
+
### Memory & verification
|
|
196
|
+
```jsonc
|
|
197
|
+
{
|
|
198
|
+
"autoMemoryEnabled": true, "autoMemoryDirectory": "~/.ur/project-memory",
|
|
199
|
+
"autoMemoryExtractionInterval": 1, // run extraction every N turns (token dial)
|
|
200
|
+
"automaticLearningEnabled": true, // local outcome stats, no model calls
|
|
201
|
+
"verifier": { "askBeforeGates": true }, // one approval request per user turn
|
|
202
|
+
"autoDreamEnabled": false,
|
|
203
|
+
"plansDirectory": ".ur/plans"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Plugins & marketplaces
|
|
208
|
+
```jsonc
|
|
209
|
+
{
|
|
210
|
+
"enabledPlugins": { "fmt@acme": true },
|
|
211
|
+
"pluginConfigs": {},
|
|
212
|
+
"extraKnownMarketplaces": {},
|
|
213
|
+
"strictKnownMarketplaces": [
|
|
214
|
+
{ "source": "github", "repo": "acme/approved-plugins" }
|
|
215
|
+
],
|
|
216
|
+
"blockedMarketplaces": [],
|
|
217
|
+
"strictPluginOnlyCustomization": false
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Auth, org & misc
|
|
222
|
+
```jsonc
|
|
223
|
+
{
|
|
224
|
+
"apiKeyHelper": "./get-key.sh",
|
|
225
|
+
"awsCredentialExport": "./scripts/aws-env.sh",
|
|
226
|
+
"awsAuthRefresh": "./scripts/aws-refresh.sh",
|
|
227
|
+
"gcpAuthRefresh": "gcloud auth application-default login",
|
|
228
|
+
"forceLoginMethod": "urai",
|
|
229
|
+
"forceLoginOrgUUID": "00000000-0000-0000-0000-000000000000",
|
|
230
|
+
"otelHeadersHelper": "./scripts/otel-headers.sh",
|
|
231
|
+
"env": { "FOO": "bar" }, // extra env for the session
|
|
232
|
+
"companyAnnouncements": [],
|
|
233
|
+
"remote": { "defaultEnvironmentId": "dev-lab" },
|
|
234
|
+
"autoUpdatesChannel": "stable",
|
|
235
|
+
"minimumVersion": "1.65.6",
|
|
236
|
+
"cleanupPeriodDays": 30,
|
|
237
|
+
"fileSuggestion": { "type": "command", "command": "./scripts/files.sh" },
|
|
238
|
+
"respectGitignore": true,
|
|
239
|
+
"defaultShell": "bash",
|
|
240
|
+
"skipWebFetchPreflight": false,
|
|
241
|
+
"voiceEnabled": false,
|
|
242
|
+
"sshConfigs": [
|
|
243
|
+
{ "id": "lab", "name": "Lab server", "sshHost": "dev@lab.example" }
|
|
244
|
+
],
|
|
245
|
+
"agent": "reviewer" // default agent config
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
`xaaIdp` is conditional on `UR_CODE_ENABLE_XAA`; when enabled,
|
|
250
|
+
`callbackPort` is optional but must be a positive integer. The
|
|
251
|
+
`disableDeepLinkRegistration: "disable"` key exists only in LODESTONE builds.
|
|
252
|
+
`assistantName` is KAIROS-only. There are no top-level `environment`,
|
|
253
|
+
`marketplace`, or `plugin` objects in the standard settings schema.
|
|
254
|
+
|
|
255
|
+
## Supported environment variables
|
|
256
|
+
|
|
257
|
+
These tables cover user-facing runtime controls. Platform-detection variables,
|
|
258
|
+
CI-provider metadata, test fixtures, and compile-time-only/internal branches
|
|
259
|
+
are not presented as supported configuration merely because source code reads
|
|
260
|
+
them.
|
|
261
|
+
|
|
262
|
+
### Providers
|
|
263
|
+
|
|
264
|
+
| Variable | Effect |
|
|
265
|
+
|---|---|
|
|
266
|
+
| `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 |
|
|
267
|
+
| `OLLAMA_HOST` / `OLLAMA_BASE_URL` | Explicit Ollama endpoint; always wins over the key-implied cloud default |
|
|
268
|
+
| `OLLAMA_CONTEXT_TOKENS` | Override the detected context window |
|
|
269
|
+
| `API_TIMEOUT_MS` | Explicit Ollama request timeout in milliseconds; overrides the model-aware runtime default |
|
|
270
|
+
| `UR_API_TIMEOUT_MS` | Default provider HTTP-client timeout where supported |
|
|
271
|
+
| `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY` | Provider credentials; also allowlisted for Agentic CI |
|
|
272
|
+
|
|
273
|
+
### Core behavior
|
|
274
|
+
| Variable | Effect |
|
|
275
|
+
|---|---|
|
|
276
|
+
| `UR_CODE_SIMPLE=1` | Minimal tool set (Bash/Read/Edit); set by `--bare` |
|
|
277
|
+
| `UR_CODE_REMOTE=true` | Remote/CCR container mode (raises heap to 8GB) |
|
|
278
|
+
| `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 |
|
|
279
|
+
| `UR_CODE_DISABLE_AUTO_MEMORY=1` | Disable auto-memory |
|
|
280
|
+
| `UR_CODE_DISABLE_COMMAND_INJECTION_CHECK=1` | Skip bash injection analysis (not recommended) |
|
|
281
|
+
| `UR_CODE_MAX_OUTPUT_TOKENS` | Cap model output tokens |
|
|
282
|
+
| `UR_CODE_MAX_RETRIES` | API retry cap |
|
|
283
|
+
| `UR_CODE_EXTRA_BODY` | Extra JSON merged into API requests |
|
|
284
|
+
| `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 |
|
|
285
|
+
| `UR_CODE_USE_POWERSHELL_TOOL=1` | Enable the PowerShell tool on Windows |
|
|
286
|
+
| `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 |
|
|
287
|
+
| `UR_CODE_ENABLE_TASKS=1` | Use structured TaskCreate/Get/Update/List tools in headless/SDK sessions; interactive sessions use them by default |
|
|
288
|
+
| `UR_CODE_MAX_TOOL_USE_CONCURRENCY` | Cap concurrent-safe tools in the ordinary agent loop (default 10, clamped to 1–32) |
|
|
289
|
+
| `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 |
|
|
290
|
+
| `ENABLE_LSP_TOOL=1` | LSP tool |
|
|
291
|
+
| `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 |
|
|
292
|
+
| `UR_CODE_SYNTAX_HIGHLIGHT=0` | Disable syntax highlighting |
|
|
293
|
+
| `UR_CODE_ACCESSIBILITY=1` | Accessibility rendering |
|
|
294
|
+
| `UR_CODE_SHELL_PREFIX` | Prefix every shell command |
|
|
295
|
+
| `UR_CODE_TAGS` | Add one opaque `tags` value to analytics environment metadata; it does not tag a conversation for `/resume` |
|
|
296
|
+
| `UR_CODE_OVERRIDE_DATE` | Fake "today" (testing) |
|
|
297
|
+
| `UR_CODE_DISABLE_AUTO_LEARNING=1` | Disable automatic local pass/fail outcome recording |
|
|
298
|
+
|
|
299
|
+
### Providers & auth
|
|
300
|
+
| Variable | Effect |
|
|
301
|
+
|---|---|
|
|
302
|
+
| `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` / `OPENROUTER_API_KEY` | API-key providers |
|
|
303
|
+
| `UR_MODEL_POOL_CHEAP/STRONG/DEFAULT` | Model pools for routing |
|
|
304
|
+
| `UR_CODE_OAUTH_TOKEN` / `UR_CODE_OAUTH_REFRESH_TOKEN` / `UR_CODE_OAUTH_SCOPES` | OAuth token injection |
|
|
305
|
+
| `UR_CODE_SESSION_ACCESS_TOKEN` | Remote session token |
|
|
306
|
+
| `URHQ_DEFAULT_MODELO_MODEL` / `URHQ_DEFAULT_MODELS_MODEL` / `URHQ_DEFAULT_MODELH_MODEL` | Default model tiers (opus/sonnet/haiku-class) |
|
|
307
|
+
| `MCP_CLIENT_SECRET` | OAuth client secret for `ur mcp add` |
|
|
308
|
+
| `UR_OPENAI_RESPONSES_STATE_KEY` | 32-byte hex/base64 key required to persist encrypted compacted Responses context |
|
|
309
|
+
|
|
310
|
+
### Protocol, skill, and telemetry controls
|
|
311
|
+
| Variable | Effect |
|
|
312
|
+
|---|---|
|
|
313
|
+
| `UR_MCP_HTTP_TOKEN` / `UR_MCP_HTTP_*` | Authenticate and bound the opt-in stateless MCP 2026 Tasks/Apps server |
|
|
314
|
+
| `UR_A2A_TOKEN` / `UR_A2A_DELEGATION_SECRET` / `UR_A2A_*` | Authenticate, scope, and bound A2A v0.3/v1 serving |
|
|
315
|
+
| `UR_ACP_STDIO_*` | Bound ACP durable sessions, prompts, output, and runtime |
|
|
316
|
+
| `UR_SKILLS_STRICT_SPEC=true` | Reject file skills that violate the Agent Skills specification |
|
|
317
|
+
| `UR_SKILLS_REQUIRE_TRUSTED_SIGNATURE=true` | Require a trusted Ed25519 skill signature at load and invocation |
|
|
318
|
+
| `UR_SKILL_TRUSTED_KEYS_FILE` | Override the trusted **public** skill-key store used to verify signatures |
|
|
319
|
+
| `OTEL_TRACES_EXPORTER` / `OTEL_METRICS_EXPORTER` / `OTEL_LOGS_EXPORTER` | Explicitly enable `otlp` or `console`; unset/`none` is off |
|
|
320
|
+
| `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true` | Opt into bounded prompt/tool/memory content attributes (off by default) |
|
|
321
|
+
| `OTEL_SDK_DISABLED=true` | Disable all OpenTelemetry SDK export |
|
|
322
|
+
|
|
323
|
+
### Internal / build
|
|
324
|
+
`USER_TYPE=ant` (internal commands/tools), `IS_DEMO`, `NODE_OPTIONS`,
|
|
325
|
+
`COREPACK_ENABLE_AUTO_PIN=0` (forced), `UR_CODE_ENTRYPOINT`, `UR_CODE_WORKER_EPOCH`,
|
|
326
|
+
`UR_CODE_ENVIRONMENT_KIND`, `UR_CODE_IS_COWORK`, `UR_CODE_BRIEF`, `UR_CODE_PROACTIVE`,
|
|
327
|
+
`UR_CODE_EAGER_FLUSH`, `UR_CODE_STREAMLINED_OUTPUT`, `UR_CODE_DEBUG_REPAINTS`,
|
|
328
|
+
`UR_CODE_EXIT_AFTER_FIRST_RENDER`, `UR_CODE_TEST_FIXTURES_ROOT`.
|
|
329
|
+
|
|
330
|
+
Names found only in dead feature branches are not runtime switches. In particular,
|
|
331
|
+
`UR_CODE_REPL`, `UR_CODE_VERIFY_PLAN`, `UR_CODE_USE_BEDROCK`,
|
|
332
|
+
`UR_CODE_USE_VERTEX`, `UR_CODE_DISABLE_CRON`, `UR_CODE_COORDINATOR_MODE`, and
|
|
333
|
+
`UR_CODE_ABLATION_BASELINE` do not enable their named backend/tool/mode in the standard
|
|
334
|
+
build. The last three are read only inside `AGENT_TRIGGERS`, `COORDINATOR_MODE`, and
|
|
335
|
+
`ABLATION_BASELINE` compile-time branches respectively; none of those features is enabled
|
|
336
|
+
by `scripts/bundle.mjs`.
|
|
337
|
+
|
|
338
|
+
## Keybindings
|
|
339
|
+
|
|
340
|
+
`~/.claude`-style keybindings live at `~/.ur/keybindings.json`; open with `/keybindings`,
|
|
341
|
+
get help with `/keybindings-help`. Managed by `src/keybindings/` (chords supported,
|
|
342
|
+
global + command-scoped bindings; see `useGlobalKeybindings.tsx` / `useCommandKeybindings.tsx`).
|
|
343
|
+
|
|
344
|
+
## Output styles
|
|
345
|
+
|
|
346
|
+
`outputStyle` setting selects a style; custom styles load from an output-styles directory
|
|
347
|
+
(`src/outputStyles/loadOutputStylesDir.ts`). `/output-style` is deprecated in favor of
|
|
348
|
+
`/config`. Built-in styles (`src/constants/outputStyles.ts`) are Explanatory,
|
|
349
|
+
Game Designer, Learning, Concise, JSON-strict (every response a parseable JSON object),
|
|
350
|
+
Debug-verbose (hypothesis-driven diagnostics), and Release-notes (changelog tone).
|
|
351
|
+
|
|
352
|
+
## Settings not covered above
|
|
353
|
+
|
|
354
|
+
These keys exist in `SettingsSchema` (`src/utils/settings/types.ts`) and were
|
|
355
|
+
previously undocumented — the gap that let several releases ship settings no
|
|
356
|
+
one could discover. `test/settingsDocCoverage.test.ts` now fails if any schema
|
|
357
|
+
key is missing from this file.
|
|
358
|
+
|
|
359
|
+
| Key | What it does |
|
|
360
|
+
|---|---|
|
|
361
|
+
| `$schema` | JSON Schema URL for editor completion in `settings.json`. Not a UR setting; ignored at runtime. |
|
|
362
|
+
| `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. |
|
|
363
|
+
| `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. |
|
|
364
|
+
| `channelsEnabled` | Teams/Enterprise opt-in for channel notifications from MCP servers that declare the capability. Off unless set. |
|
|
365
|
+
| `allowedChannelPlugins` | Allow-list of `{ marketplace, plugin }` pairs permitted to deliver channel notifications. Used with `channelsEnabled` to bound which plugins can notify. |
|
|
366
|
+
| `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. |
|
|
367
|
+
| `pluginTrustMessage` | Extra text appended to the plugin trust warning shown before installation, for organizations that need to state their own policy at that moment. |
|
|
368
|
+
|
|
369
|
+
## Tool-result pruning (`context.pruneToolResults`)
|
|
370
|
+
|
|
371
|
+
Superseded tool results — old file reads, greps, shell output — are cleared
|
|
372
|
+
from context once doing so would free a worthwhile amount, keeping the most
|
|
373
|
+
recent ones untouched.
|
|
374
|
+
|
|
375
|
+
| Key | Default | What it does |
|
|
376
|
+
|---|---|---|
|
|
377
|
+
| `context.pruneToolResults.enabled` | `true` | Master switch. |
|
|
378
|
+
| `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. |
|
|
379
|
+
| `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. |
|
|
380
|
+
|
|
381
|
+
Why it is on by default: the alternative when context fills is autocompact,
|
|
382
|
+
which replaces the entire history with a summary. Dropping a superseded file
|
|
383
|
+
read is strictly less destructive than losing the conversation.
|
|
384
|
+
|
|
385
|
+
Compactable tools are `Read`, shell, `Grep`, `Glob`, `WebSearch`, `WebFetch`,
|
|
386
|
+
`Edit` and `Write`. Cleared results are replaced with a marker, not deleted, so
|
|
387
|
+
the tool call itself remains visible in the transcript.
|
|
388
|
+
|
|
389
|
+
This is separate from the time-based trigger (`tengu_slate_heron`), which fires
|
|
390
|
+
only after an hour of idling and is configured through GrowthBook — a service a
|
|
391
|
+
local install never reaches, so it is effectively always off.
|
|
392
|
+
|
|
393
|
+
## Memory integrity signing (`UR_MEMORY_INTEGRITY_KEY`)
|
|
394
|
+
|
|
395
|
+
Unsigned, the manifest defends against accident and unaware tampering only:
|
|
396
|
+
anyone who can write a memory file can also rewrite the manifest to match, and
|
|
397
|
+
verification passes. Setting `UR_MEMORY_INTEGRITY_KEY` adds an HMAC over the
|
|
398
|
+
file digests, so a forged manifest is detected even when every digest matches
|
|
399
|
+
the file beside it.
|
|
400
|
+
|
|
401
|
+
Off by default, deliberately. A key has to live somewhere, and a key stored
|
|
402
|
+
next to the data it protects adds no security — enable this only when the key
|
|
403
|
+
comes from somewhere the memory directory is not (password manager, CI secret).
|
|
404
|
+
|
|
405
|
+
`ur memory-integrity verify` exits non-zero on an invalid signature, and also
|
|
406
|
+
when a manifest is signed but no key is available: an unverifiable signature is
|
|
407
|
+
not a pass.
|