* feat(cli): add orca ports to list a workspace's detected ports
Scripts and agents had no way to read the ports Orca already detects for
a workspace, so finding a dev server on a random port meant redoing the
lsof scan by hand. `orca ports` reuses the host-scoped
workspacePorts.scanHost RPC, keeps the rows owned by the current (or
--worktree) workspace, and prints port, pid, process, connect host,
protocol, how the owner was matched, and the advertised URL. --all shows
every listener on that host. An older runtime without scanHost gets an
"update Orca" error instead of a raw method_not_found.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(cli): resolve folder workspaces in orca ports and match rows by path
Run inside a native folder, `orca ports` failed with selector_not_found
(or picked an enclosing git worktree) because it only searched the
worktree list. It now resolves the cwd like `agent launch`, native
folders first, and shows that host's listeners. Rows are matched on the
owner's path instead of its id, so every instance of a repo-backed
folder workspace keeps its ports even though attribution names only the
first instance as owner. `--all` adds the worktree id when two owners
share a display name, and the skill guide notes that only workspace
rows carry `owner` and `advertisedUrl`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(cli): refuse orca ports for folder workspaces without --all; document the command
Co-authored-by: Manuel Meurer <manuel@meurer.io>
* fix(cli): recognise native folder path selectors in orca ports; note SSH scan limits
Co-authored-by: Manuel Meurer <manuel@meurer.io>
* fix(cli): refuse a folder path shared by several folder workspaces in orca ports
Co-authored-by: Manuel Meurer <manuel@meurer.io>
* fix(cli): refuse a path a worktree and a folder workspace share in orca ports
Co-authored-by: Manuel Meurer <manuel@meurer.io>
---------
Co-authored-by: Manuel Meurer <manuel@meurer.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep stale linked-reference status inline
* fix: shimmer stale reference rows without a clock
* docs: compare row and shadcn text shimmer treatments
* fix: shimmer only stale reference metadata
* fix: remove obsolete row shimmer class
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* Transfer keyboard focus when a sibling chat pane opens
* fix(native-chat): hand focus to newly opened chat composer
* fix(native-chat): keep tab bar controller within line limit
* fix(chat): split into a fresh conversation beside the current chat
* test(chat): declare the split fixture store without an assertion
* fix(chat): route the split to the source conversation host
* test(chat): keep the split regression focused on the launch contract
* test(chat): give the command palette split fixture its conversation agent
* test(chat): seed the legacy command fixture without expanding its asserted shape
* test(chat): isolate pane identity commands from the split launch boundary
* Prevent chat splits from starting a terminal on host refusal
* Cancel structured launches when their destination pane closes
* Model live destination groups in agent launch test fixture
* Capture split chat focus intent at the user action
* feat(chat): add the terminal pane hover action cluster
* fix(chat): keep pane controls above the conversation surface
* refactor(chat): share the tab resume launch hook and format pane controls
* style(chat): document reuse of the terminal header button styles
* refactor(ui): share the pane title button variants between terminals and chats
* fix(chat): keep header actions scoped to the displayed chat
* fix(chat): abandon Resume when its destination pane closes
* test(chat): declare destination fixtures without type assertions
* fix(chat): keep Resume visible when its source pane closes
* fix(chat): reuse tab menu Resume placement unchanged
* test: fix Resume regression harness setup
* fix(chat): hand input to the split pane during admission
* fix(chat): Split opens a fresh chat beside the current one
Split Right/Down on a native chat used to move the chat into a new pane.
It now opens an empty pane beside the chat and launches a new chat of the
same agent on the same host into it through the New Chat launch, so the
new composer takes focus at once. A launch that never opens a tab closes
the empty pane. Drops the earlier admission and focus-transfer changes
that main now covers.
* fix(chat): Split palette search words describe a new chat, not a move
* fix: remove misleading chat move shortcut hints
* fix(chat): a new chat stays in its pane until its host lists it
A host tab list built before a chat's create landed can arrive after the
create reply. Once the reply settled the launch, nothing protected the new
tab, so that older list dropped it: Split's new pane collapsed and focus
moved to another chat, and the next list re-added the chat elsewhere.
Keep a small in-memory record for a chat this client created that no host
list has shown yet. While it exists, a list that omits the chat keeps its
tab. The record ends when an accepted list from that host includes the
chat, when the tab closes, on workspace teardown, or 30 seconds after the
reply, when the worktree is re-read from its host (including an unchanged
version) so a chat the host really closed is dropped then. The launch
lifecycle, status, persistence and settlement are unchanged.
* test(chat): type the faked create replies without an assertion
* Keep new chat protection tied to accepted host lists
* Update paired chat close regression to current suppression API
* fix(chat): Portuguese Split palette words describe a new chat
* test(chat): use the destination group option in split fixture
* Avoid History projection in native chat header and currentness checks
* fix(native-chat): keep Find below pane controls
* fix(ui): keep noninteractive tooltip layers pointer-transparent
* Mount native chat actions only for shown panes
* Use checked property access in header instrumentation
* Read Continue eligibility records through workspace selectors
* Cover native header Find clearance and tooltip click passage
---------
Co-authored-by: Orca Worker <orca-worker@localhost>
* ci: move routine checks and unsigned builds to Blacksmith
* ci: retain GitHub Mac images for isolated SSH fixtures
* ci: keep shared terminal perf preparation on Blacksmith
* test: allow encrypted slow-link fixture to finish on ARM CI
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* test: remove redundant cases and repair behavioral assertions
* docs: reconcile audit records with current main
* fix(deps): apply security updates from #32101
Apply the six-file DOMPurify 3.4.17 and Next.js 16.4.1 patch from PR #32101 to resolve the dependency security gate for this test audit. Original patch by Brennan Benson.
* test: satisfy changed-line quality gates
Add required braces and replace filter indexing with find. Rerun both CI quality gates and the 27 affected relay tests; refresh audit hashes and record the corrections.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* Use incremental tsrs for local typechecks
* Update pinned Bun to 1.4.4
* fix(deps): bump dompurify to 3.4.17 and docs next to 16.4.1 for security advisories
dompurify 3.4.17 patches GHSA-cg2g-xh64-v4q7, GHSA-mrv2-3pqr-j5jr and
GHSA-c6gr-qvv4-5v3f in the root and mobile lockfiles. next 16.4.1 patches
GHSA-2464-fhr4-w9xw, GHSA-673q-mjm6-r5xr and GHSA-p3m5-59mp-jv5r in the
docs site.
* Prepare mobile bundle for smoke benchmarks
* Give native compiler benchmarks a larger ARM runner
---------
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* Track Agent Dashboard adoption and daily visible use
- Record enablement, board opens, and per-surface daily visibility
- Persist daily limits across restarts and respect consent and window visibility
* Track dashboard telemetry at surface roots
* docs(chat): explain structured sessions and conversation handoffs
* docs(chat): distinguish copy handoffs from in-place view switches
Same labels mean different things by surface: tab/header Continue in
Chat UI opens a new structured chat, while the terminal-pane context
menu toggles the transcript view in place. Scope composer live-value
routing by session type.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add Orca's own bundled-skill planner and installer (not wired in yet)
One planner decides what installing Orca's bundled skills does to each
target folder; execute re-plans under per-path locks and runs only a plan
whose digest still matches; a shared summary derives badge, wording and
exit code. A copy counts as Orca's untouched one only when its SKILL.md
bytes match a version some build shipped (resources/skills/released-digests.json,
generated from git history and checked add-only).
Nothing calls this yet; the npx path is unchanged.
* Report left-alone folders as warnings and keep backups in the home
A leave is no longer a failure: the outcome line says what happened plus
"N left alone: <reason>", and the exit code is 1 only for a failed or
changed op. Backups for every scope go to <home>/.agents/.orca-skill-backups
on the executing host, so a project Replace never writes into the repo;
moving there falls back to copy, verify, then remove across filesystems.
* Update Orca's skills with Orca's own installer instead of npx skills
The app's Update skills dialog, badge, nudge and status pills now read the
bundled-skill plan and summary, and Update executes the reviewed plan's
digest. `orca skills install|update` runs the same planner in-process with
--dry-run, --force, --json and per-summary exit codes. Removes both npx
spawn sites, the freshness inventory modules and the npx round-trip CI.
* Update only where the skill already is; one provider-root rule for app and CLI
installedOnly now drops every location that holds nothing (keeping the shared slot
only when an existing agent link points at it), so Update never adds a skill for
another agent. The app and CLI resolve the Claude skills folder through the same
rule in localBundledSkillInput; a test asserts both plan identically.
* Compact Update skills dialog: one row per skill, locations named by agent
summarizeBundledSkillPlan now returns each skill's locations, labelled by
agent (or "Shared folder") with a ~-collapsed path; the dialog shows one row
per skill that needs something, collapses up-to-date skills into one line, and
lists every location behind "Show all locations". The result reads "Updated N
skills · M left alone". Under installedOnly a Replace with no shared copy
replaces in place instead of adding one.
* fix(skills): keep location paths readable by putting the state under the path
* fix(skills): hold the last plan in state, not a ref mutated during render
Split the update dialog's rows, headline and footer into components, move the Update label
next to the other plan copy, and use z.strictObject for the request schemas.
* Escape non-ASCII characters in bundled-skill regex and wording
The orcad bundle rejects a literal non-ASCII character in a regex.
* fix(cli): escape non-ASCII apostrophes in the skills install help text
* test(orcad): check the bundled CLI plans a skill install without npx
Drop the deleted roundtrip workflow's group from the closed-PR cancellation fixture.
* Make bundled-skill test fixtures link folders the way the product does on Windows
Directory links in fixtures are junctions on Windows, which need no
Developer Mode; the one file-link fixture is skipped there.
* Resolve legacy skill agent keys canonically
* Reject stale skill replacements when auxiliary content changes
* Keep ordinary bundled skill classification shallow
* Leave unreadable skill replacements alone without aborting plans
* Pass force-all through shallow planning and describe unreadable copies
* Clarify skill update statuses and folder details
* Keep selected skill replacements in place with one status
* Report completed skill replacements with their backup confirmation
* Clarify available skill updates and skipped copies
* Keep skill update results in preview order
* Show each skill skip reason once
* Count skipped skills instead of skipped folders
* Make installer input and link tests work on Windows
* Bound bundled skill classification reads and parse names linearly
* Keep workspace skill roots inside the resolved workspace
* Compare workspace skill roots with native path semantics
* Restrict bundled skill backups to their owner on POSIX
* Keep recovered skills needing attention until they are updated
* Count completed skill updates in the status tooltip
* Sync the runtime localization catalog
* feat(resources): end local terminals with checked identity checks
- Add a PTYs view to the Resource Manager that lists local terminals and can end one. Before stopping, the host confirms the terminal's incarnation, agent ownership, and attachments. This prevents ending a same-ID replacement that started after the list was read.
- Bump the daemon protocol to v50 and gate the new fenced kill on it. Older daemons ignore the extra fields, so the client refuses End instead of sending an unchecked kill.
- Admit diagnostic reads (PTY listing and memory snapshot) only while the Resources view is visible, so a hidden window does no background scanning.
- Report incarnation and host on spawn and exit events so the renderer can match them to the terminal it showed.
- Replace the popover's terminal-session list with the new inventory and move memory polling into the Resources view.
* Show unrouted daemon PTYs in the Resource Manager
* Simplify PTY controls and clarify safe termination
* Format local build compatibility protocol lists
* Add PTY resource management localization strings
* Harden PTY resource manager test fixtures
* Use typed IPC event in PTY kill test fixture
* Refine local PTY resource view model typing
* Refine local PTY resource view model typing
* Include local host identity in PTY lifecycle event tests
* fix(native-chat): name a chat from its first message at once; the generated name replaces it
A native chat's one stored name was written only by a best-effort, one-shot
generation, so any failure left every surface on the 'Codex Chat' placeholder.
The first prompt now names the chat when its first turn starts, and the
generated name replaces it only while the field still holds that seed.
* fix(native-chat): the chat names setting says a chat shows its first message until it is named
* fix(ssh): say where Orca runs instead of "managed server" in the UI
Users read "managed server" as hosting run by someone else, so they declined
moving their SSH hosts. Every user-facing string now says "Orca on <host>" or
"this host's Orca server", in all six locales; Settings > "Orca on your SSH
hosts" and the setup line say the code and files stay where they are and only
Orca's list of projects, tabs and terminals moves to the host. CLI command names,
logs and identifiers are unchanged.
Fixes#30880
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): reassure only when something moves; name the host's label in its row
Review follow-ups: the reassurance shows only while Orca sets itself up or
moves a host, not on every reconnect; the converting line no longer repeats it;
the row names the SSH host's current label; the section description and the
Move anyway dialog stop repeating themselves; translate the Restart dialog's
buttons; drop "managed" from the remaining raw causes and the external
automation refusal.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
No host ever read intent: 'gesture'. The client stops sending it, the params
schema strips it from older clients, and docs/reference records the rule that a
snapshot never carries intent.
* fix(security): put every trust dialog on a host-owned token surface
Plugin themes write CSS tokens on the document root, and dialogs portal to
body, so any trust surface without plugin-security-chrome inherits them; a
theme could hide what is being approved. The orca.yaml hook trust dialog,
notebook run confirmation, plugin install, remove and rollback dialogs were
missing it. DialogContent gains surface="security", which applies the
host-owned tokens, and a scrollable prop for the plugin dialogs' existing
viewport-height scrolling; every trust dialog uses the surface and a test
lists them. The style guide says when to use each.
* fix(security): keep inline trust decisions on the host-owned surface
The agent command approval card (Allow/Deny) and the browser certificate
override sit outside a dialog, so plugin theme tokens still reached them.
A SecuritySurface primitive puts its child on the same host-owned token set
as DialogContent surface="security"; both use it, and the security surface
test now lists inline trust surfaces as well as dialogs.
The root moved to pnpm 12 in #17156 but these two isolated workspaces were
left on pnpm 10, so CI and deploys carried a second pnpm and pnpm/action-setup.
- Pin the root's integrity-checked pnpm 12.14.0 and regenerate both
lockfiles (only the pnpm 12 package-manager document is added; the
dependency graph is unchanged).
- Move settings pnpm 12 ignores out of .npmrc and package.json#pnpm into
each pnpm-workspace.yaml; onlyBuiltDependencies becomes allowBuilds, and
cloud keeps esbuild's script skipped as pnpm 10 did. package-manager-strict
is gone in pnpm 12, whose own version pinning supersedes it.
- docs/site drops --ignore-workspace: under pnpm 12 it skips the workspace
file, losing the overrides and failing the frozen install. vercel.json now
pins install/build so a stale dashboard command cannot reintroduce it.
- Cloud and docs workflows use pnpm/setup@v2 like the root; the relay
unit-test step uses the root's pnpm instead of npx pnpm@10.
* Add telemetry for directional tab close requests
Measure how often people use Close Tabs To The Left and Right, without recording tab titles, paths, or workspace identifiers.
- Sample a stable 10% of installs by hashing the install ID, so membership survives restarts. The app-open event carries the sampled flag so the group can be analysed.
- Cap each direction to one event per app session, tracked in main, so repeated clicks or extra windows cannot inflate volume.
- Count the request before the close flow runs, so cancelled save prompts still count.
- Route both directions through one helper that counts eligible unpinned tabs in visible order.
* Count settings opt-in sessions in tab-close sampling denominator
Enabling telemetry from settings now fires `app_opened` for that session, not only when the opt-in came from the pending banner. Before, settings opt-ins never emitted `app_opened`, so those sessions were missing from the adoption denominator for directional tab close events.
- `trackAppOpenedOnce` now marks the session as tracked only when `track()` accepts the event. An opt-out or environment consent override no longer uses up the session's denominator.
- Tests cover sampling for settings opt-in and the `DO_NOT_TRACK` override.