
Multica Skill Importing
- 19 installs
- 44k repo stars
- Updated August 5, 2026
- multica-ai/multica
Helps with ai & agent building tasks during AI-assisted development.
About
multica-skill-importing is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- multica-skill-importing
- AI & Agent Building
- AI-coding skill
Multica Skill Importing by the numbers
- 19 all-time installs (skills.sh)
- +7 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #10,571 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/multica-ai/multica --skill multica-skill-importingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 19 |
|---|---|
| repo stars | ★ 44k |
| Last updated | August 5, 2026 |
| Repository | multica-ai/multica ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Importing skills into Multica
Use this skill when the user already provided a skill URL, slug, or a clear intent to import a specific skill into the current Multica workspace.
Do not use this skill to decide which skill the user needs. If the user only describes a capability and no URL is known, external search may produce candidate URLs, but this import skill starts only once a URL or concrete import target is known.
Every claim below is traced to source in references/skill-importing-source-map.md. When in doubt, read that file.
The invariant
A skill is installed for Multica only when it exists in the current workspace's skill database. The single supported path that puts it there is the workspace import endpoint, driven by this CLI:
multica skill import --url <url> --output jsonThe CLI defaults to --on-conflict fail. Current CLIs send:
POST /api/skills/import
body: { "url": "<url>", "on_conflict": "fail" }Do not finish with npx skills add. That installs into an external/local skill environment, not the Multica workspace DB, so Multica cannot manage or bind it.
Supported URL source families
detectImportSource accepts these hosts (and www. variants). Pass any of these forms to multica skill import --url <url> --output json:
multica skill import --url clawhub.ai/owner/skill --output json
multica skill import --url skills.sh/owner/repo/skill --output json
multica skill import --url github.com/owner/repo --output json
multica skill import --url github.com/owner/repo/tree/main/path/to/skill --output json
multica skill import --url github.com/owner/repo/blob/main/path/to/SKILL.md --output jsonclawhub.ai,skills.sh,github.comare the recognized hosts.- A GitHub URL may be a bare
owner/repo, a/tree/{ref}/...directory, or a
/blob/{ref}/.../SKILL.md file.
- A bare ClawHub slug (no host) is accepted and routed to ClawHub.
- Any other host is rejected with a 400 naming the supported sources.
Direct URL flow
1. When the request contains a concrete URL, the import endpoint can be called directly; search is not required by the API:
multica skill import --url <url> --output json2. Treat the response as the source of truth. Current CLI imports use the structured import result envelope:
{
"status": "created|updated|conflict|skipped|failed",
"reason": "...",
"skill": { "...": "SkillWithFilesResponse when created/updated" },
"existing_skill": { "id": "...", "name": "...", "can_overwrite": true }
}For created / updated, skill is a workspace SkillWithFilesResponse: it embeds the standard SkillResponse and adds the supporting files array. Report the relevant fields:
statusandreasonwhen present.skill.id/skill.name/skill.description.skill.config.origin(provenance: which source the skill was imported from —
set only when the source supplied an origin, so treat it as possibly absent).
skill.files/ files count.skill.created_at/skill.updated_at.existing_skill.id/existing_skill.namewhen status isconflict,
skipped, or failed due to an existing skill.
Because the response is structured, read these returned fields instead of guessing whether the import succeeded.
3. Agent-skill binding is a separate mutable operation. add preserves existing assignments and appends the new id:
multica agent skills add <agent-id> --skill-ids <skill-id> --output json
multica agent skills list <agent-id> --output jsonAfter the final multica agent skills list <agent-id> --output json, verify the target skill id is present before claiming the skill is available to that agent.
Additive add vs replace-all set
multica agent skills add is additive: the server inserts the assignments without clearing existing ones (AddAgentSkills).
multica agent skills set is replace-all: the server clears every current assignment, then re-adds exactly the ids you pass (SetAgentSkills). set is the replacement path. Passing only one id to set leaves the agent with only that one skill and drops every previous assignment.
Reserved SKILL.md supporting file
A skill's primary content is its SKILL.md. That filename is reserved: the daemon writes the primary content to SKILL.md itself when preparing the execution environment, so a supporting file may not also be named SKILL.md (IsReservedContentPath; the check cleans the path and is case-insensitive, so ./SKILL.md and sub/../SKILL.md are caught too).
Practical effect when importing or creating a skill: if the manifest lists a supporting file named SKILL.md, the server silently drops it — the import still succeeds, but that entry will be absent from the returned files. So if a supporting file you expected is missing, check whether it was named SKILL.md; rename it to a non-reserved path. (The hard 400 rejection — "SKILL.md is reserved for the primary skill content" — only fires on the dedicated single-file endpoint PUT /api/skills/{id}/files, not on import.)
Same-name conflicts: --on-conflict
Default behavior is safe: multica skill import --url <url> is equivalent to --on-conflict fail. If the imported skill name already exists, the command prints a structured conflict result and exits non-zero; no skill is created or updated.
Choose an explicit strategy only when the user asked for it or the intent is clear:
--on-conflict fail(default): do nothing on conflict; report `status:
conflict` with a reason that suggests overwrite or rename.
--on-conflict overwrite: update the existing same-name skill in place, but
only if the current user is the skill's original creator. This preserves the skill ID, created_by, created_at, and agent-skill bindings; it replaces description, content, provenance config, and supporting files. Non-creators get status: failed.
--on-conflict rename: create a new skill with an automatic suffix such as
-2 / -3; the existing skill is untouched.
--on-conflict skip: leave the existing skill untouched and report `status:
skipped`.
Concrete examples:
# Safe default. Fails with status=conflict if review-helper already exists.
multica skill import --url https://skills.sh/acme/repo/review-helper --output json
# Replace the existing same-name skill, preserving its ID and agent bindings.
multica skill import --url https://skills.sh/acme/repo/review-helper --on-conflict overwrite --output json
# Keep the existing skill and import a copy such as review-helper-2.
multica skill import --url https://skills.sh/acme/repo/review-helper --on-conflict rename --output json
# Batch-friendly behavior: leave the existing skill alone and mark it skipped.
multica skill import --url https://skills.sh/acme/repo/review-helper --on-conflict skip --output jsonLegacy compatibility: clients that do not send on_conflict keep the old contract. A duplicate import returns 409 and the body carries the existing workspace skill identity:
{
"error": "a skill with this name already exists",
"existing_skill": {
"id": "<skill-id>",
"name": "<skill-name>"
}
}Current CLI normalizes that legacy shape into status: conflict and exits non-zero for the default fail strategy. Treat existing_skill.id and existing_skill.name as the source of truth, then fetch details if needed:
multica skill get <skill-id> --output jsonOlder servers may return a 409 whose body is only a string like a skill with this name already exists, with no existing_skill key. Recover by finding the existing workspace skill yourself:
multica skill list --output json
multica skill get <skill-id> --output jsonThen report that the skill already exists and include its id / name. Do not retry in a loop, and do not create a second skill under a different name just to dodge the conflict.
Incorrect → correct
Incorrect (bypasses Multica):
npx skills add https://skills.sh/owner/repo/skillThe skill may exist locally, but Multica cannot manage it as a workspace skill.
Incorrect agent binding for a normal add (replaces every existing assignment):
Using set with only the new skill id wipes the agent's other skills. For an add, use add.
Correct import:
multica skill import --url https://skills.sh/owner/repo/skill --output jsonAgent binding after import, when the caller intentionally wants to mutate that agent's skill assignments:
multica agent skills add <agent-id> --skill-ids <skill-id> --output json
multica agent skills list <agent-id> --output jsonReferences
references/skill-importing-source-map.md— every behavior above mapped to
file:line in server/, plus the verification command to re-derive the lines.
Skill-importing source map
Evidence layer for multica-skill-importing. Every behavioral claim in SKILL.md maps to a real code path below with file:line. Paths are relative to the repo root (multica/).
Re-derive before trusting: line numbers drift. To re-verify a single anchor, grep the symbol and read its surroundings, e.g.:
grep -n "func (h \*Handler) ImportSkill" server/internal/handler/skill.go
grep -n "func runSkillImport" server/cmd/multica/cmd_skill.go
grep -n "func IsReservedContentPath" server/internal/skill/reserved.goImport endpoint and route
| Behavior | File:line |
|---|---|
ImportSkill handler (POST /api/skills/import) | server/internal/handler/skill.go:1882 |
Decodes ImportSkillRequest ({ "url": ..., "on_conflict": ... }) | server/internal/handler/skill.go:1895-1899, struct at :553 |
Validates on_conflict (fail, overwrite, rename, skip) | server/internal/handler/skill.go:1900-1908, helper validImportOnConflict at :566 |
| Detects source family + normalizes URL | server/internal/handler/skill.go:1910 (calls detectImportSource) |
Persists provenance into config.origin | server/internal/handler/skill.go:1944-1948 — set only when imported.origin != nil; otherwise config stays {} and origin is absent |
| Structured conflict dispatcher | server/internal/handler/skill.go:1813-1878 |
Builds skill + files via createSkillWithFiles (def server/internal/handler/skill_create.go:77, tx body :29) | wrapped by createImportedSkillWithName at server/internal/handler/skill.go:1774 |
Structured success: 201 Created with {status:"created", skill} when on_conflict was sent | server/internal/handler/skill.go:1985-1988 |
Legacy success: 201 Created with bare SkillWithFilesResponse when on_conflict was omitted | server/internal/handler/skill.go:1990 |
Route registration r.Post("/import", h.ImportSkill) | server/cmd/server/router.go:874 |
CLI: multica skill import --url
| Behavior | File:line |
|---|---|
skill import command def | server/cmd/multica/cmd_skill.go:60-64 |
--url flag | server/cmd/multica/cmd_skill.go:142 |
--on-conflict flag (default fail) | server/cmd/multica/cmd_skill.go:143 |
--output flag (default json) | server/cmd/multica/cmd_skill.go:144 |
runSkillImport | server/cmd/multica/cmd_skill.go:412 |
Requires --url | server/cmd/multica/cmd_skill.go:418-421 |
Reads and validates --on-conflict | server/cmd/multica/cmd_skill.go:422-425 |
Sends on_conflict in the request body | server/cmd/multica/cmd_skill.go:428-431 |
POST /api/skills/import | server/cmd/multica/cmd_skill.go:436 |
| Structured HTTP error body handling | server/cmd/multica/cmd_skill.go:437-440, handleSkillImportError at :454 |
Prints structured result (json or table) | server/cmd/multica/cmd_skill.go:443, helper at :497 |
Same-name conflict handling
| Behavior | File:line |
|---|---|
SkillImportResult (status, reason, skill, existing_skill) | server/internal/handler/skill.go:104-109 |
ExistingSkillIdentity (id, name, created_by, can_overwrite) | server/internal/handler/skill.go:112-117 |
| Pre-create lookup for structured conflict flow | server/internal/handler/skill.go:1951-1962 |
| Race-safe unique-violation fallback into structured conflict flow | server/internal/handler/skill.go:1966-1971 |
Default fail: status:"conflict" and HTTP 409 | server/internal/handler/skill.go:1872-1877 |
overwrite: creator-only update, preserves skill identity/bindings via overwriteSkillWithFiles | server/internal/handler/skill.go:1823-1852, tx helper at server/internal/handler/skill_create.go:133 |
rename: creates suffixed name with bounded attempts | server/internal/handler/skill.go:1854-1870, helper at :1786 |
skip: returns status:"skipped" and leaves existing skill untouched | server/internal/handler/skill.go:1816-1821 |
Legacy duplicate branch when on_conflict was omitted | server/internal/handler/skill.go:1973-1978 |
Legacy duplicate response {error, existing_skill} | server/internal/handler/skill.go:118-123 |
CLI normalizes legacy {existing_skill} body into status:"conflict" | server/cmd/multica/cmd_skill.go:454-482, helper at :484 |
Response shape: SkillWithFilesResponse
| Behavior | File:line |
|---|---|
SkillWithFilesResponse = embedded SkillResponse + Files []SkillFileResponse | server/internal/handler/skill.go:99-102 |
SkillResponse fields (id, workspace_id, name, description, content, config, created_by, created_at, updated_at) | server/internal/handler/skill.go:41-51 |
SkillFileResponse fields | server/internal/handler/skill.go:80-87 |
createSkillWithFilesInTx returns SkillWithFilesResponse{SkillResponse, Files} | server/internal/handler/skill_create.go:66-69 |
config.origin set on import | server/internal/handler/skill.go:1947 |
For current CLI imports, SkillWithFilesResponse appears under SkillImportResult.skill when status is created or updated. Legacy clients that omit on_conflict still receive a bare SkillWithFilesResponse.
URL source families (detectImportSource)
| Behavior | File:line |
|---|---|
detectImportSource | server/internal/handler/skill.go:773-804 |
skills.sh / www.skills.sh | server/internal/handler/skill.go:791-792 |
clawhub.ai / www.clawhub.ai | server/internal/handler/skill.go:793-794 |
github.com / www.github.com | server/internal/handler/skill.go:795-796 |
| Bare slug (no host) defaults to ClawHub | server/internal/handler/skill.go:798-800 |
parseGitHubURL handles /tree/{ref}/... and /blob/{ref}/.../SKILL.md | server/internal/handler/skill.go:1450-1503 (tree/blob check :1463-1480) |
Additive add vs replace-all set
| Behavior | File:line |
|---|---|
AddAgentSkills (additive: AddAgentSkill loop, no RemoveAll) | server/internal/handler/skill.go:2161; loop :2192-2200 |
Route POST /api/agents/{id}/skills/add | server/cmd/server/router.go:851 |
SetAgentSkills (replace-all: RemoveAllAgentSkills then re-add) | server/internal/handler/skill.go:2106; RemoveAllAgentSkills :2138; re-add :2143-2151 |
Route PUT /api/agents/{id}/skills | server/cmd/server/router.go:850 |
CLI agent skills add def ("without replacing existing assignments") | server/cmd/multica/cmd_agent.go:125-130 |
runAgentSkillsAdd → POST .../skills/add | server/cmd/multica/cmd_agent.go:797; POST :818 |
CLI agent skills set def ("replaces all current assignments") | server/cmd/multica/cmd_agent.go:118-123 |
runAgentSkillsSet → PUT .../skills | server/cmd/multica/cmd_agent.go:772; PUT :790 |
CLI agent skills list | server/cmd/multica/cmd_agent.go:740; GET :750 |
Reserved primary-content filename (SKILL.md)
| Behavior | File:line |
|---|---|
ContentFilename = "SKILL.md" | server/internal/skill/reserved.go:12 |
IsReservedContentPath (cleans path, case-insensitive compare) | server/internal/skill/reserved.go:25-27 |
Import/create path: reserved supporting file is silently skipped (continue) | server/internal/handler/skill_create.go:50-54 |
UpdateSkill (PUT /api/skills/{id}) replace-files path: also silently skips | server/internal/handler/skill.go:490-494 |
UpsertSkillFile (PUT /api/skills/{id}/files): rejects 400 "SKILL.md is reserved for the primary skill content" | server/internal/handler/skill.go:2014; reserved check :2034-2036 |
Reason SKILL.md is reserved: the daemon writes the skill's Content to that path itself when preparing the execution environment, so a supporting file may not also claim it (server/internal/skill/reserved.go:8-24).
Behavior is path-shape-dependent. On import or create a manifest's SKILL.md supporting file is dropped (it will not appear in the returned files), so the import still succeeds — it does not 400. The hard 400 rejection fires only on the dedicated single-file endpoint PUT /api/skills/{id}/files.