Skip to content

feat(skills): add a Skills page under Settings → Build - #6662

Merged
pedrofrxncx merged 3 commits into
mainfrom
rafavalls/skills-settings-page
Aug 31, 2026
Merged

feat(skills): add a Skills page under Settings → Build#6662
pedrofrxncx merged 3 commits into
mainfrom
rafavalls/skills-settings-page

Conversation

@rafavalls

@rafavalls rafavalls commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

What is this contribution about?

Describe your changes and why they're needed.

Skills already drive agent behaviour at runtime (buildSkillCatalog<available-skills>), but the only way to see or add one was to browse raw folders in the Library. This adds Settings → Build → Skills: a page listing the org's whole catalog (its own, built-in public sets, synced repos) with search and origin filter chips, plus folder-import for new ones. Skills are SKILL.md folders on org-fs, so import is the Library's upload with the format enforced — pick a folder containing a SKILL.md and its files land under home/skills/<slug>/ with subdirectories intact (files are grouped by destination dir; flattening would collapse references/style.md onto the root). Cards reuse the Library's FolderIcon so a skill looks like the same object on both pages: Finder blue for the org's own (deletable), graphite plus a view-only badge for read-only sets and repos, with the body glyph naming the origin. Filter chips are derived from the catalog rather than hardcoded, since which public sets exist is deployment config (ORGFS_PUBLIC_SETS) and repo volumes are per-org.

Web-only — no API, schema, endpoint or migration changes. Everything composes existing org-fs routes (/fs/skills, PUT/DELETE file, list).

How did you verify your code works?

Name the tests you ran or added and what you observed. "Verified manually" or "existing tests" without specifics doesn't count.

  • tsc --noEmit (apps/web) and oxlint clean on all touched files; knip reports no orphans.
  • bun run --cwd=apps/web test: 2987 pass / 112 fail. I re-ran with this branch's changes stashed and got byte-identical counts (2987/112/13 errors), so the failures pre-date this branch and none are introduced here.
  • react.d.ts (the webkitdirectory augmentation) is load-bearing, not decorative: removing the file reproduces exactly 2 webkitdirectory type errors, so the attribute is genuinely type-checked rather than silently any. It lives in its own module file because putting declare module "react" in the script-scoped globals.d.ts declares an ambient module that shadows React entirely (~30 errors across packages/ui).
  • Seeded a real multi-file skill (home/skills/weekly-report with references/{template,tone}.md) into a local org through OrgFs.write() and confirmed both consumers agree: the route's filesExist probe returns hasSkill=true (so the Library renders a skill card), and detectSkills returns id=home/skills/weekly-report with the parsed name/description (so agents get it in <available-skills>).

Screenshots/Demonstration

Add screenshots or a Loom video if your changes affect the UI.

Page layout follows the Connections page rhythm (title → search → chips → cards on one gap-6 column); cards follow ProjectCard.

How to Test

Provide step-by-step instructions for reviewers to test your changes:

  1. Go to Settings → Build → Skills. The built-in core / storefront sets should list as graphite folders with a view-only badge; filter chips show one per origin with counts.
  2. Click a card — the Library's skill preview opens (SKILL.md rendered, bundled files in the sidebar).
  3. Click Import skill and pick a folder containing a SKILL.md (nested subfolders are fine). It appears as a blue folder attributed to your org, with a delete action in its hover menu.
  4. Pick a folder without a SKILL.md — expect a toast telling you to pick the skill's own folder, and no upload.
  5. Confirm the imported skill also shows in Library and is offered to agents via the chat / picker.

Migration Notes

If this PR requires database migrations, configuration changes, or other setup steps, document them here. Remove this section if not applicable.

None.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

🤖 Generated with Claude Code


Summary by cubic

Adds Settings → Build → Skills so orgs can see every skill available to their agents (own, built-in sets, synced repos) and import new ones, instead of browsing raw folders in the Library.

  • Lists the full org skill catalog with search and origin filter chips; clicking a card opens the Library's skill preview.
  • Importing a folder with a SKILL.md at its root uploads it under home/skills/<slug>/ with subdirectories intact; other folders are rejected with an error toast.
  • Imports refuse existing slugs, drop dotfiles and tooling dirs, cap at 200 files, and roll back a partially failed upload.
  • Failed catalog loads render their own error state, not an empty state.
  • Cards reuse the Library's FolderIcon: blue for the org's own deletable skills, graphite with a view-only badge for read-only sets and repos.
  • Web-only; no API, schema, or migration changes. Adds en and pt-br translations.

