Skip to content

feat(web): add cross-harness skill manager - #4630

Open
t3dotgg wants to merge 5 commits into
mainfrom
t3code/plan-skill-manager-1
Open

feat(web): add cross-harness skill manager#4630
t3dotgg wants to merge 5 commits into
mainfrom
t3code/plan-skill-manager-1

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

  • add a Skills settings page that inventories global Codex and Claude skills across connected computers
  • group skills by computer and harness with searchable, collapsible sections
  • expose each skill's description, install path, copy action, and full SKILL.md content
  • add authenticated server discovery, shared contracts, client runtime state, and focused tests
  • include the implementation plan used to explore cross-machine discovery and future management actions

Why

Skills currently live in harness-specific directories on individual computers, which makes them difficult to discover or inspect. This introduces a unified read-only view so users can understand what is installed and where before adding mutation operations such as copy, install, or removal.

Screenshot

Skills settings grouped by Claude and Codex

Validation

  • vp test run apps/server/src/skills/SkillInventory.test.ts apps/web/src/components/settings/SkillsSettings.test.ts
  • vp run --filter @t3tools/web typecheck
  • targeted formatting and linting for the changed web files
  • manually verified through the shared T3 Code web environment

Note

Low Risk
Read-only filesystem scans behind existing environment auth; no skill mutation. Main exposure is returning full SKILL.md paths and contents to authorized clients.

Overview
Adds a read-only Skills settings page at /settings/skills so users can see global Codex and Claude skill installations on each connected computer, with search, refresh, collapsible grouping by environment and harness, copy-path, and inline SKILL.md viewing.

Server: New GET /api/skills (orchestration read scope) runs discoverGlobalSkillInventory, scanning configured provider instances via existing Claude/Codex discovery, reading SKILL.md content and skipping unreadable files. Contracts add SkillInventory types; client-runtime adds @t3tools/client-runtime/state/skills for fetch, filter, and display helpers.

Also wires sidebar/search routing and includes an architecture plan doc for future harness coverage and safe removal.

Reviewed by Cursor Bugbot for commit 86bd726. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add cross-harness skill manager settings page with server-side inventory API

  • Adds a /settings/skills page in the web app that lists skills across all connected environments, with search, refresh, and collapsible per-harness groups
  • Introduces a GET /api/skills endpoint on the server that scans global skills for all configured provider instances (Codex and Claude drivers), returning a typed SkillInventory payload
  • Adds SkillInventory and SkillInventoryInstallation schemas to the contracts package, and exposes a new @t3tools/client-runtime/state/skills subpath with filtering, grouping, and path-formatting helpers
  • Skills discovery reads SKILL.md files from provider home directories; unreadable files are silently skipped rather than failing the scan

Macroscope summarized 86bd726.

Summary by CodeRabbit

  • New Features

    • Added a Skills section in Settings for viewing installed Codex and Claude skills across connected environments.
    • Search, filter, refresh, expand/collapse, and copy skill paths from the inventory.
    • Added connection, loading, empty, and error states.
    • Added an authenticated API for retrieving skill inventories.
  • Documentation

    • Added an architecture and implementation plan for the skill manager.
  • Tests

    • Added coverage for inventory discovery, filtering, grouping, path formatting, and display behavior.

Built with gpt-5.6-sol through the Codex harness.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: a cross-harness skill manager for the web application.
Description check ✅ Passed The description explains the changes, motivation, UI impact, validation, and scope, with a screenshot for the new settings page.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/plan-skill-manager-1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Jul 27, 2026
@t3dotgg
t3dotgg marked this pull request as ready for review July 27, 2026 10:52
@github-actions github-actions Bot added the size:XXL 1,000+ changed lines (additions + deletions). label Jul 27, 2026
Comment thread apps/web/src/components/settings/SkillsSettings.tsx
Comment thread apps/web/src/components/settings/SkillsSettings.tsx Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: a cross-harness skill manager with new server endpoints, contracts, UI components, and client-side logic. New user-facing capabilities of this scope warrant human review regardless of code quality.

No code changes detected at 86bd726. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

@macroscopeapp macroscopeapp Bot left a comment

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.

