Add Toolr Item
Add a new item to the seedr registry from a local filesystem path.
Workflow
1. Parse the argument
Extract <path> from the user's input (e.g. /add-toolr /Users/daniel/whatever/.claude/hooks/abc).
Verify the path exists (file or directory) using Bash ls or Read.
2. Detect content type
Infer ComponentType from the path. Use the deepest matching segment:
| Path contains | Type |
|---|---|
/skills/ or file named SKILL.md | skill |
/hooks/ | hook |
/agents/ | agent |
/plugins/ or .claude-plugin/ | plugin |
/mcp/ or .mcp.json | mcp |
/settings/ or settings.json | settings |
/commands/ | command |
If ambiguous, ask the user with AskUserQuestion.
3. Derive a default slug
From the path's final meaningful segment (directory name or filename without extension), kebab-case it.
Example: /Users/daniel/whatever/.claude/hooks/pre-commit-lint -> slug pre-commit-lint.
4. Ask clarifying questions
Use AskUserQuestion to collect metadata. Ask in batches to minimize round-trips.
Batch 1 — Identity & scope:
questions:
- question: "What name should this <type> have in the registry?"
header: "Name"
options:
- label: "<auto-derived name>" # Title-cased from slug
description: "Auto-derived from the path"
- label: "Custom name"
description: "Enter a custom display name"
- question: "What is the recommended install scope?"
header: "Scope"
options:
- label: "project (Recommended)"
description: "Install into the current project directory"
- label: "user"
description: "Install into the user's home config"
- label: "local"
description: "Install into .local config (Claude only)"
- question: "Which AI tools is this compatible with?"
header: "Compat"
multiSelect: true
options:
- label: "claude"
description: "Anthropic Claude Code"
- label: "copilot"
description: "GitHub Copilot"
- label: "gemini"
description: "Google Gemini CLI"
- label: "opencode"
description: "OpenCode CLI"
Note: For hooks, agents, settings, and commands, default compatibility to ["claude"] only since those types are Claude-specific. Pre-select accordingly.
Batch 2 — Description:
After the user answers batch 1, read the source content to auto-generate a description. Then ask:
questions:
- question: "Use this description? '<auto-generated description>'"
header: "Description"
options:
- label: "Yes, use it"
description: "Accept the auto-generated description"
- label: "Edit it"
description: "Provide your own description"
5. For hooks: Extract triggers from settings
If the detected type is hook and the path points to a .sh script file:
- •Find the parent
.claude/directory from the script path - •Read both
settings.jsonandsettings.local.jsonin that directory - •Search the
hooksobject for entries that reference this script file - •Extract all triggers (event + matcher combinations)
Example settings.json structure:
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash", "hooks": [{ "type": "command", "command": ".claude/hooks/my-hook.sh" }] },
{ "matcher": "Write", "hooks": [{ "type": "command", "command": ".claude/hooks/my-hook.sh" }] }
]
}
}
From this, extract triggers:
[
{ "event": "PreToolUse", "matcher": "Bash" },
{ "event": "PreToolUse", "matcher": "Write" }
]
Match the script by comparing the filename at the end of the command path.
6. Copy content to registry
Based on the detected type:
- •skill: Copy directory to
registry/skills/<slug>/. Expect aSKILL.mdinside. - •hook: Copy the
.shscript file toregistry/hooks/<slug>/. - •agent: Copy
.mdfile toregistry/agents/<slug>/. - •plugin: Copy directory to
registry/plugins/<slug>/. - •mcp: Copy config to
registry/mcp/<slug>/. - •settings: Copy config to
registry/settings/<slug>/. - •command: Copy to
registry/commands/<slug>/.
Create the target directory if it doesn't exist. Use cp -r for directories, cp for files.
7. Build file tree for manifest
After copying, build a FileTreeNode[] from the copied content. Walk the directory recursively:
FileTreeNode = { name: string, type: "file" | "directory", children?: FileTreeNode[] }
Use find <dir> | sort and parse the output to build the tree.
8. Write item.json and compile manifest
Write the item metadata as registry/<type>s/<slug>/item.json:
{
"slug": "<slug>",
"name": "<name from user>",
"type": "<detected type>",
"description": "<description>",
"compatibility": ["<from user answers>"],
"sourceType": "toolr",
"author": { "name": "Toolr Suite", "url": "https://github.com/toolr-suite" },
"externalUrl": "https://github.com/twiced-technology-gmbh/seedr/tree/main/registry/<type>s/<slug>",
"updatedAt": "<current ISO 8601 date>",
"contents": { "files": [<file tree>] },
"recommendedScope": "<scope from user>"
}
For hooks, also include triggers in the contents object:
{
"contents": {
"files": [{ "name": "my-hook.sh", "type": "file" }],
"triggers": [
{ "event": "PreToolUse", "matcher": "Bash" },
{ "event": "PreToolUse", "matcher": "Write" }
]
}
}
Write with JSON.stringify(item, null, 2) + "\n".
Then recompile the manifest:
npx tsx scripts/compile-manifest.ts
9. Confirm
Print a summary:
- •Type, slug, name
- •Path copied to
- •
item.jsonwritten and manifest compiled - •Remind user to commit and push
Important notes
- •
sourceTypeis always"toolr"— this skill is for manually-maintained items only - •The sync script (
pnpm sync) preserves toolr items and only replaces synced items - •If
registry/<type>s/<slug>/item.jsonalready exists, warn the user and ask whether to update or abort - •For skills, validate that a
SKILL.mdexists in the source directory - •
featureddefaults tofalse— do not set it unless the user asks