Written for commit cc6aec8. Summary will update on new commits.

Review in cubic

@github-actions github-actions Bot added the claude PR authored by a coding agent label Aug 27, 2026
rafavalls and others added 3 commits August 31, 2026 14:48
Surfaces the org's skill catalog (the same `/fs/skills` data the runtime
renders as `<available-skills>`) as a browsable page, with folder-import
for new ones.

Skills are `SKILL.md` folders on org-fs, so importing is the Library's
upload with the format enforced: pick a folder containing a SKILL.md and
its files land under `home/skills/<slug>/`, subdirectories intact. Cards
reuse the Library's FolderIcon — Finder blue for the org's own, graphite
plus a view-only badge for built-in sets and synced repos — and filter
chips are derived from the catalog rather than a hardcoded list, so a
deployment's own public sets appear automatically.

Web-only; no API, schema, or endpoint changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Six issues from a review pass over the page:

- A failed catalog fetch rendered the "No skills yet" empty state, with an
  Import CTA — a member missing ORG_FS_READ was told the org had no skills.
  Now its own error state, with the message and a retry.
- Importing over an existing slug silently merged into it: matching filenames
  overwritten, the old skill's other files left behind. A live `stat` of the
  destination now refuses, pointing at delete-then-reimport.
- The upload loop awaited one directory group at a time (N round-trip waves for
  N subdirectories) and left earlier groups on disk when a later one failed.
  One `allSettled` fan-out instead — settled, not `all`, so the catalog refresh
  can't run while PUTs are still in flight.
- The catalog query shared the "/" picker's key but not its staleTime, so every
  mount and window focus rescanned home plus every synced repo volume.
- Folder import had no file filter or cap: a stray `node_modules` fanned out to
  one PUT per file. Dotfiles and tooling dirs are dropped, the count is capped.
- Filter-chip existence was derived from the search-filtered list, so chips
  vanished and the active filter silently reset while typing. Chips now come
  from the whole catalog; only their counts narrow.

The pure import mapping moves to `skills-import.ts` so it is unit-testable
without the route's React module graph.
… tree

Follow-up on the review of the previous commit — five of the six were mine:

- The slug probe sat outside the try, so a `/stat` that threw (no ORG_FS_READ,
  object storage unconfigured, a 5xx) became an unhandled rejection: the user
  picked a folder and nothing happened at all. It is inside now, with the
  handler's toast.
- A partially-failed import left the destination directory behind — a broken
  skill in `<available-skills>` if SKILL.md landed, and an undeletable blocker
  on the slug probe if it didn't. The tree is rolled back, but only when the
  probe proved it ours to delete: rolling back unconditionally would delete an
  existing skill whenever the probe itself failed.
- Where `webkitdirectory` is ignored (iOS Safari) the flat selection imported as
  `home/skills/skill` with every subdirectory flattened onto the root. Now
  refused with an explanation.
- `upload.isPending` tracked only the last-started group, so the button
  re-enabled mid-import and a second import could trip the slug guard against
  the directory the first one had just created. One flag across the handler.
- The success toast named the picked folder while every later message named the
  slug. It reports the slug.
- `fetchOrgFsStat` duplicated `useOrgFsStat`'s wire contract; the hook
  delegates to it.
@pedrofrxncx
pedrofrxncx force-pushed the rafavalls/skills-settings-page branch from d8d9341 to cc6aec8 Compare August 31, 2026 17:48
@pedrofrxncx
pedrofrxncx merged commit 5810fbe into main Aug 31, 2026
33 checks passed
@pedrofrxncx
pedrofrxncx deleted the rafavalls/skills-settings-page branch August 31, 2026 17:59
decocms Bot pushed a commit that referenced this pull request Aug 31, 2026
PR: #6662 feat(skills): add a Skills page under Settings → Build
Bump type: minor

- decocms (apps/api/package.json): 4.308.0 -> 4.309.0
- @decocms/native (apps/native/package.json): 4.308.0 -> 4.309.0

Deploy-Scope: web
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude PR authored by a coding agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants