Repository navigation
feat(tui): browse and install Skill Stacks with /stacks - #366
Merged
Merged
Conversation
Adds the TUI's first way onto the CoDev SkillHub: `/stacks` (and the unbound `prompt_stacks` keybind) opens a browser for the hub's Skill Stacks, then walks scope (this project or global), an agent preset, and — only when prepare reports collisions — a skip-or-overwrite choice before installing. Escaping the conflict prompt discards the staging rather than leaving it to the server's TTL. Everything goes through the server's v2.skillhub routes (#364), so the install lands on the host that runs the agent, in the same folders `codev skill stack pull` writes. After a successful install the dialog disposes the server instance — what a config update does too — because skill discovery is cached per instance and nothing else invalidates it; without that the model would not see the new skills until a restart. Flow state lives in an awaited controller rather than components, as in dialog-configure.tsx: dialog.replace stores the element factory and can re-invoke it. And since replace() fires every prior step's onClose even when this flow advances itself, "did the user escape mid-download?" is answered by checking whether the dialog still shows the step we put up. The agent picker is a preset list because DialogSelect is single-choice (a per-row toggle needs its own keybind, like dialog.mcp.toggle); CoDev Code is in every preset and is folded in server-side regardless. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P1MfYkJD3tQZRgqBKB4gig
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
P2 of the Skill Stack integration (P0 #361 → CLI, P1 #364 → server routes). The TUI's first way onto the CoDev SkillHub.
What it does
/stacks(also theprompt_stackskeybind, unbound by default likeprompt_skills) opens a browser for the hub's Skill Stacks beside/skills. Pick one → This project or Global → an agent preset → the dialog callsprepare, and only if the hub reports skills already installed does it stop to ask skip them or overwrite them (naming the collisions). Then it installs, refreshes, and toastsInstalled N of M skill(s) from <stack>, K skipped.Escaping the conflict prompt discards the staging rather than leaving it for the server's TTL. Escaping during download does the same once the download returns; the flow never installs into a dialog the user has already left.
Why it's shaped this way
v2.skillhubroutes). The install lands on the host that runs the agent — the same.claude/skills+.agents/skillsfolderscodev skill stack pullwrites.QUESTION(Dax)incore/src/skill.ts), so after a successful install the dialog callsinstance.dispose— exactly what a config update already does — and the next request rebuilds it. Without this a/stacksinstall would be invisible until restart.dialog-configure.tsxpattern):dialog.replacestores the element factory and may re-invoke it. And sincereplace()fires every prior step'sonCloseeven when this flow advances itself, "did the user escape mid-step?" is answered by checking whether the dialog still shows the factory we put up (stillShowing), never viaonClose.DialogSelectis single-choice; a per-row toggle needs a registered keybind likedialog.mcp.toggle, which is more upstream surface than the choice warrants today. CoDev Code is in every preset and folded in server-side regardless.Tests
packages/tui/test/skill-stack.view.test.tsxboots the real app against a fetch fixture and drives the whole flow through rendered frames: browse → scope → agents → conflict prompt → install → toast, asserting/instance/disposewas called exactly once and nothing was discarded; a second test escapes at the conflict prompt and asserts the staging was discarded and nothing installed.Full TUI suite 271 pass / 0 fail; keymap test and opencode's
test/cli/run(which pins keybind defaults) pass;bun typecheckclean.Bookkeeping
DIVERGENCES.mdrow forprompt/index.tsx+config/keybind.ts(the two upstream files touched; the dialog and test are fork-only).CHANGELOG.md→ Unreleased → Skills.codev-landing-page(content/docs/code) —/stacksandprompt_stacksneed a line there once this ships.Next: P3, the desktop app's Stacks tab on the same routes.
🤖 Generated with Claude Code
https://claude.ai/code/session_01P1MfYkJD3tQZRgqBKB4gig