Skip to content

feat: install skills from a source, view their files, and let agents change Tools - #17691

Open
juliusmarminge wants to merge 26 commits into
t3code/agent-tools-settingsfrom
t3code/skills-installer
Open

juliusmarminge wants to merge 26 commits into
t3code/agent-tools-settingsfrom
t3code/skills-installer

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Stacked on #17101.

Problem

Settings → Tools (#17101) can switch skills on and off, but it can't install a skill, show what's inside one, tell where it came from, or warn that two different skills share a name. Agents also had no way to change Tools themselves. The outside skills series (#17513–#17515) showed these gaps; this takes the parts that fit #17101's model, where T3 never writes an agent's config files.

Change

Install skills like npx skills

  • Add skills takes a GitHub owner/repo, a git URL or a folder on the environment. It lists the source's skills (name, description, file count, and an Includes scripts badge), and installs the ones you pick at the current scope:
    • at environment scope into ~/.agents/skills;
    • at project scope into the project's .agents/skills and skills-lock.json, which can be committed.
  • Installs run the real skills CLI (1.7.1, MIT), pinned and bundled into the server, with its telemetry off. So the folders, links and lock files are the same ones npx skills writes, and a terminal npx skills update keeps working.
    • It runs as a hidden t3 skills-cli subcommand of T3 itself (like acp-mcp-bridge). No Node or npm is needed on the environment, and the CLI is a lazily loaded chunk of the server bundle.
    • Arguments are built from typed input only, git can't prompt, and stdin is closed.
  • Agents that read only their own folder get a link to the installed skill, chosen from a new per-agent folder table (packages/provider-core/src/server/AgentSkillFolders.ts, adapted from feat(web): see which agents can use each skill (skills 1/3) #17513). Claude gets a .claude/skills link, Grok in projects, and Antigravity globally.
  • Update reinstalls a skill from the source its lock records. Remove deletes it with its links and lock entry. Both only apply to skills the CLI installed.

See what's there (the list and skill page follow @n0mahd's design in #17513, credited as co-author)

  • The list has dense one-line rows and sections with a count and a hint ("This project · 2 · Lives in this repo"). A ✦ shows when every enabled agent loads a skill; otherwise the row shows the agents that do.
  • Packs: skills installed from a source are grouped under a collapsible From owner/repo row, with one switch for the group and the first three skills shown. This covers skills installed here or with npx skills; both read the CLI's lock files.
  • Conflict: a mark appears when two copies of a name have different SKILL.md text. Copies reached through links count as one.
  • Needs attention filters to conflicts, and to project or global skills an enabled agent doesn't load.
  • The skill page opens from a row and goes back on Escape. It shows:
    • Used by chips and the source;
    • Includes scripts, naming the script files;
    • Copy path, Update and Remove;
    • a file tree with script labels, and a read-only viewer that renders SKILL.md (Preview/Source) and reuses projects.readFile;
    • a switch between copies when a name has several.

Agents

  • New MCP tools:
    • t3_tools_read and t3_tools_update switch skills and Settings → Tools servers for the environment or a project, in one settings write;
    • t3_skills_install and t3_skills_remove.
  • The settings patches they write are shared with the web page (packages/shared/src/agentTools.ts), so both produce the same overrides.

Server and permissions

  • A SkillLibrary service backs the new skills.* RPCs: inspect, preview, install, update and remove.
  • Inspect only looks at the SKILL.md paths the enabled agents report; a client never names a path.
  • Install, update and remove need providers:manage, like adding an MCP server, because a skill can carry scripts every agent can run. Inspect and preview need filesystem:read.
  • A project install needs a registered project's folder.
  • Install, update and remove run one at a time, because each CLI run rewrites a whole lock file.
  • Afterwards every project the agents have listed is rescanned, one agent at a time per folder. Only the first scan is fresh: a fresh scan drops the other agents' lists of that folder, so a second fresh scan would erase the first agent's result.
  • ServerSettingsService.updateSettingsWith(build) is new. It builds a patch from the latest settings inside the write lock, so t3_tools_update can't overwrite a concurrent change.
  • Project skill switches now match names ignoring case (mergeProjectDisabledSkills), like the environment list and the composer already did.

Docs: docs/user/tools.md.

Not in this PR: a skills.sh search (sources are pasted), separate switches per agent, moving skills between scopes, editing skills, instruction files (#17515), and mobile.

Verification

  • Focused tests:
    • SkillLibrary runs the real bundled CLI through bin.ts against a temp HOME and a local source, with no network. It covers preview, a project install with Claude's link, inspect reporting the source, update, remove, and the refusals.
    • The t3_tools_update handler writes one patch for a project and never returns secrets.
    • Logic tests cover source groups, the conflict mark, availability, Needs attention and the SKILL.md body.
  • Checks: server, web, contracts, shared and client-runtime typecheck; targeted lint; knip on the affected workspaces.
  • Bundle: vp pack the server, then node dist/bin.mjs skills-cli add … installs from the bundle.
  • In the real app (dev server, a throwaway git project):
    • Add skills → mattpocock/skills listed 38 skills and flagged the 4 with scripts.
    • Installing grill-me and tdd wrote .agents/skills, Claude's .claude/skills links and skills-lock.json, the same as npx skills.
    • The row showed under From mattpocock/skills.
    • Update restored a locally edited tdd. Remove deleted its folder, link and lock entry.
    • Editing the project's grill-me so it differed from the global copy showed Conflict. Its skill page switched between the project copy and the global one.
    • Installing diagnosing-bugs showed it as loaded by both Claude and Codex straight away, with Includes scripts and its .sh file labeled script.
    • At 390 px the list has no horizontal overflow.
  • Real agent: a Claude Sonnet 5.5 turn in the project loaded the installed grill-me (session init lists it) and called t3_tools_read through the t3-code MCP server.

Not checked: Windows (the CLI uses junctions there), a desktop build, and a remote environment. They use the same RPCs and the same bundled CLI.

Before After
Before: monospace names, no counts, flat source group After: dense rows, This project · 2 with a collapsible From mattpocock/skills group, Needs attention (5), ✦ marks
Skill page Dark Phone
diagnosing-bugs page: Used by Codex and Claude, From mattpocock/skills, Includes scripts, file tree with a script label, rendered SKILL.md The list in dark mode The list at 390 px
Add skills Agent calling t3_tools_read
Add skills dialog listing mattpocock/skills with Includes scripts badges Claude answering from t3_tools_read

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

🤖 Generated with Claude Code

juliusmarminge and others added 2 commits October 9, 2026 18:55
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>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Oct 10, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 10, 2026
Comment thread apps/server/src/skills/SkillsCli.ts
Comment thread apps/web/src/components/settings/AddSkillsDialog.tsx
Comment thread apps/server/src/skills/SkillLibrary.ts Outdated
Comment thread apps/server/src/skills/SkillLibrary.ts Outdated
Comment thread apps/server/src/mcp/toolkits/tools/handlers.ts Outdated
Comment thread apps/web/src/components/settings/ToolsSettings.tsx
Comment thread packages/shared/src/agentTools.ts
@macroscopeapp

macroscopeapp Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This is a large production feature that installs and removes executable skill content, adds agent-facing settings mutation, starts configured MCP servers with stored environment variables, and changes the built-in tool and authorization surface. An unresolved High-severity finding also affects skill export with directory symlinks, so the change requires human review.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.9 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 1 — 8 ✅

Baseline: unavailable · PR result: 88a827b · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

- 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>
Comment thread apps/server/src/skills/SkillLibrary.ts
…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>
Comment thread apps/server/src/skills/SkillLibrary.ts
Comment thread packages/shared/src/agentTools.ts
…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>
Comment thread packages/shared/src/agentTools.ts Outdated
Comment thread apps/server/src/skills/SkillLibrary.ts Outdated
juliusmarminge and others added 2 commits October 9, 2026 20:02
- 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 (#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>
Comment thread apps/server/src/skills/SkillLibrary.ts Outdated
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>
Comment thread apps/web/src/components/settings/AddSkillsDialog.tsx Outdated
…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>
Comment thread apps/server/src/cli/skillsCli.ts Outdated
juliusmarminge and others added 2 commits October 10, 2026 20:45
…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>
Comment thread apps/web/src/components/settings/SkillDetail.tsx
juliusmarminge and others added 3 commits October 10, 2026 21:28
…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>
Comment thread apps/web/src/components/settings/ToolsSettings.tsx
juliusmarminge and others added 2 commits October 10, 2026 21:48
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>
juliusmarminge and others added 7 commits October 10, 2026 21:57
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>
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>
return yield* tooLarge(`${input.name} has too many files to copy.`);
}
let bytes = 0;
const bundled = yield* Effect.forEach(files, (file) =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High skills/SkillLibrary.ts:723

Exporting a skill with a directory symlink fails with a filesystem error instead of producing a bundle: listFiles includes links, and this loop passes each path to readFile, which fails when the path is a directory link. Filter symlink entries before reading them, or preserve links explicitly in the bundle.

-      const bundled = yield* Effect.forEach(files, (file) =>
+      const regularFiles = yield* Effect.filter(files, (file) =>
+        fileSystem.readLink(path.join(folder, file.path)).pipe(
+          Effect.as(false),
+          Effect.orElseSucceed(() => true),
+        ),
+      );
+      const bundled = yield* Effect.forEach(regularFiles, (file) =>
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/skills/SkillLibrary.ts around line 723:

Exporting a skill with a directory symlink fails with a filesystem error instead of producing a bundle: `listFiles` includes links, and this loop passes each path to `readFile`, which fails when the path is a directory link. Filter symlink entries before reading them, or preserve links explicitly in the bundle.

juliusmarminge and others added 3 commits October 11, 2026 02:16
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>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant