Skip to content

feat: plugins settings becomes Plugins & Skills with full skill management - #170

Merged
badcuban merged 13 commits into
mainfrom
worktree-skills-tab
Aug 22, 2026
Merged

feat: plugins settings becomes Plugins & Skills with full skill management#170
badcuban merged 13 commits into
mainfrom
worktree-skills-tab

Conversation

@badcuban

Copy link
Copy Markdown
Collaborator

The plugins settings page mixed four concepts (plugins, skills, apps, MCP connections) in one scroll, skills were buried inside per-provider rows with no way to create, delete, or toggle them, and the Apps section always paid a ~12s ChatGPT directory fetch.

What this changes:

Page structure

  • The page splits into two underline tabs, Plugins and Skills, with the tab in the URL (?tab=skills) and remembered across visits. Shared search, provider chips, and scope picker sit above the tabs.
  • Settings nav entry renamed to "Plugins & Skills" and moved to sit after Providers; a command-palette entry opens the Skills tab directly.
  • Installed plugins render as rows (icon, name, description, on/off switch) instead of an icon strip. Marketplaces demote to a collapsed "Marketplace sources" row under Advanced. Each section gets a one-line explainer, and Codex-only surfaces carry the provider glyph.

Skill management (new)

  • Skills list flat across providers, grouped by origin (project / personal / from plugins / built in), with plugin-bundled skills collapsed into one disclosure row per plugin that also carries the plugin's enable switch.
  • New skill scaffolding (writes a SKILL.md into the provider's personal skills folder), guarded deletion (inventory-membership, symlink, realpath-root checks; never plugin-bundled files), and enable/disable for both providers: Codex via skills/config/write, Claude via the <name>@skills-dir plugin id. A Codex toggle also reaches a same-name copy the row shadows, so "off" means off.
  • Contracts gain canToggle/canDelete computed server-side plus create/delete RPCs.

Correctness and speed

  • Connected Codex apps load instantly from the local app/installed snapshot (enriched via app/read); the full directory stays behind Browse with a visible loading and error state in the dialog. App rows show real logos and say "Connected".
  • Skill descriptions using YAML block scalars (>-) parse correctly instead of rendering ">".
  • A user skill sharing a name with a Codex built-in shows once; provider chip switches cache late responses and show skeletons instead of a false "No plugins installed"; the page fits a 390px phone (row truncation, responsive connections table); personal skills no longer mislabel as project skills when the project sits under the home directory.

Gates: fmt, lint, typecheck, server + web unit suites, and the web browser suite all pass. Verified live on desktop and mobile viewports.

Skills could only be toggled on Codex, and there was no way to create or
delete one. The server now reports per-skill canToggle/canDelete, routes
the Claude toggle through its skills-dir plugin ids, and adds guarded
create and delete actions for user and project skills roots.
The page mixed plugins, skills, apps, and connections in one scroll, and
skills were buried inside per-provider rows.

A page-level tab bar now splits it in two. Skills get a flat cross-provider
list grouped by origin, with inline toggles where the provider supports
them, a New skill button, and Delete in the skill detail dialog. Apps move
out of the per-provider rows into their own section on the Plugins tab.
…ggle

Adds server coverage for the new create and delete actions, the toggle
routing that derives a <name>@skills-dir plugin id, and the canToggle and
canDelete flags the inventory now reports. Adds web coverage for the page
tab resolution and the skill origin grouping.
The Apps section always waited on app/list, which resolves the whole
ChatGPT directory through the backend and can never be instant. Connected
apps now come from app/installed, a local snapshot read, enriched with one
app/read call for real names, descriptions, and logos. The full directory
stays deferred until the user opens Browse.

The Plugins and Skills tabs were small chips inside a section card, so they
read as filters. They are now underline tabs at the top of the page, with
the shared search and filters below them. Each section gained a one-line
explainer, provider-exclusive surfaces show the provider glyph, app rows
render their real icon, and app status reads Connected rather than
Installed.
A single plugin can ship a hundred skills, which buried everything the user
wrote. Bundled skills now sit behind one disclosure row per plugin carrying
the plugin's own enable/disable switch, which also restores the bundle
toggle the tab split had dropped. Searching opens only the plugins the
query actually narrowed.

Codex reports its built-in skills and a user's own copy under one name, so
a user copy now hides the built-in it shadows.

Skill front matter using YAML block scalars rendered as just a > character.
The parser now folds those blocks into the real description.
A raw control character in the template literal made git treat the file as
binary. The escape sequence produces the same string.
Codex keys enabled state by path, so a personal skill and the built-in it
shadows have two independent flags under one name. The list shows them as
one row, so switching it off wrote only one flag and left the other copy
live while the row read Off.

The Codex toggle now lists skills first and writes every user- and
system-scoped copy sharing the name. Project-scoped copies stay
independent, and a failed listing still toggles the requested path.
The page owns both now, but the nav entry and the command palette only
mentioned plugins, so skills were unfindable from either. The route path is
unchanged, so existing links and the remembered tab keep working. The
palette gains an entry that opens the Skills tab directly.
… loading

Installed plugins were a strip of logos, which answered what you had and
nothing else: enabling or disabling one meant opening it first. They are
rows now, with a description and an On/Off switch.

Marketplaces had a standing section for something rarely touched. It is one
collapsible row at the bottom of the tab, keeping every capability.

Opening Browse for apps starts a catalog fetch that takes seconds, but the
connected rows were already on screen so the dialog showed a settled count
and looked finished. It now says it is still loading, and says so plainly if
the fetch fails, with a retry.
…list

Two things made a switch back to a provider look empty. A response that
arrived after the user changed chips was thrown away instead of cached, so
returning to that provider was a cold miss. And once an inventory held only
the provider that was last fetched, selecting a different chip filtered to
nothing and every section rendered its real empty label while the refetch
ran.

Responses are now cached for the key they were issued under whatever the
user is looking at, and a provider the loaded inventory cannot answer for
shows the loading skeletons instead of claiming to be empty. A failed fetch
still shows its error.
The section manages what the providers can do, so it belongs next to them
rather than below the instruction and connection pages. The order test also
still expected the old Plugins label; both expectations now match the nav.
At 390px the plugin and app rows sat in a grid whose items could not
shrink, so one long unbreakable path stretched every row to ~1050px and
pushed all the switches and badges off screen. The connections table kept
three fixed columns that starved the name column into overlapping headers.

Grid rows get min-w-0 so text truncates instead of stretching the track.
The connections table drops to name and status below sm, with the provider
mark riding with the name. The load-time line truncates instead of
clipping, and a personal skill no longer reports as a project skill when
the project directory sits under the home directory (the ancestor walk was
re-filing the user skills root).
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
threadlines Skipped Skipped Aug 22, 2026 7:11am

Request Review

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Aug 22, 2026
@badcuban
badcuban merged commit b1c3b95 into main Aug 22, 2026
15 checks passed
@badcuban
badcuban deleted the worktree-skills-tab branch August 22, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 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