Effect service conventions review of the new skills service, HTTP layer, contracts, and client-runtime helper. One finding: an aliased service-module import in the new server test. Everything else (namespaced effect/* subpath imports, environment-based dependency acquisition via yield* ServerSettingsService, runPromise confined to the React boundary, schema-only contracts) matches the conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/skills/SkillInventory.test.ts Outdated
Comment thread apps/server/src/skills/SkillInventory.ts
Comment thread apps/server/src/skills/SkillInventory.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
docs/architecture/skill-manager-plan.html (1)

817-826: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align the touchpoint list with the paths shipped in this PR.

The list names packages/contracts/src/environment.ts and apps/server/src/http.ts. This PR adds packages/contracts/src/skillInventory.ts, apps/server/src/skills/http.ts, and wires the route in apps/server/src/server.ts. Update the list so the plan matches the delivered Phase 1 code.

📝 Proposed doc update
-          <code>packages/contracts/src/environment.ts</code> ·
-          <code>packages/contracts/src/environmentHttp.ts</code> · new inventory schemas ·
+          <code>packages/contracts/src/skillInventory.ts</code> ·
+          <code>packages/contracts/src/environmentHttp.ts</code> ·
           <code>apps/server/src/provider/Drivers/ClaudeSkills.ts</code> ·
           <code>apps/server/src/provider/Layers/CodexProvider.ts</code> · new
           <code>apps/server/src/skills/</code> service/adapters ·
-          <code>apps/server/src/http.ts</code> · new client-runtime query helper ·
+          <code>apps/server/src/skills/http.ts</code> ·
+          <code>apps/server/src/server.ts</code> ·
+          <code>packages/client-runtime/src/state/skillInventoryHttp.ts</code> ·
           <code>apps/web/src/components/settings/SettingsSidebarNav.tsx</code> · new
           <code>apps/web/src/routes/settings.skills.tsx</code> and settings components.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture/skill-manager-plan.html` around lines 817 - 826, Update the
touchpoint list in the architecture plan to replace environment.ts and server
http.ts references with the shipped skillInventory.ts and skills/http.ts paths,
and add the route wiring file server.ts. Preserve the other listed Phase 1
touchpoints.
apps/server/src/skills/SkillInventory.ts (1)

25-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated skill-installation mapping and mark the fallback providers.

The "codex" and "claudeAgent" branches both read each skill file and map it to SkillInventoryInstallation; moving this through a shared map helper prevents future drift. The shared return []; fallback also leaves Cursor and Grok unexplained — add a comment or explicit branches for them to satisfy the provider adapter decision guidance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/server/src/skills/SkillInventory.ts` around lines 25 - 83, Extract the
duplicated file-reading and SkillInventoryInstallation mapping from
discoverInstanceSkills into a shared helper, reusing the branch-specific
provider ID, harness display name, skill metadata, and enabled state for both
codex and claudeAgent. Replace both Effect.forEach mapping blocks with that
helper while preserving their existing skill discovery inputs. Document the
fallback return [] by adding explicit Cursor and Grok branches or a comment
identifying those unsupported providers.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/server/src/skills/SkillInventory.test.ts`:
- Line 14: Replace the aliased layerTest import in SkillInventory.test.ts with a
namespace import for serverSettings, then update both call sites to invoke
ServerSettings.layerTest(...), preserving the existing arguments and test
behavior.

In `@apps/web/src/components/settings/SkillsSettings.logic.ts`:
- Around line 1-102: Move the framework-agnostic helpers formatSkillPath,
filterSkillInventory, displayedSkillCount, setKeyCollapsed, skillKey,
groupSkillsByHarness, and skillContentForDisplay, along with the
SkillHarnessGroup type and their supporting constants/helpers, into
packages/client-runtime beside the skills HTTP client. Export them from the
package and update the web settings logic to import and reuse those shared
symbols, preserving all existing behavior.

---

Nitpick comments:
In `@apps/server/src/skills/SkillInventory.ts`:
- Around line 25-83: Extract the duplicated file-reading and
SkillInventoryInstallation mapping from discoverInstanceSkills into a shared
helper, reusing the branch-specific provider ID, harness display name, skill
metadata, and enabled state for both codex and claudeAgent. Replace both
Effect.forEach mapping blocks with that helper while preserving their existing
skill discovery inputs. Document the fallback return [] by adding explicit
Cursor and Grok branches or a comment identifying those unsupported providers.

In `@docs/architecture/skill-manager-plan.html`:
- Around line 817-826: Update the touchpoint list in the architecture plan to
replace environment.ts and server http.ts references with the shipped
skillInventory.ts and skills/http.ts paths, and add the route wiring file
server.ts. Preserve the other listed Phase 1 touchpoints.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 106ee80a-4e78-4d75-912a-1f334194d3b0

📥 Commits

Reviewing files that changed from the base of the PR and between f0f16e4 and befd2fe.

📒 Files selected for processing (16)
  • apps/server/src/server.ts
  • apps/server/src/skills/SkillInventory.test.ts
  • apps/server/src/skills/SkillInventory.ts
  • apps/server/src/skills/http.ts
  • apps/web/src/components/settings/SettingsSidebarNav.tsx
  • apps/web/src/components/settings/SkillsSettings.logic.ts
  • apps/web/src/components/settings/SkillsSettings.test.ts
  • apps/web/src/components/settings/SkillsSettings.tsx
  • apps/web/src/routeTree.gen.ts
  • apps/web/src/routes/settings.skills.tsx
  • docs/architecture/skill-manager-plan.html
  • packages/client-runtime/package.json
  • packages/client-runtime/src/state/skillInventoryHttp.ts
  • packages/contracts/src/environmentHttp.ts
  • packages/contracts/src/index.ts
  • packages/contracts/src/skillInventory.ts

Comment thread apps/server/src/skills/SkillInventory.test.ts Outdated
Comment thread apps/web/src/components/settings/SkillsSettings.logic.ts Outdated
@t3dotgg
t3dotgg force-pushed the t3code/plan-skill-manager-1 branch from befd2fe to a63d4e1 Compare August 5, 2026 00:09
@t3dotgg t3dotgg changed the title Add cross-harness skill manager feat(web): add cross-harness skill manager Aug 5, 2026
Comment thread packages/client-runtime/src/state/skillInventoryHttp.ts Outdated
Comment thread apps/web/src/components/settings/SkillsSettings.tsx Outdated
Comment thread apps/web/src/components/settings/SkillsSettings.tsx Outdated
Comment thread apps/server/src/skills/SkillInventory.ts
Comment thread apps/server/src/skills/SkillInventory.ts
Comment thread apps/web/src/components/settings/SkillsSettings.tsx
@t3dotgg
t3dotgg force-pushed the t3code/plan-skill-manager-1 branch from 88eaab3 to 86bd726 Compare August 7, 2026 11:49
const fileSystem = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const installations = yield* Effect.forEach(input.skills, (skill) =>
fileSystem.readFileString(skill.path).pipe(

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.

🔴 Critical skills/SkillInventory.ts:42

readSkillInstallations reads skill.path via fileSystem.readFileString without verifying the path is not a symlink that resolves outside the discovered skill directory. A SKILL.md symlink such as skills/leak/SKILL.md -> /etc/passwd passes discovery, and line 42 returns the target file's full contents to any client of the remote skills API, leaking arbitrary host files. Consider rejecting symlinks or verifying the resolved real path is contained within the expected skill root before reading.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/skills/SkillInventory.ts around line 42:

`readSkillInstallations` reads `skill.path` via `fileSystem.readFileString` without verifying the path is not a symlink that resolves outside the discovered skill directory. A `SKILL.md` symlink such as `skills/leak/SKILL.md -> /etc/passwd` passes discovery, and line 42 returns the target file's full contents to any client of the remote skills API, leaking arbitrary host files. Consider rejecting symlinks or verifying the resolved real path is contained within the expected skill root before reading.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 11.3 KiB 11.3 KiB −3 B (−0.0%) 15.1 KiB
Codex Thread snapshot wire 5.5 KiB 5.4 KiB −3 B (−0.1%) 7.3 KiB
Codex Live turn WebSocket wire 5.9 KiB 5.9 KiB 0 B (0.0%) 7.8 KiB
Codex Live turn WebSocket decoded 49.7 KiB 49.7 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 16 16 0 (0.0%) 21
Claude Total thread wire 11.3 KiB 11.3 KiB +12 B (+0.1%) 15.1 KiB
Claude Thread snapshot wire 5.5 KiB 5.5 KiB +5 B (+0.1%) 7.3 KiB
Claude Live turn WebSocket wire 5.8 KiB 5.9 KiB +7 B (+0.1%) 7.8 KiB
Claude Live turn WebSocket decoded 50.6 KiB 50.6 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 16 16 0 (0.0%) 21

Baseline: 239ef1c · PR result: 86bd726 · 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: 94.6 KiB
  • Claude decoded thread snapshot: 95.3 KiB

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

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 86bd726. Configure here.

) : visibleInventory?.installations.length === 0 ? (
<StatusLine>
{query ? "No skills match this search." : "No global Codex or Claude skills found."}
</StatusLine>

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.

Wrong empty-state for blank search

Low Severity

The empty inventory message branches on raw query, while filtering and the rest of this panel treat only a trimmed query as an active search via isSearching. Whitespace-only input still counts as a search here, so an actually empty inventory can show the “no matches” copy instead of the “no skills found” copy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 86bd726. Configure here.

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

Labels

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