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.
@@ -0,0 +1,271 @@
1
+ # 12 — Security, Sandbox & Stability
2
+
3
+ Source of truth: `src/utils/permissions/`, `src/utils/sandbox/`,
4
+ `src/entrypoints/sandboxTypes.ts`, `src/services/safety/projectSafety.ts`,
5
+ `src/security/`, `src/services/guardrails/guardrails.ts`, `src/stability/`,
6
+ `src/services/verifier/`, and `src/services/tools/toolHooks.ts`.
7
+
8
+ This chapter distinguishes an **enforced runtime boundary** from an
9
+ **inspection/advisory helper**. A command that can scan, classify, or print a
10
+ warning is not described as blocking ordinary agent execution unless it is
11
+ actually wired into that execution path.
12
+
13
+ ## Permission engine — enforced
14
+
15
+ Every enabled tool call passes through the permission engine. Rules are loaded
16
+ from `permissions.allow`, `permissions.ask`, and `permissions.deny`, the
17
+ `--allowed-tools`/`--disallowed-tools` flags, session decisions, and managed
18
+ policy. Rule syntax is `Tool` or `Tool(specifier)`, for example
19
+ `Bash(git:*)`, `Edit(src/**)`, or `mcp__server__tool`.
20
+
21
+ User-addressable modes are:
22
+
23
+ | Mode | Runtime behavior |
24
+ |---|---|
25
+ | `default` | Honor explicit rules and ask for undecided operations. |
26
+ | `plan` | Restrict mutation while planning. |
27
+ | `acceptEdits` | Auto-accept the supported edit path while retaining other checks. |
28
+ | `autoApprove` | Convert ordinary approval prompts to allow, except tools that require user interaction. Explicit deny rules and earlier safety checks still apply. |
29
+ | `bypassPermissions` | Broad bypass mode, but explicit ask rules and safety-check decisions that are marked bypass-immune can still prompt. Org/settings kill switches can disable the mode. |
30
+
31
+ `--dangerously-skip-permissions` selects bypass mode;
32
+ `--allow-dangerously-skip-permissions` makes that mode available to the
33
+ interactive selector. Managed settings can restrict permission rules, hooks,
34
+ and MCP servers to managed sources.
35
+
36
+ The normal external build does **not** enable the `TRANSCRIPT_CLASSIFIER`
37
+ feature. Its AI-classified `auto` mode is therefore source-only. The accepted
38
+ `permissions.classifierPermissionsEnabled` schema field is not read by a
39
+ shipped enforcement path and must not be treated as an active control.
40
+
41
+ Bash adds command parsing, command-injection checks, dangerous-pattern
42
+ classification, project safety policy, path validation, and sandbox-aware
43
+ permission decisions. `UR_CODE_DISABLE_COMMAND_INJECTION_CHECK` weakens one of
44
+ those checks and is not a safe default.
45
+
46
+ ## OS sandbox — enforced when enabled and available
47
+
48
+ Set `sandbox.enabled` in settings to request OS-level Bash isolation. macOS uses
49
+ `/usr/bin/sandbox-exec`; Linux/WSL uses `bwrap`; Windows is unsupported. With
50
+ `sandbox.failIfUnavailable: false` (the default), an unavailable sandbox warns
51
+ and may run commands unsandboxed subject to permissions. Set
52
+ `failIfUnavailable: true` for a startup hard failure. The
53
+ `allowUnsandboxedCommands` policy controls whether a tool call may explicitly
54
+ request an unsandboxed run.
55
+
56
+ ```text
57
+ /sandbox status
58
+ /sandbox check
59
+ /sandbox init
60
+ /sandbox eval "curl https://example.com" --json
61
+ /sandbox exclude "npm run test:*"
62
+ ```
63
+
64
+ The command surface is easy to misread:
65
+
66
+ - `status` and `check` inspect support/configuration.
67
+ - `init` writes `.ur/safety-policy.json`; it does **not** write or enable an OS
68
+ sandbox configuration.
69
+ - `eval` classifies a shell string through the project safety policy. It does
70
+ not execute the command.
71
+ - `/sandbox exclude "<pattern>"` is an interactive slash-command action. It
72
+ appends a non-duplicate pattern to `sandbox.excludedCommands` in the
73
+ project-local `.ur/settings.local.json`; the shell form `ur sandbox exclude`
74
+ is not implemented by the separate non-interactive command.
75
+ - An excluded match skips the OS sandbox for the entire Bash tool call. This is
76
+ a convenience exception, not a security boundary: it weakens isolation and
77
+ matching is heuristic. A compound call is excluded only when **every**
78
+ non-empty executable subcommand matches an exclusion; one unmatched segment
79
+ or a parse failure keeps the whole call sandboxed. Normal Bash permission
80
+ and safety-policy checks still apply:
81
+ exclusion does not itself grant tool permission.
82
+
83
+ Filesystem settings are merged with permission-derived paths. Existing parents
84
+ are canonicalized, sensitive UR/settings/skill paths are made non-writable, and
85
+ a sandbox-created bare-repository signature is scrubbed only when all required
86
+ signature paths appeared after the command.
87
+
88
+ Selective network-domain enforcement is not implemented by the compatibility
89
+ runtime. If allowed/denied domain lists are present, it fails closed by blocking
90
+ network for the sandboxed process instead of pretending to enforce host-level
91
+ filtering.
92
+
93
+ ### Deny-default helper versus active profile
94
+
95
+ `buildSeatbeltProfile()` has a source-level `denyByDefault` option and also uses
96
+ a `(deny default)` profile when `allowRead` is non-empty. However,
97
+ `denyByDefault` is not part of `SandboxSettingsSchema`, and the shipped runtime
98
+ adapter does not pass it. With no `allowRead`, the macOS compatibility profile
99
+ uses `(allow default)` plus write/network/targeted denials. Therefore
100
+ `denyByDefault` is a tested builder capability, not a selectable shipped
101
+ setting. Linux `bwrap` separately mounts `/` read-only when no read allow-list
102
+ is supplied.
103
+
104
+ ## Project shell safety policy — enforced for Bash
105
+
106
+ `.ur/safety-policy.json` classifies commands as read-only, project edits, safe
107
+ local commands, network operations, or destructive operations. Bash permission
108
+ checks consume this evaluation.
109
+
110
+ ```text
111
+ /safety status
112
+ /safety init
113
+ /safety check --command "rm -rf build" --json
114
+ ```
115
+
116
+ ## Untrusted-content framing — enforced on three channels
117
+
118
+ `src/security/promptInjection.ts` provides deterministic detection and framing,
119
+ not a proof that prompt injection is impossible.
120
+
121
+ | Function | What it does |
122
+ |---|---|
123
+ | `scanForInjection(text)` | Detects seven instruction/exfiltration/boundary patterns plus hidden Unicode and reports a score. |
124
+ | `stripHiddenCharacters(text)` | Removes zero-width and bidirectional control characters. |
125
+ | `wrapUntrusted(text, source)` | Adds a random 128-bit nonce boundary, warning labels, and an in-memory source-ledger record. |
126
+ | `makeCanary()` / `canaryLeaked()` | Standalone canary helpers. |
127
+
128
+ The shipped automatic wrappers are exactly:
129
+
130
+ - `WebFetch` textual results;
131
+ - `WebSearch` formatted results (its citation reminder stays outside the data
132
+ boundary); and
133
+ - textual MCP tool-result blocks, except a tool explicitly marked as a trusted
134
+ control channel.
135
+
136
+ Local file reads, GitHub tool results, arbitrary user text, and every other
137
+ tool result do not pass through this wrapper merely because the module comment
138
+ mentions those threat classes. `makeCanary()` and `canaryLeaked()` are exported
139
+ helpers but are not installed in the main query/tool loop. `/sources` exposes
140
+ the bounded in-memory provenance created by actual `wrapUntrusted()` calls; it
141
+ does not prove that a model used a source to form a claim.
142
+
143
+ The durable boundaries remain permissions, OS sandboxing where enabled, scoped
144
+ credentials, and explicit human approval.
145
+
146
+ ## Guardrails — manual checks plus two diff gates
147
+
148
+ Rules in `.ur/guardrails/*.json` support `regex`, `contains`, `pii`,
149
+ `maxLength`, `jsonSchema`, and `llm`; phases are `input`, `output`, or `both`;
150
+ actions are `warn` or `block`.
151
+
152
+ ```text
153
+ /guardrails init
154
+ /guardrails list
155
+ /guardrails validate
156
+ /guardrails check "send this to x@y.com" --phase output --json
157
+ ```
158
+
159
+ `/guardrails check` evaluates the supplied text and reports a tripwire. The
160
+ engine is **not** a universal pre/post hook on every normal tool call. Its
161
+ deterministic diff-compatible rules are additionally wired into:
162
+
163
+ - `agent-task pr --create` self-review; and
164
+ - the Agent CI review path.
165
+
166
+ LLM and JSON-schema guardrails are not part of those diff gates. A blocking
167
+ finding prevents the relevant PR/CI handoff unless that command's explicit
168
+ override path is used; it does not globally stop unrelated agent activity.
169
+
170
+ ## Security toolkit — deterministic/local commands
171
+
172
+ The `/security` family is a command toolkit, not a collection of automatically
173
+ invoked model tools:
174
+
175
+ ```text
176
+ /security scan
177
+ /security code
178
+ /security secrets
179
+ /security report
180
+ /scope set local
181
+ /threat-model
182
+ /vuln
183
+ /ir
184
+ /compliance
185
+ /playbook
186
+ /harden
187
+ /kali
188
+ /lab create web-vuln
189
+ ```
190
+
191
+ Workspace code/secret scans are bounded heuristic scanners. `/vuln` consults
192
+ the dependency vulnerability implementation and can report no results when the
193
+ registry is unavailable. `/ir` and `/harden` are read-only collection/check
194
+ paths. `/scope` controls the security module's active web/testing operations;
195
+ it is separate from ordinary UR filesystem tool permissions. Lab creation
196
+ accepts only known templates and rejects unsafe roots.
197
+
198
+ The bundled `/security-review` skill is a model workflow prompt with explicit
199
+ verification and publishing instructions. Its existence does not turn the
200
+ security scanners into a universal automatic gate.
201
+
202
+ ## Devcontainer target
203
+
204
+ `/devcontainer` is an explicit Docker-backed execution target described by
205
+ `.ur/devcontainer.json`:
206
+
207
+ ```text
208
+ /devcontainer status
209
+ /devcontainer init --image node:22
210
+ /devcontainer exec -- npm test
211
+ ```
212
+
213
+ It affects commands deliberately routed through the devcontainer command. It
214
+ does not transparently move every Bash/tool call into Docker.
215
+
216
+ ## Stability ledger — recording is enforced; analysis is advisory
217
+
218
+ Normal tool start/finish hooks append action evidence to `.ur/actions.jsonl`.
219
+ The commands below inspect that ledger:
220
+
221
+ ```text
222
+ /stability metrics
223
+ /stability firewall
224
+ /stability why "ECONNRESET"
225
+ /stability policy
226
+ /stability cooldown
227
+ /evidence 20
228
+ /actions 10
229
+ ```
230
+
231
+ `metrics`, `firewall`, `why`, and `cooldown` calculate failure, latency,
232
+ repetition, blast-radius, or likely-cause summaries. `firewall` prints an
233
+ advisory recommendation; it does not pause or cancel the core query loop.
234
+ `StabilityMonitor` is a self-contained source API and is not instantiated by
235
+ the normal query loop. This is a Monitor/Analyze evidence layer, not a fully
236
+ automatic MAPE-K controller.
237
+
238
+ ## Verifier gates — separate enforced query-loop layer
239
+
240
+ The verifier is independent of `/stability`. In the default `strict` mode its
241
+ L1 query-loop checks include empty turns, repeated calls, completion claims
242
+ versus successful tool effects, unfinished actionable tasks, and configured or
243
+ auto-detected project gates after edits. Interactive sessions ask before
244
+ running project gates; non-interactive sessions can run them directly unless
245
+ `verifier.askBeforeGates` says otherwise. `UR_VERIFIER_MODE=loose|off` weakens
246
+ or disables these checks.
247
+
248
+ Immediate promises such as “let me create it now” are checked only in the final
249
+ visible clause and require matching successful mutation evidence. Rejections
250
+ are capped at three per user turn to avoid an infinite correction loop. The
251
+ independent L2 verification subagent is opt-in through `/verify` or
252
+ `UR_VERIFIER_AUTO_SUBAGENT=1`; it is not auto-spawned by default.
253
+
254
+ ## Claim ledger and credentials
255
+
256
+ `/claim-ledger add` stores claim/source strings in
257
+ `.ur/evidence/claims.json` through the contained private-state writer (atomic
258
+ replacement, regular-file/symlink checks, `0600` mode, and a 2 MiB bound).
259
+ Loading is fail-closed: malformed JSON, a wrong root shape, duplicate IDs,
260
+ unsupported confidence/source kinds, or malformed records make `list`,
261
+ `validate`, and `add` fail nonzero; `add` never replaces the corrupt file with
262
+ an empty ledger. Source kinds are `web`, `file`, `mcp`, `tool`, and `user`.
263
+ `validate` checks only this stored structure; it does **not** fetch URLs, open files,
264
+ or prove that a source still resolves.
265
+
266
+ On macOS, credentials prefer Keychain and fall back to
267
+ `~/.ur/.credentials.json` when keychain reads/writes fail. On Linux and Windows,
268
+ the current implementation uses that plaintext JSON store directly. The file
269
+ is chmod `0600`, but it is still plaintext; “kept in the OS keychain” is not a
270
+ cross-platform guarantee. `/privacy-settings` and `--offline` control
271
+ telemetry/network behavior separately from credential storage.
@@ -0,0 +1,129 @@
1
+ # 13 — Research & File/Media Analysis
2
+
3
+ Source of truth: `src/services/agents/workingMode.ts`,
4
+ `src/constants/prompts.ts`, `src/ur/{notes,researchGraph,fileops,sysinfo}.ts`,
5
+ and `src/commands/{research,paper,cite,graph,read,search,index,summarize,analyze,convert,image,video,youtube,mode}/`.
6
+
7
+ ## Working mode
8
+
9
+ ```text
10
+ /mode research
11
+ /mode code
12
+ /mode debug
13
+ /mode browser
14
+ /mode image
15
+ /mode video
16
+ /mode data
17
+ ```
18
+
19
+ The selected value is persisted in `.ur/mode`. `getWorkingModePrompt()` loads it
20
+ for the `working_mode` system-prompt section, so it changes the behavioral
21
+ instructions used on subsequent model turns. Invalid or unreadable values fall
22
+ back to `code`; changing the mode atomically writes a regular in-workspace
23
+ marker and clears the system-prompt section cache. A failed write returns
24
+ nonzero and leaves the previous marker intact.
25
+
26
+ This is prompt guidance, not a different model, tool registry, permission mode,
27
+ or deterministic workflow engine. Security-specific mode names are handled by
28
+ the separate security module.
29
+
30
+ ## Notes, papers, and citations
31
+
32
+ | Command | Actual operation | Example |
33
+ |---|---|---|
34
+ | `/research [note]` | Append a timestamped research note, or list notes. | `/research RAG eval baselines chosen` |
35
+ | `/paper [title or path]` | Append a paper string, or list papers. It does not parse a PDF. | `/paper papers/mamba.pdf` |
36
+ | `/cite [citation]` | Append a citation string, or list citations. It does not resolve or validate the citation. | `/cite Gu & Dao 2023` |
37
+
38
+ These are per-project file-backed collections under `.ur/`; they do not
39
+ automatically enter the model context merely because they were stored. Record
40
+ text is non-empty and capped at 64 KiB. The `.ur/research/` directories and
41
+ JSONL collection files must be regular in-workspace paths; symlinked storage,
42
+ read failures, and write failures return a nonzero command result rather than
43
+ claiming success.
44
+
45
+ ## “Research graph”
46
+
47
+ `/graph` is currently a set of typed append-only JSONL collections under
48
+ `.ur/graph/`, not an edge-traversable graph database.
49
+
50
+ Supported entity names are `sources`, `papers`, `claims`, `methods`, `datasets`,
51
+ `metrics`, `limitations`, `citations`, `concepts`, `notes`, `experiments`,
52
+ `open_questions`, and `links`.
53
+
54
+ ```text
55
+ /graph
56
+ /graph papers
57
+ /graph papers Mamba: Linear-Time Sequence Modeling
58
+ /graph claims SSMs match attention at 1B scale
59
+ ```
60
+
61
+ With no argument it reports per-collection counts. With an entity it lists
62
+ that collection. With an entity plus text it appends `{ts,text}`. Records do
63
+ not have IDs or validated links, so this surface must not be described as a
64
+ relational or knowledge graph. Writes are bounded, reject symlinked/outside
65
+ storage, and report a nonzero failure instead of claiming a record was saved.
66
+
67
+ ## Text-file helpers
68
+
69
+ | Command | Operation |
70
+ |---|---|
71
+ | `/read <path>` | Return a bounded text-like file to the user/model. |
72
+ | `/summarize <path>` | Return the bounded file prefixed with a summarization instruction. The model performs the summary. |
73
+ | `/analyze <path>` | Return the bounded file prefixed with an analysis instruction. The model performs the analysis. |
74
+ | `/search <query>` | Case-insensitive substring search across bounded workspace text files; at most 60 hits. |
75
+ | `/index` | Write a path-only workspace index to `.ur/index/files.txt`; this is not an embedding index. |
76
+
77
+ `/read`, `/summarize`, and `/analyze` accept the entire remaining command string
78
+ as the path, so workspace-relative paths containing spaces work without special
79
+ token parsing. `readFileSafe()` rejects absolute paths, `..`, directories,
80
+ binary extensions, and symlinks that resolve outside the workspace. Reads are
81
+ truncated at 64,000 characters by default.
82
+
83
+ `/search` and `/index` walk at most 8,000 entries and skip hidden entries other
84
+ than `.ur` plus common dependency/build directories. They are dependency-free
85
+ convenience helpers, not substitutes for the model tools `Grep`, `Glob`, or
86
+ semantic `CodeSearch`. The walker canonicalizes candidate files and skips
87
+ symlinks resolving outside the workspace. `/index` writes atomically beneath a
88
+ canonical in-workspace `.ur/index/` directory and returns nonzero if
89
+ `files.txt` cannot be persisted.
90
+
91
+ ## Conversion and media commands
92
+
93
+ These commands have intentionally narrow behavior:
94
+
95
+ | Command | What it actually does |
96
+ |---|---|
97
+ | `/convert <file> <target>` | Reports which of `pandoc`, `ffmpeg`, and `libreoffice` are installed. It does **not** execute a conversion or create an output file. |
98
+ | `/image <file> [task]` | Reports extension/size and, when `tesseract` exists, runs bounded OCR. It ignores the optional task text and does not invoke a vision model. |
99
+ | `/video <file\|url> [task]` | For a local file, reports bounded `ffprobe` format/stream metadata. For a URL, reports whether `yt-dlp` is installed. It does not extract frames/audio and ignores task text. |
100
+ | `/youtube <url> [task]` | Runs `yt-dlp --dump-json --skip-download` and prints selected metadata/description. It does not fetch subtitles/transcripts or summarize, and ignores task text. |
101
+
102
+ `/convert`, `/image`, `/video`, and `/youtube` take only the first whitespace
103
+ token as the file/URL (and `/convert` takes the second as target), so paths
104
+ containing spaces are not supported by those four parsers. Their output may
105
+ suggest asking the agent to use Bash or a vision-capable model for the next
106
+ step, but the local command itself has not performed that next step.
107
+ `/image` and `/video` also accept absolute paths and do not enforce workspace
108
+ containment.
109
+
110
+ `/os` reports presence of `git`, `ollama`, `node`, `bun`, `python3`, `ffmpeg`,
111
+ `yt-dlp`, `rg`, `cargo`, and `go`. `/ur-doctor` repeats that tool list, probes
112
+ the selected Ollama host, lists selected `.ur` assets, and checks for workspace
113
+ Playwright. Its current `mcp cfg` line checks legacy
114
+ `.ur/mcp/servers.toml` paths rather than the normal `.mcp.json`/settings MCP
115
+ sources, so it is not an authoritative MCP configuration diagnostic.
116
+
117
+ ## Research-oriented bundled skills
118
+
119
+ The normal build registers these user-invocable prompt workflows:
120
+
121
+ - `/paper-implementation` (alias `/implement-paper`);
122
+ - `/latex-paper` (alias `/latex`); and
123
+ - `/benchmark` (aliases `/bench`, `/perf`).
124
+
125
+ Their prompts instruct the model to spawn an isolated worktree agent, gather
126
+ focused evidence, ask before a broader final verification sequence, and avoid
127
+ commit/push/PR publication unless separately requested. Those are agent
128
+ instructions, not a deterministic guarantee that the model completed every
129
+ step; verify the returned worktree, diff, and command evidence.
@@ -0,0 +1,177 @@
1
+ # 14 — Sessions, History & Recovery
2
+
3
+ Source of truth: `src/utils/{sessionStorage,sessionStoragePortable,fileHistory}.ts`,
4
+ `src/cost-tracker.ts`, `src/commands/{resume,rewind,branch,export,tag,rename,session,tasks,stats,cost,usage,files}/`,
5
+ `src/commands/bg/bg.ts`, `src/services/agents/backgroundRunner.ts`,
6
+ `src/cli/transports/{SSETransport,WebSocketTransport}.ts`, `src/tasks.ts`, and
7
+ `src/Task.ts`.
8
+
9
+ ## Transcript persistence
10
+
11
+ Interactive sessions persist JSONL transcripts under
12
+ `~/.ur/projects/<sanitized-project-path>/<session-id>.jsonl`. Session name,
13
+ tag, mode, agent, worktree, and PR-link metadata are entries in that transcript.
14
+ `cleanupPeriodDays: 0`, `--no-session-persistence` in print mode, test mode, or
15
+ `UR_CODE_SKIP_PROMPT_HISTORY` suppresses transcript writes.
16
+
17
+ Cost is **not** stored independently in every transcript. The cost tracker saves
18
+ one “last session” cost/usage snapshot in the project entry of `~/.ur.json`; a
19
+ resume restores it only when that stored `lastSessionId` matches. Older
20
+ sessions can therefore have transcripts without a restorable cost snapshot.
21
+
22
+ ## Continue and resume
23
+
24
+ ```text
25
+ ur -c
26
+ ur -r
27
+ ur -r 6f9d…
28
+ ur -r "auth refactor"
29
+ ur -c --fork-session
30
+ ur --from-pr 123
31
+ /resume [id or search]
32
+ ```
33
+
34
+ - `-c` continues the most recent session for the project.
35
+ - `-r` opens the picker; its optional value is an ID or search term.
36
+ - `--fork-session` creates a new session ID while loading the prior
37
+ conversation.
38
+ - `--from-pr` resolves a transcript linked to a GitHub PR.
39
+ - `-n "name"` sets a startup title; `/rename` changes it later.
40
+
41
+ `/tag <name>` stores exactly one searchable tag on the current session.
42
+ Applying a different value replaces the prior tag; running the same value again
43
+ opens the removal confirmation. This is not a many-tags-per-session system.
44
+
45
+ Transcript appends use a single active drain with per-file FIFO queues. Failed
46
+ entries are restored ahead of later arrivals, the failure is retained until
47
+ `flush()` observes it, and a later `flush()` can retry after the underlying
48
+ filesystem problem is repaired. Session IDs used to construct transcript paths
49
+ must match the bounded alphanumeric/dash form.
50
+
51
+ ## Transport recovery
52
+
53
+ For CCR-v2 remote sessions, `SSETransport` validates numeric sequence IDs,
54
+ requires contiguous delivery, advances its checkpoint only after delivering a
55
+ valid frame, and reconnects on malformed, mismatched, gapped, or incomplete
56
+ frames.
57
+
58
+ `WebSocketTransport` keeps a maximum of 1,000 meaningful outbound frames for
59
+ replay. On overflow it drops the oldest buffered frame and logs a diagnostic.
60
+ Reconnection replays buffered UUID messages and control frames that use
61
+ `request_id`. Frames remain buffered until a reconnect reports a last-received
62
+ UUID; confirming that UUID evicts it and every earlier buffered frame. A buffer
63
+ containing only control frames has no per-control acknowledgement key, so those
64
+ frames can replay again on later reconnects.
65
+
66
+ These are transport-level guarantees. They do not make an unavailable remote
67
+ service durable, and the direct-connect/remote-control launch commands are
68
+ source-only in the normal external bundle as described in chapter 11.
69
+
70
+ ## Checkpoints, rewind, branches, and side chats
71
+
72
+ File-history snapshots are captured as agent edits occur.
73
+
74
+ ```text
75
+ /rewind
76
+ /checkpoint
77
+ /branch try-other-approach
78
+ /fork try-other-approach
79
+ /btw what's the difference between execa and spawn?
80
+ ```
81
+
82
+ `/rewind`/`/checkpoint` can restore conversation state, UR-managed file
83
+ snapshots, or both. These snapshots are separate from git commits.
84
+
85
+ `/branch`/`/fork` copies the persisted main-chain conversation into a new
86
+ session ID and switches to it; the optional argument is the branch session
87
+ title. `/btw` manages a durable side chat without replacing the main chain.
88
+
89
+ ## Export and inspection
90
+
91
+ ```text
92
+ /export session.txt
93
+ /copy
94
+ /trace
95
+ /agent-inspect
96
+ /cost
97
+ /stats
98
+ /usage
99
+ /insights
100
+ ```
101
+
102
+ `/export [filename]` renders the same plain-text transcript for both supported
103
+ filename suffixes. Explicit `.txt` and `.md` suffixes are preserved, so
104
+ `/export session.md` writes `session.md`; `.md` does not select a separate
105
+ Markdown renderer. A missing suffix or any other suffix is normalized to
106
+ `.txt`. Without a filename, the interactive export dialog offers a generated
107
+ `.txt` name or clipboard behavior. File targets must be relative to the
108
+ workspace, their parent directory must already exist, and traversal or symlink
109
+ escapes are rejected.
110
+
111
+ `/cost` reports the in-memory current-session cost/duration for API-key/local
112
+ usage. For ordinary UR subscription users it reports subscription/overage state
113
+ instead of an exact dollar breakdown and is hidden from the slash menu.
114
+ `/stats` is an interactive activity view; `/usage` opens the Usage settings tab
115
+ for plan limits. They are not aliases for the same data.
116
+
117
+ `/files` lists the paths in the current read-file cache, but its command is
118
+ enabled only for `USER_TYPE=ant`; it is not available in the normal external
119
+ build. `/trace` and `/agent-inspect` expose recent/tool and subagent execution
120
+ views respectively.
121
+
122
+ ## Detached background agents — shipped
123
+
124
+ The supported external command family is `ur bg`, not the source-only legacy
125
+ `--bg`, `ur ps`, `ur logs`, `ur attach`, and `ur kill` fast paths.
126
+
127
+ ```text
128
+ ur bg run "run the full test suite and summarize"
129
+ ur bg fanout "audit each package" --agents 3 --worktree
130
+ ur bg list
131
+ ur bg status <id>
132
+ ur bg logs <id> --tail 120
133
+ ur bg attach <id>
134
+ ur bg steer <id> --message "focus on the failing integration test"
135
+ ur bg kill <id>
136
+ ```
137
+
138
+ `run` starts one detached child; `fanout` starts the requested bounded number.
139
+ `--worktree` is opt-in. `--pr` is also opt-in and is rejected without
140
+ `--worktree`; when supplied, it authorizes the background PR/push handoff
141
+ configured by the remaining PR flags. `--dry-run` records/plans the task without
142
+ spawning its worker.
143
+
144
+ State, logs, outputs, and idempotent steering inboxes live under the git/project
145
+ root's `.ur/background/`. The manifest is lock-protected and atomically
146
+ replaced. Steering applies only to queued/running tasks and is bounded to
147
+ 64 KiB per message and 8 MiB per inbox.
148
+
149
+ The legacy `--bg` and process-level `ps|logs|attach|kill` fast paths are behind
150
+ the `BG_SESSIONS` build feature, which the normal external bundle does not
151
+ enable. They must not be documented as the supported npm command syntax.
152
+
153
+ ## In-session tasks
154
+
155
+ `/tasks` (alias `/bashes`) opens the task dialog for the current process.
156
+ `TaskOutput` reads task output and `TaskStop` stops a supported running task.
157
+ The five creatable lifecycle implementations in the external runtime are:
158
+
159
+ - local shell;
160
+ - local agent;
161
+ - remote agent;
162
+ - in-process teammate; and
163
+ - dream.
164
+
165
+ `local_workflow` and `monitor_mcp` remain parseable/renderable historical task
166
+ types, but have no constructor or stop lifecycle in this distribution. A stop
167
+ request for them returns an explicit unsupported-type error.
168
+
169
+ ## Multi-directory access and trust
170
+
171
+ - `/add-dir ../other-repo` or `--add-dir` extends the allowed working
172
+ directories; normal path/permission checks still apply.
173
+ - Interactive startup asks whether the workspace is trusted. Print mode skips
174
+ that dialog and therefore must be used only in a directory the caller already
175
+ trusts.
176
+ - `/ur-init` scaffolds UR project assets under `.ur/`; `/init` generates the
177
+ agent-instruction file (`UR.md`).
@@ -0,0 +1,43 @@
1
+ # UR-Nexus — Technical Specifications
2
+
3
+ > Audited against the executable source and tests for `ur-agent` v1.65.7.
4
+ > Command, tool, flag, provider, and setting claims are checked against the
5
+ > implementation rather than copied from product prose. Release validation
6
+ > keeps this version synchronized and packages the complete `technical/`
7
+ > catalog with the npm artifact.
8
+
9
+ UR-Nexus is an autonomous engineering workflow engine: a terminal (Ink/React) coding agent
10
+ with a plan → execute → test → verify → document → benchmark loop, local/server model support
11
+ (Ollama, llama.cpp, and vLLM), cloud API providers (OpenAI, Anthropic, Gemini, OpenRouter,
12
+ and any OpenAI-compatible endpoint), a multi-agent orchestration layer, and a large built-in
13
+ command/tool surface. An LM Studio adapter remains in the registry but is explicitly disabled
14
+ in this release, so it is not advertised as an available backend.
15
+
16
+ ## Document map
17
+
18
+ | File | Contents |
19
+ |---|---|
20
+ | [01-architecture.md](01-architecture.md) | Runtime architecture: entrypoints, REPL, query engine, task types, services |
21
+ | [02-cli-reference.md](02-cli-reference.md) | The `ur` binary: flags, subcommands, headless mode, background sessions |
22
+ | [03-slash-commands.md](03-slash-commands.md) | Every interactive slash command with usage examples |
23
+ | [04-tools.md](04-tools.md) | Every model-invocable tool (built-in + conditional) with schemas and examples |
24
+ | [05-providers-and-models.md](05-providers-and-models.md) | Provider registry, model selection, routing, escalation, effort/fast modes |
25
+ | [06-configuration.md](06-configuration.md) | settings.json schema, scopes, permission rules, env variables, keybindings |
26
+ | [07-memory-and-context.md](07-memory-and-context.md) | UR.md, auto-memory, /remember, semantic memory, knowledge base, context pack, compaction |
27
+ | [08-skills-plugins-workflows.md](08-skills-plugins-workflows.md) | Skills (SKILL.md), bundled skills, plugins/marketplaces, declarative workflows, patterns, toolsmith |
28
+ | [09-multi-agent.md](09-multi-agent.md) | Subagents, crews, arena, background agents, routing, escalation, worktrees per task |
29
+ | [10-headless-automation-eval.md](10-headless-automation-eval.md) | `-p` print mode, /exec, SDK, automations, triggers, CI loop, eval harness, benchmarks |
30
+ | [11-integrations.md](11-integrations.md) | MCP, IDE/ACP, A2A, Chrome, GitHub, Slack, remote control, desktop, voice |
31
+ | [12-security-sandbox-stability.md](12-security-sandbox-stability.md) | Permission system, sandbox, safety policy, guardrails, security toolkit, stability/MAPE-K |
32
+ | [13-research.md](13-research.md) | Research notes, papers, citations, research graph, file/media analysis commands |
33
+ | [14-sessions.md](14-sessions.md) | Session persistence, resume, rewind/checkpoints, branching, export, tags, insights |
34
+
35
+ ## Quick facts (from code)
36
+
37
+ - **Package**: `ur-agent`, binary `ur` (`bin/ur.js` → `dist/cli.js`, bundled from `src/entrypoints/cli.tsx`).
38
+ - **Runtime**: the npm binary uses a Node ≥ 18.18 launcher and requires Bun ≥ 1.3 for the bundled CLI; the TUI uses React 19 and the vendored Ink fork in `src/ink`.
39
+ - **Local-first**: default model backend is the local Ollama runtime (`http://localhost:11434`); `--offline` disables all cloud paths.
40
+ - **Registered commands at this release**: 168 bundled registry entries, 161 visible entries, 237 visible slash invocation tokens, and 70 rows in `ur --help`; fast-path lifecycle/server commands are documented separately in doc 02. User/project skills, installed plugins, workflows, and MCP prompts are additive and normalized by source priority.
41
+ - **Registered tools**: the built-in pool is assembled per session from `src/tools.ts:getAllBaseTools()` and then filtered by runtime, mode, settings, permissions, and availability. Doc 04 enumerates the public built-ins and every supported gate; connected MCP tools are additive.
42
+ - **Feature flags**: compile-time `feature(...)` gates (`bun:bundle`) dead-code-eliminate internal-only surfaces from external builds; `USER_TYPE=ant` gates internal commands.
43
+ - **Project state**: lives under `.ur/` in each repo (artifacts, specs, workflows, guardrails, safety policy, knowledge, memory index, devcontainer config, tools, index).