diff --git a/README.md b/README.md index 079740a..660b453 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,13 @@ What the dashboard can now do (all state-changing actions require `ADMIN_TOKEN`) (marker-file managed, so hand-installed skills survive), enabled connectors become the run's `--mcp-config` file (nothing lands in the repo tree), and plugins/permissions fold into the generated per-agent `settings.json` — so a change in the UI reaches the next - launch of every agent, no redeploy. + launch of every agent, no redeploy. Skills can also be **installed from a marketplace + prompt** (SkillsMP and friends): paste the page's install prompt and a `skill_install` + command runs it through a one-off headless claude in a staging dir on the worker, then + imports whatever `/SKILL.md` (+ auxiliary files) landed as managed rows. + Headless means nobody can answer questions mid-install, so the wrapped prompt makes the + choices a human would be asked — always user scope, the instructions' defaults — and + reports them in the command result for after-the-fact review. The command queue is exposed over HTTP as `POST …/agents/spawn`, `POST …/agents/{n}/kill`, `POST …/approvals`, `POST …/forge-init`, `POST …/poll-ci`, `POST …/sync`, diff --git a/frontend/components/sections/ClaudeSection.tsx b/frontend/components/sections/ClaudeSection.tsx index ea4c94a..c5d60e2 100644 --- a/frontend/components/sections/ClaudeSection.tsx +++ b/frontend/components/sections/ClaudeSection.tsx @@ -43,6 +43,51 @@ function parseLines(text: string): string[] { const emptySkill = { name: "", description: "", content: "", enabled: true }; +/* Install-from-prompt: paste the "install prompt" a marketplace page (SkillsMP etc.) + * shows, and the worker runs it through a one-off headless claude, importing whatever + * it fetches as managed skills. Headless = nobody to answer questions, so the run makes + * the choices a human would be asked (scope, options) itself — always user scope, + * sensible defaults — and reports them; the import lands below for review/editing. */ +function InstallCard() { + const s = useDashboard(); + const [prompt, setPrompt] = useState(""); + + const run = async () => { + const ok = await s.installClaudeSkill(prompt.trim()); + if (ok) setPrompt(""); + }; + + return ( + +
+ + Install from a marketplace prompt + +
+