Skip to content

feat: Settings → Tools and skill installs (upstream #17101 + #17691) - #10

Merged
nickleuze merged 37 commits into
nick/v2from
nick/feat/tools-skills
Oct 12, 2026
Merged

nickleuze merged 37 commits into
nick/v2from
nick/feat/tools-skills

Conversation

@nickleuze

Copy link
Copy Markdown
Owner

Problem

Upstream's Settings → Tools (pingdotgg#17101) and skill installs (pingdotgg#17691) are still open. We want them in the fork's build now.

Change

Merges the stacked PRs at upstream/pr/17691 (9f0fa23). They branch from an upstream commit the fork already contains, so only their commits come in. Fork glue:

  • AgentToolsRpcGroup: the 8 skills/MCP RPCs get their own group and handler layer, like TicketRecordRpcGroup. In the core group they pushed ws.ts past the type checker's instantiation depth. The server's layer requirements then silently became any (TS2589, visible with tsc --checkers 1).
  • T3_MCP_TOOLKITS: now also lists the fork's goal and ticket toolkits, so Settings → Tools describes them. The registration test checks that this list matches the tools the server serves.
  • Tools MCP toolkit: gets ThreadCommandExecutor, the same way the environment toolkit does.
  • Newer upstream changes: the PRs' hostProcess imports follow the HostProcess rename (refactor(shared): host process references live in a HostProcess module pingdotgg/t3code#17641). Four focus rings use ring-inset to pass no-outset-state-indicators (fix(ui): keep focus and selection borders visible across the app pingdotgg/t3code#16675).
  • Conflicts: RPC scopes, Cursor adapter imports, MCP layer list, route tree (regenerated), lockfile (adds skills@1.7.1 only).
  • Docs: a new row in docs/operations/personal-fork.md says that once upstream merges these PRs, the next sync takes upstream's version and keeps only this glue.

Verification

  • Typecheck: server (default and single checker), web, desktop, mobile, contracts, shared, client-runtime and the provider packages.
  • Server tests (753): RpcAuthorization, DeviceService, Tools handlers, worktree registration, McpServerTools, SkillLibrary, Claude/Codex/OpenCode adapters, ProviderRegistry, serverSettings, terminal Manager, ticket handlers.
  • Other tests: shared agentTools, web toolsSettings.logic, client-runtime commandPermissions, contracts settings, and Cursor CursorT3Tools / adapter / T3McpHttpSession.
  • Fork scripts: node --test fork/*.test.mjs (13/13).
  • Lint and format: run on the changed files.
  • Integration: a trial merge with nick/integration (open PR Tickets: one-click Launch (plan-first), t3_ticket_start, launch on another Mac, Create & launch #9) is clean.

Not checked: a running app and the full CI suite. Fork CI runs on this PR.

Implemented by Claude Opus 5.5 in T3 Code (Claude Code harness).

🤖 Generated with Claude Code

juliusmarminge and others added 30 commits October 8, 2026 00:04
Adds a Tools settings page with Skills and MCP servers tabs, scoped to
environments and projects like other settings.

- MCP servers added in T3 are injected into every provider session next to
  the t3-code server (Claude, Codex, Cursor, OpenCode 1/2, Grok and ACP
  agents). Sensitive env/header values live in the secret store.
- Skills can be switched off by name; Claude, Codex and OpenCode 1.x hide
  them from the session, and the composer drops them from its menu.
- Projects override servers and skill switches per name instead of
  replacing the environment's list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main moved per-thread MCP config into the McpProviderSessions service and
the ACP adapter into packages/provider-acp. The user's tools now ride on
that service's config, and the adapters read them from the session they
are handed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claudeMcpQueryOverrides built the skillOverrides settings, but the turn
never handed them to makeClaudeQueryOptions, so a skill switched off in
Settings → Tools still loaded in Claude sessions. Found by running a real
Claude turn; the new test opens a turn and checks the query options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Renaming an MCP server or variable keeps its stored secret: the client
  sends where it was saved and the server moves it. A sensitive value
  hand-edited into settings.json moves into the store on the next save.
- Turning a secret off and on again with nothing typed keeps it.
- Editing a server at All environments no longer copies it, without its
  secrets, onto environments that never had it; adding one checks names
  across every environment.
- A settings-only client can change a project's skills or switches when
  the project has its own servers: resending a server unchanged is not a
  provider change.
- Environment server switches need provider management, like the server.
- OpenCode 2 always denies other threads' user servers and retries ones
  that failed to register. OpenCode 1 and 2 give an external server the
  user's servers, and OpenCode 1 reapplies skill rules on resume and
  rollback.
- ACP agents get an absolute command for bare names like npx.
- The composer hides disabled skills from slash commands too, a project
  switch for a server named like an object property is ignored, and a
  search for MCP servers opens that tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SDK passes mcpServers to the CLI as an inline --mcp-config argument,
which any local user can read. A sensitive env value or header from
Settings → Tools now goes into the child's environment and --mcp-config
carries a ${VAR} reference, the same as T3's own token since pingdotgg#17408.
Checked against claude 2.1.292: a stdio server received the expanded value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…skills by scope

- Secret copies read every source before anything is written, so swapping
  two variable names no longer leaves both with one value.
- A repository skill under a folder named plugins stays in Repository; the
  plugins path only classifies skills a provider reports without a scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two sensitive entries with the same name made the second reference point
at the first one's placeholder. Each name now gets one reference holding
its last value, matching how the variable record resolves duplicates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s that ask

The user's servers were added to Claude's allowedTools, which skips the
permission prompt in approval-required and auto-accept sessions. Full
access already runs them without asking, so the allow rule only bypassed
the modes that ask. Their tools now go through the session's approval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds a hidden `t3 skills-cli` subcommand that runs the pinned skills CLI
(vercel-labs/skills 1.7.1, telemetry off) and a SkillLibrary service with
preview, install, update, remove and inspect, exposed as skills.* RPCs.
Installs land where `npx skills` puts them, with links for agents that
read only their own folder, chosen from a per-agent folder table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ge Tools

Settings → Tools → Skills gets Add skills (preview a source's skills, then
install them at the current scope), groups installed skills under the
source they came from with one switch, marks conflicting copies of a name,
and adds View files, Update and Remove to each skill's menu. Agents get
t3_tools_read, t3_tools_update, t3_skills_install and t3_skills_remove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- remove: the skills CLI exits 0 when it can't delete a skill, so check the
  folder and lock entry afterwards and report the failure.
- update: follow the CLI's own update source rules, using a GitLab or git
  lock's recorded URL and full-depth discovery when a source can't take a
  folder.
- Show a per-skill update failure, and lock the source field while finding.
- t3_tools_update builds its patch inside the settings write lock
  (updateSettingsWith), so a concurrent change isn't overwritten.
- Project skill switches match names ignoring case, like the environment's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ling

- install, update and remove share a lock: each skills CLI run rewrites a
  whole lock file, so two at once could drop each other's entries.
- A project skill switch is written with the environment's spelling of
  the name.
- The CLI child gets the host environment it resolved (HostProcessEnvironment)
  rather than the process's own, so tests run it against their temp home.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ny skill name

- A global install, update or remove now rescans every project an agent has
  listed, since a project's skill list includes the global skills.
- Project skill switches use a null-prototype map, so a skill named
  __proto__ gets a switch like any other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- After a skill change, agents that list the same folder rescan it one
  after another: a fresh scan drops the others' snapshots of that folder,
  and the registry discards a scan whose starting snapshot changed.
- mcpServerEnabledPatch reads only own keys, so `constructor` isn't taken
  for an inherited server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports the Skills UI from n0mahd's skills series (pingdotgg#17513) onto the Tools page:
- dense one-line rows, sections with counts and a hint ('This project · 2
  · Lives in this repo'), ✦ when every agent loads a skill;
- installed packs as collapsible 'From owner/repo' groups with one switch
  and the first three skills shown;
- a Needs attention filter (conflicts, and project or global skills an
  enabled agent doesn't load);
- a skill page replacing the View files dialog: Used by chips, the source,
  Includes scripts with the script files, Copy path, Update and Remove, a
  file tree with script labels, SKILL.md rendered or as source, each copy
  of a conflicting name, and Escape back to the list.

The server marks each file as a script, so the list and the tree agree.
After an install, one agent rescans a project fresh and the rest follow
without dropping its result, so every agent's list shows the new skill.

Co-Authored-By: n0mahd <39080654+n0mahd@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CLI matches --skill against a skill's SKILL.md name and keys its lock
files by it, but installs into that name sanitized as a folder (`Git
Review` -> `git-review`). Preview now returns the CLI's name with the
folder, and inspect, update and remove find a lock entry by either form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lts whole

- The Add skills dialog ticks at most 200 skills, the most one install
  takes, says so for a bigger source, and the agent tool shares the limit.
- The skills CLI prints its --json result and exits at once, so a result
  over 64 KiB was cut short in the pipe and the preview failed. The
  subcommand now exits only after stdout drains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cking

Deferring process.exit until stdout drained let the CLI's code run on
past an exit it relied on: `add --list` returned into the install path.
A blocking stdout pipe writes everything before the next statement, so
process.exit stays immediate and nothing is cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The skill page drew its own Skills / section crumb under the scope picker.
The open skill now lives in the URL (?skill=), so the settings header reads
Settings / Tools / <skill>, with Tools leading back to the list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p pack rows

At All projects, Codex's own skill list (read in the folder T3 was launched
from) filled a This project section that belonged to no picked project.
Project skills now come only from a scan of the picked checkout.

Skills inside a From <source> pack, and its N more row, now start where the
pack's name does instead of under its icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pack's skills now line up with every other row. Its From <source> heading
is a slim tinted band whose switch and chevron sit in the rows' columns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tabs, search and buttons took three rows above the list. Each tab now puts
the tabs at the start of its own toolbar: search, the attention filter,
rescan and Add skills on Skills; Add server on MCP servers.

Needs attention becomes a warning icon with its count, shown only when
something needs a look, and its tooltip says what that means.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Not available to Claude gave nothing to act on: the agent chips already show
who loads a skill, and nothing in T3 makes another agent load it. Only a name
used by different skills needs a look now, and its message says what to do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilter

Each skill in the Add skills picker took three lines, so a big source showed
three at a time. Rows now match the Skills list: name and one-line
description, a script mark, and the file count on the right. A header box
selects or clears every skill shown, and a source with many skills gets a
filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hovering a description that ends in an ellipsis, in the Skills list or the
Add skills picker, shows the full text. The fit is checked as the tooltip
opens, so a line that fits shows none and the lists measure nothing until
hovered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove only reached skills the skills CLI had installed, so most of a
skill folder could be switched off but not deleted. A skill's menu now has
Remove for any copy an agent finds directly in its own skill folders, at
home or in the project. One the CLI installed still goes through the CLI;
another is deleted from each folder an agent reports for it, links first,
along with the folder a link points to when that is one of the user's own.
Plugin and built-in skills stay switch-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy path sat in the skill's menu, away from the path it copies. It is now
an icon button after the folder path, for whichever copy is shown, and turns
into a check once copied. The menu keeps Update and Remove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With Copy path beside the path, the skill's menu held one or two items. They
are now buttons on the skill's page: Update for a skill installed from a
source, and Remove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juliusmarminge and others added 7 commits October 10, 2026 22:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every agent session gets the t3-code server, but the MCP servers tab only
listed servers added there, so it looked like T3's tools weren't given at
all. It now heads the list as a built-in server with a switch that is on and
locked, since nothing turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With several environments in scope, the Skills tab read only the primary
environment, so a skill on one machine but not another looked the same.
It now reads every environment in scope and merges their skills by name.
A row shows the machines that have the skill, or one fleet mark when they
all do; its page lists them and can copy the skill to the ones missing it.

A copy goes through two new RPCs. skills.export packs the folder an agent
reports for the skill (bounded at 4 MiB and 500 files). skills.import
reinstalls from the skill's remote source when the CLI recorded one, so the
copy can be updated, and otherwise writes the files into .agents/skills
with links for agents that read their own folder. Update and Remove on a
skill's page now reach every environment in scope that has it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings → Tools listed MCP servers but couldn't show what each one offers.
`mcpServers.listTools` starts the named server the way an agent session
would, with the project's overrides and the stored secrets, asks it for
`tools/list` (following cursors), and stops it again, within 30 seconds.
Command servers run in the project's checkout with the host environment
under their own variables; URL servers fall back to SSE on a 404/405.
Failures come back as a typed McpServerToolsError with a plain message.

T3's own `t3-code` server is described from the toolkits `/mcp` registers,
without starting anything; a registration test keeps that list in step.

Listing runs the server's command with its secrets, so it needs
`providers:manage`, the scope that gates adding that command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clicking a server on the MCP servers tab, including the built-in t3-code
row, opens its page in place of the list, the way a skill opens: the
header reads Settings / Tools / <server>, and the Tools crumb or Escape
goes back. The page shows the transport and command or URL, the switch,
Edit and Remove as buttons, then the server's tools in dense rows that
open to their parameters (name, type, required, description).

Tools load through `mcpServers.listTools`, with a delayed skeleton, an
error with Retry, and a refresh; an edit while the page is open lists
them again. A server that is switched off can still be inspected. The
row's switch, Reset and menu keep their clicks to themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ols and skill installs

Brings in pingdotgg#17101 (manage skills and MCP servers in
Settings → Tools) and pingdotgg#17691 (install skills from a source, view their
files, let agents change Tools), stacked, at upstream/pr/17691 9f0fa23.

Fork integration:
- AgentToolsRpcGroup: the skills/MCP RPCs get their own group and handler
  layer, like TicketRecordRpcGroup. In the core group they pushed ws.ts past
  the type checker's instantiation depth, which turned the server's layer
  requirements into `any`.
- T3_MCP_TOOLKITS lists the fork's goal and ticket toolkits; the Tools
  toolkit gets ThreadCommandExecutor like the environment toolkit.
- hostProcess imports follow upstream's HostProcess module rename (pingdotgg#17641).
- Focus rings use ring-inset for no-outset-state-indicators (pingdotgg#16675).
- Conflicts: RPC scopes, Cursor adapter imports, route tree, lockfile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nickleuze
nickleuze merged commit 6e8a251 into nick/v2 Oct 12, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants