with one click
automate
// Expert advisor that helps decide and create the right Claude Code automation
// Expert advisor that helps decide and create the right Claude Code automation
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | automate |
| description | Expert advisor that helps decide and create the right Claude Code automation |
| disable-model-invocation | true |
| hooks | {"PreToolUse":[{"matcher":"Write","hooks":[{"type":"command","command":"\"${CLAUDE_PLUGIN_ROOT}/scripts/guard-json-config.sh\"","statusMessage":"Validating JSON before write..."}]}],"PostToolUse":[{"matcher":"Edit","hooks":[{"type":"command","command":"\"${CLAUDE_PLUGIN_ROOT}/scripts/guard-json-config.sh\"","statusMessage":"Validating JSON after edit..."}]}]} |
Arguments: $ARGUMENTS
Before routing commands, ensure the registry is available.
If ~/.claude/automations-registry.json does NOT exist:
Scan for existing automations created by this plugin (they have created-by: automate markers). This handles reinstallation after uninstall.
~/.claude/skills/*/SKILL.md and .claude/skills/*/SKILL.md for frontmatter containing created-by: automate~/.claude/agents/*.md and .claude/agents/*.md for frontmatter containing created-by: automate~/.claude/settings.json for hook entries with "_meta": {"createdBy": "automate"}.claude/settings.json for the same.mcp.json and ~/.claude.json for MCP entries with "_meta": {"createdBy": "automate"}.lsp.json and ~/.claude/lsp.json for LSP entries with "_meta": {"createdBy": "automate"}For each found automation, reconstruct a registry entry:
{
"id": "recovered-<type>-<name>",
"name": "<extracted from frontmatter or key name>",
"type": "<skill|hook|subagent|permission|custom-command|mcp-server|lsp-server>",
"scope": "<global if in ~/.claude/, project if in .claude/>",
"path": "<absolute path to the file>",
"created": "<file modification time>",
"modified": "<file modification time>",
"description": "<extracted from frontmatter or empty>",
"recovered": true
}
Write the rebuilt registry and report:
"Found N existing automations created by this plugin. Registry rebuilt."
If nothing found → proceed normally (clean start).
Parse $ARGUMENTS to check for sub-commands:
If $ARGUMENTS is list, help, verify, edit, delete, export, import, or cleanup:
Tell the user:
"Management commands are now separate skills for faster execution. Use
/automate-{command}instead. For example:/automate-list,/automate-edit <name>, etc. Run/automate-helpfor the full reference."
Then STOP. Do not proceed to the creation workflow.
Otherwise: Proceed to Create New Automation below.
This skill MUST create EVERYTHING it promises. Partial implementations are FORBIDDEN.
If you decide "Hook + Skill is needed":
If ANY component fails:
An incomplete automation is worse than no automation.
Read the schema files from this plugin to know what values are valid:
plugin/schemas/hooks.json - Valid hook events, types, matchersplugin/schemas/skills.json - Skill frontmatter requirementsplugin/schemas/subagents.json - Subagent configurationplugin/schemas/permissions.json - Permission patternsplugin/schemas/custom-commands.json - Custom command formatplugin/schemas/mcp-servers.json - MCP server configurationplugin/schemas/lsp-servers.json - LSP server configurationplugin/schemas/agent-teams.json - Agent team configurationCRITICAL: Only use values listed in these schemas. Never invent event names or fields.
Use AskUserQuestion for each phase. The interview adapts based on answers to minimize questions.
Ask the user to pick the closest category:
What best describes what you want to create?
1. Something that must happen automatically every time (e.g., check before every commit)
2. Knowledge or rules Claude should follow (e.g., coding standards, project conventions)
3. A workflow I'll trigger manually (e.g., generate boilerplate, run analysis)
4. Integration with external tools/services (e.g., database, API, GitHub)
5. Multiple agents working in parallel on different aspects
6. I'm not sure, help me decide
If answer is 1 (automatic/every time) → Hook path: Ask: "Does it need Claude's intelligence to decide, or is a simple script enough?"
If answer is 2 (knowledge/rules) → Skill or CLAUDE.md path: Ask: "Must this rule be GUARANTEED (can never be skipped), or is it advisory (Claude should follow it but it's not critical)?"
disable-model-invocation: falsedisable-model-invocation: trueIf answer is 3 (manual workflow) → Skill (manual) path: Ask: "Does this workflow need a separate, isolated context (e.g., deep analysis that shouldn't pollute your main conversation)?"
disable-model-invocation: trueIf answer is 4 (external integration) → MCP/LSP path: Ask: "What kind of integration do you need?"
If answer is 5 (parallel agents) → Agent Team path: Proceed directly. Warn about experimental status.
If answer is 6 (not sure) → Full interview: Ask ALL of these questions (one AskUserQuestion with numbered items):
Before proceeding, read ~/.claude/automations-registry.json and check for conflicts:
If conflicts are found, use AskUserQuestion to show them:
Found existing automation that may conflict:
- "pre-commit-check" (hook, PreToolUse → Bash) — "Blocks pushes to main"
What would you like to do?
1. Overwrite the existing automation
2. Rename the new automation
3. Cancel
Propose 3 name options based on the automation's purpose:
Suggested names:
1. pre-commit-tests
2. test-runner-hook
3. commit-guard
Which do you prefer? (or type your own)
Also ask about scope if not yet determined:
~/.claude/....claude/...Based on the answers, use this decision matrix:
| Criterion | Hook | Skill | Skill (manual) | Subagent | Permissions | CLAUDE.md | Custom Cmd | MCP Server | LSP Server | Agent Team |
|---|---|---|---|---|---|---|---|---|---|---|
| Must happen ALWAYS without exceptions | YES | no | no | no | no | no | no | no | no | no |
| Rule about what Claude can/cannot do | no | no | no | no | YES | maybe | no | no | no | no |
| Domain knowledge applied automatically | no | YES | no | no | no | maybe | no | no | no | no |
| Complex workflow invoked manually | no | no | YES | no | no | no | no | no | no | no |
| Needs separate/isolated context | no | no | no | YES | no | no | no | no | no | no |
| Independent review/analysis | no | no | no | YES | no | no | no | no | no | no |
| Simple global rule | no | no | no | no | no | YES | no | no | no | no |
| Shortcut for frequent prompt | no | no | no | no | no | no | YES | no | no | no |
| External tool/service integration | no | no | no | no | no | no | no | YES | no | no |
| Code intelligence/language analysis | no | no | no | no | no | no | no | no | YES | no |
| Parallel multi-agent orchestration | no | no | no | no | no | no | no | no | no | YES |
Hook + Skill - When it must always happen (hook) but requires complex logic (skill)
~/.claude/scripts/settings.json with VALID event (PreToolUse, PostToolUse, etc.)~/.claude/skills/[name]/SKILL.mdrelatedHook/relatedSkill linksSkill + Subagent - When the skill defines the workflow but needs a subagent for deep analysis
~/.claude/agents/[name].mdPermissions + CLAUDE.md - Permissions for technical block, CLAUDE.md to explain why
settings.jsonCLAUDE.mdMCP Server + Skill - External tool access + workflow orchestration
.mcp.jsonAgent Team + Skill - Multi-agent orchestration + domain knowledge
~/.claude/teams/{name}/config.jsonAfter the decision and before explaining, show the user a concrete preview of what will be created. This helps the user confirm the approach is correct before any files are written.
For a Hook:
Here's what will be created:
~/.claude/settings.json (hook entry):
{
"hooks": {
"PreToolUse": [{"matcher": "Bash", "hooks": [{"type": "command", "command": "~/.claude/scripts/your-hook.sh"}]}]
}
}
~/.claude/scripts/your-hook.sh (executable script):
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# ... your logic here ...
For a Skill:
Here's what will be created:
~/.claude/skills/skill-name/SKILL.md:
---
name: skill-name
description: What this skill does
disable-model-invocation: true
created-by: automate
---
# Skill Title
...
For a Subagent:
Here's what will be created:
~/.claude/agents/agent-name.md:
---
name: agent-name
description: What this agent does
tools: Read, Grep, Glob, Bash
model: inherit
created-by: automate
---
...
For MCP Server:
Here's what will be created:
.mcp.json (or ~/.claude.json for global):
{
"mcpServers": {
"server-name": {
"type": "stdio",
"command": "path/to/server",
"args": []
}
}
}
For combinations, show all components that will be created.
Adapt the example to use the actual names, events, and logic discussed during the interview. Use AskUserQuestion to confirm: "Does this look right? (Yes / Adjust / Cancel)"
Before creating, explain to the user:
If the decision involves a COMBINATION (e.g., Hook + Skill), explicitly list ALL components:
CREATION PLAN:
[ ] Component 1: Hook (PreToolUse → Bash) - enforces the rule
[ ] Component 2: Skill (semver) - provides the logic
CRITICAL: You MUST create ALL components. Do NOT proceed to Step 6 until all boxes are checked.
Ask for confirmation before proceeding.
CRITICAL: Before creating any file, validate against the schemas.
Every automation created MUST be registered.
After creating the files, add to ~/.claude/automations-registry.json:
{
"id": "unique-id",
"name": "automation-name",
"type": "skill|hook|subagent|permission|custom-command|claude-md|mcp-server|lsp-server|agent-team",
"scope": "global|project",
"path": "path/to/main/file",
"created": "ISO-timestamp",
"modified": "ISO-timestamp",
"description": "what it does"
}
Add created-by: automate marker to files:
For Skills/Subagents (markdown frontmatter):
---
name: skill-name
description: ...
created-by: automate
---
For JSON configs (hooks, permissions, custom-commands): Add to the specific entry:
{
"_meta": {
"createdBy": "automate",
"createdAt": "ISO-timestamp"
}
}
For MCP/LSP configs (JSON): Same pattern as hooks:
{
"_meta": {
"createdBy": "automate",
"createdAt": "ISO-timestamp"
}
}
For Agent Teams (JSON): Same pattern:
{
"_meta": {
"createdBy": "automate",
"createdAt": "ISO-timestamp"
}
}
ONLY use these valid events (from schemas/hooks.json):
SessionStart - Session begins (matchers: startup, resume, clear, compact)SessionEnd - Session ends (matchers: clear, resume, logout, prompt_input_exit, other, bypass_permissions_disabled)UserPromptSubmit - When user submits a prompt (no matcher)PreToolUse - Before a tool executes (matchers: Bash, Edit, Write, Edit|Write, mcp__.*)PostToolUse - After a tool succeeds (same matchers as PreToolUse)PostToolUseFailure - After a tool failsPermissionRequest - When permission dialog appearsNotification - When Claude needs attention (matchers: permission_prompt, idle_prompt)Stop - When Claude finishes responding (no matcher)StopFailure - When turn ends due to API error (matchers: rate_limit, authentication_failed, billing_error, invalid_request, server_error, max_output_tokens, unknown; output ignored)PreCompact - Before context compaction (matchers: manual, auto)PostCompact - After context compaction completes (matchers: manual, auto)SubagentStart, SubagentStop - Subagent lifecycleTeammateIdle - Agent team teammate about to go idle (matchers: agent name; exit 2 only)TaskCreated - Task being created via TaskCreate (no matcher; exit 2 prevents creation)TaskCompleted - Task being marked completed (no matcher; exit 2 only)ConfigChange - Config file changed during session (matchers: user_settings, project_settings, local_settings, policy_settings, skills)InstructionsLoaded - When CLAUDE.md or .claude/rules/*.md loaded (matchers: session_start, nested_traversal, path_glob_match, include, compact; exit code ignored)WorktreeCreate - When a worktree is being created (no matcher; any non-zero exit fails creation)WorktreeRemove - When a worktree is being removed (no matcher)Elicitation - When MCP server requests user input (matchers: MCP server name regex)ElicitationResult - After user responds to MCP elicitation (matchers: MCP server name regex)CwdChanged - When working directory changes, e.g. cd (no matcher; useful for direnv)FileChanged - When a watched file changes on disk (matchers: filename basename, e.g. .envrc, .env)PermissionDenied - When user denies a permission request (matchers: tool name; non-blocking, informational)NEVER use these (they don't exist):
Correct structure:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "your-command-here"
}
]
}
]
}
}
NEVER overwrite settings.json. Always merge.
Adding a hook:
~/.claude/settings.json (use {} if it doesn't exist).hooks["EventName"][]
.hooks doesn't exist → set to {}.hooks["EventName"] doesn't exist → set to []Removing a hook:
hooks[].command matches
(or match via _meta.createdBy: "automate" + automation name)Never write a partial hooks object — always include all existing events.
Hook handler fields:
type (string, required): command, http, prompt, or agent. All events support all 4 types.if (string, optional): Permission rule syntax filter — only runs hook when tool/event matches (e.g. Bash(git *))command (string): Shell command to run (command type)prompt (string): Prompt text (prompt/agent type)url (string): URL endpoint (http type, required)headers (object): HTTP headers (http type, optional; supports $VAR interpolation from environment)allowedEnvVars (array): Environment variables to include in http request (http type, optional)async (boolean): Run hook in background without blocking Claude (command type only)shell (string): Shell to use — bash (default) or powershell (Windows). Requires CLAUDE_CODE_USE_POWERSHELL_TOOL=1timeout (integer): Timeout in seconds. Defaults: command=600, prompt=30, agent=60statusMessage (string): Custom spinner message while hook runsmodel (string): Model for prompt/agent hooks (default: haiku)once (boolean): Run hook only once per sessionExit codes:
Input modification (PreToolUse only):
PreToolUse hooks can modify tool inputs via hookSpecificOutput.updatedInput. When a hook returns JSON with an updatedInput field, Claude will use the modified input instead of the original.
Hook input (stdin):
Hook commands receive a JSON object via stdin with the full context. Read it with cat or jq:
cat | jq -r '.tool_name' - Name of the toolcat | jq -r '.tool_input.file_path' - Tool input fieldscat | jq -r '.tool_input.command' - Bash command (for Bash tool)Note: TOOL_INPUT and CLAUDE_TOOL_INPUT env vars are NOT set. Always read from stdin.
Environment variables available to hooks (no tool input):
CLAUDE_PROJECT_DIR - Project directory pathCLAUDE_SESSION_ID - Current session identifierCLAUDE_ENV_FILE - File path for persisting environment variables (SessionStart hooks)CLAUDE_PLUGIN_ROOT - Root directory of the pluginCLAUDE_PLUGIN_DATA - Directory for plugin persistent data (survives plugin updates)CLAUDE_CODE_REMOTE - Set to 'true' in remote/web environmentsUse templates from ${CLAUDE_SKILL_DIR}/../../templates/hook-*.json as a base.
Location: .claude/skills/[name]/SKILL.md (project) or ~/.claude/skills/[name]/SKILL.md (global)
Required frontmatter:
---
name: skill-name
description: What this skill does
disable-model-invocation: true|false
created-by: automate
---
Use template from ${CLAUDE_SKILL_DIR}/../../templates/skill.md.
Location: .claude/agents/[name].md (project) or ~/.claude/agents/[name].md (global)
Required frontmatter:
---
name: agent-name
description: What this agent does
tools: Read, Grep, Glob, Bash
model: inherit
created-by: automate
---
Valid tools: Agent, AskUserQuestion, Bash, CronCreate, CronDelete, CronList, Edit, EnterPlanMode, EnterWorktree, ExitPlanMode, ExitWorktree, Glob, Grep, ListMcpResourcesTool, LSP, Monitor, NotebookEdit, PowerShell, Read, ReadMcpResourceTool, SendMessage, ShareOnboardingGuide, Skill, TaskCreate, TaskGet, TaskList, TaskOutput, TaskStop, TaskUpdate, TeamCreate, TeamDelete, TodoWrite, ToolSearch, WebFetch, WebSearch, Write
MCP tools can also be used as mcp__<server>__<tool>
Valid models: opus, sonnet, haiku, inherit
Optional frontmatter fields:
disallowedTools - Tools the subagent cannot usepermissionMode - Permission handling mode (default, acceptEdits, dontAsk, bypassPermissions, plan)skills - Skills to preload into subagent context at startuphooks - Hooks specific to the subagentmemory - Persistent memory scope (user, project, local)maxTurns - Maximum number of agentic turnsmcpServers - MCP servers scoped to this subagentbackground - Always run as background task (boolean)isolation - Set to 'worktree' for isolated git worktreeeffort - Effort level: low, medium, high, max (Opus 4.6 only)initialPrompt - Auto-submitted as first user turn when running as main session agent (via --agent)Use template from ${CLAUDE_SKILL_DIR}/../../templates/subagent.md.
Location: .claude/settings.json
{
"permissions": {
"allow": ["Bash(git commit *)"],
"deny": ["Bash(git push *)"]
}
}
Warning: Does NOT work with --dangerously-skip-permissions. Use Hooks instead for guaranteed blocks.
Location: .claude/settings.json
{
"customCommands": {
"name": "prompt text"
}
}
Add the rule to ./CLAUDE.md (project) or ~/.claude/CLAUDE.md (global).
Location: .mcp.json (project) or ~/.claude.json (global, under mcpServers key)
Structure:
{
"mcpServers": {
"server-name": {
"type": "stdio",
"command": "path/to/server",
"args": ["--flag"],
"env": {"KEY": "value"}
}
}
}
Valid types: stdio, http, sse (deprecated), ws
command fieldurl field, optional headers and oauth (recommended for remote)url field (deprecated, use http instead)url field, WebSocket transportmcp__<server>__<tool> in Claude"matcher": "mcp__servername__.*"Use template from ${CLAUDE_SKILL_DIR}/../../templates/mcp-server.json.
Location: .lsp.json (project) or ~/.claude/lsp.json (global)
Structure:
{
"server-name": {
"command": "path/to/lsp-server",
"args": ["--stdio"],
"languages": ["typescript", "javascript"]
}
}
Required: command, languages array Optional: args, initializationOptions
Use template from ${CLAUDE_SKILL_DIR}/../../templates/lsp-server.json.
Location: ~/.claude/teams/{team-name}/config.json
Structure:
{
"name": "team-name",
"description": "What the team does",
"agents": [
{
"name": "agent-name",
"role": "What this agent does",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "inherit"
}
]
}
Teams are orchestrated via natural language, not declarative config. The team config defines agents and their capabilities; coordination happens through Claude's reasoning.
Warning: Requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 environment variable. Agent Teams are experimental and may change.
Valid teammateMode (configured in settings.json as teammateMode): in-process, tmux, auto
Valid models: opus, sonnet, haiku, inherit
Use template from ${CLAUDE_SKILL_DIR}/../../templates/agent-team.json.
This skill has built-in PreToolUse/PostToolUse hooks that automatically validate JSON before Write and after Edit operations on config files (settings.json, .mcp.json, .lsp.json, etc.). If the JSON is malformed, the write is blocked and you will see the jq error — fix the JSON and retry.
Before creating any configuration file, verify against schemas:
hooks array with type and commandmcpServers key exists, each server has type and either command (stdio) or url (http/sse/ws)command and languages arrayname/description/agents exist, each agent has nameIf validation fails, show the error and do NOT create the file.
After writing ANY JSON config file, ALWAYS run:
jq . <file-path> > /dev/null
If this fails, the file is broken. Read it back, fix the JSON, and rewrite.
CRITICAL: A malformed JSON config file will silently break Claude Code — it won't start and gives no error. This is the single most important validation step.
BEFORE showing results to user, verify ALL planned components were created:
If ANY component is missing or invalid:
If any component fails validation and cannot be fixed after 2 attempts, roll back ALL created components:
~/.claude/automations-registry.jsonAfter rollback, show the user exactly what was rolled back and why:
ROLLBACK — could not complete automation after 2 attempts:
Rolled back:
- Deleted ~/.claude/scripts/check-semver.sh
- Removed hook entry from ~/.claude/settings.json (PreToolUse → Bash)
- Removed registry entry "semver-hook"
Reason: Hook script failed validation — invalid jq syntax on line 12
Please fix the issue and try again with /automate <description>.
An incomplete automation is worse than no automation — always roll back rather than leave broken components.
Hook + Skill:
relatedHook/relatedSkill linksSkill + Subagent:
Permissions + CLAUDE.md:
MCP Server + Skill:
Agent Team + Skill:
MANDATORY: Test that the automation actually works before finishing.
# Test the hook script by sending JSON via stdin (how hooks actually receive input)
echo '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | ~/.claude/scripts/your-hook.sh
echo $? # Should be 0 (allow) or 2 (block)
If the test fails:
/skills listdisable-model-invocation: false, verify Claude recognizes when to use itOnly after ALL verifications pass:
Show the CREATION PLAN with all boxes checked:
CREATION COMPLETE:
[x] Component 1: Hook - ~/.claude/scripts/check-semver.sh
[x] Component 2: Skill - ~/.claude/skills/semver/SKILL.md
Show test results:
TESTS PASSED:
[x] Hook blocks when VERSION not staged (exit 2)
[x] Hook allows when VERSION is staged (exit 0)
[x] Skill registered and visible
Explain how to use the automation
Confirm all components are in the registry
If you cannot complete all steps, explicitly tell the user what failed and why.
--dangerously-skip-permissions, Permissions won't work. Suggest Hook as an alternative for blocks.~/.claude/automations-registry.json for management with list/edit/delete/export/import.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 and are experimental. The feature may change or be removed.mcp__<server>__<tool> in Claude and can be matched in hooks using "matcher": "mcp__servername__.*".http sends requests to a URL endpoint; use headers for auth with $VAR interpolation and allowedEnvVars to expose env vars.