{"slug": "skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands", "title": "Skills Were Only Half the Answer: Upgrading to Agents, Skills and Commands", "summary": "Developer Nasrul Hazim rewrote his agent-skills repository into a three-layer system of skills, agents, and commands, now named nasrulhazim/claude, to overcome limitations of skills alone. The new structure separates knowledge (skills), role personas with tool restrictions (agents), and workflow triggers (commands), and is bundled into projects via Kickoff 1.36.0. Key improvements include read-only tool boundaries for reviewers and automatic migration from the old setup.", "body_md": "Back in February I wrote about [agent-skills](https://dev.to/nasrulhazim/teaching-claude-code-to-think-like-a-laravel-developer-introducing-agent-skills-58cm) — a repo of `SKILL.md`\n\nfiles that taught Claude Code my Laravel conventions so I'd stop re-explaining Pest, Action classes and Livewire 4 every session.\n\nIt worked. But after a few months of daily use, I hit a ceiling that skills alone couldn't fix.\n\nToday I rewrote the repo. New name, new structure, three layers instead of one: ** nasrulhazim/claude**.\n\nAnd because most of my projects are scaffolded from Kickoff, the same roster now ships into every generated app via [Kickoff 1.36.0](https://github.com/cleaniquecoders/kickoff/releases/tag/1.36.0).\n\nThis post is the upgrade guide.\n\nBefore (`agent-skills` ) |\nAfter (`claude` ) |\n|\n|---|---|---|\n| Repo | `nasrulhazim/agent-skills` |\n`nasrulhazim/claude` |\n| Content | 14 skills | 29 skills, 20 agents, 10 commands |\n| Installs to | `~/.claude/skills/` |\n`~/.claude/{skills,agents,commands}/` |\n| Install methods | curl script | curl script or plugin marketplace |\n| Renames | manual cleanup | automatic via `migrations.txt`\n|\n| Project-level | copy skills by hand | bundled by Kickoff 1.36.0 |\n\n**Upgrade in one line:**\n\n```\ncurl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash\n```\n\nThe installer detects your old skills, removes the renamed ones, and tells you what changed. Read on for what to watch out for.\n\nA skill answers *\"how should this be done?\"* It carries knowledge and method — Pest patterns, PHPStan workflow, Livewire component structure.\n\nWhat it doesn't answer is *\"who is doing it, and what are they allowed to touch?\"*\n\nThat distinction turned out to matter a lot. Concretely:\n\n**Problem 1 — reviewers that write code.** I'd ask for a code review, and Claude would helpfully \"fix\" things mid-review. A review should produce findings, not commits. A skill can *say* \"don't edit files\"; it can't *enforce* it.\n\n**Problem 2 — no fan-out.** I maintain 20+ packages. Bumping a dependency across all of them is the same role repeated 20 times in parallel. Skills are loaded into one session; there's no unit to delegate and multiply.\n\n**Problem 3 — skills doing two jobs.** `self-update`\n\nwas maintaining `CLAUDE.md`\n\n. `api-lifecycle`\n\ncovered design through governance. Fine names in isolation, but they didn't compose into a system I could reason about.\n\nSo the rewrite split one concept into three.\n\n| Layer | Answers | Loaded | Example |\n|---|---|---|---|\nSkill |\nHow is this done? |\nOn demand, by trigger phrase or `/name`\n|\n`pest-testing` , `code-quality`\n|\nAgent |\nWho does it, with what tools? |\nBy delegation, explicit or automatic |\n`code-reviewer` , `qa-engineer`\n|\nCommand |\nRun this workflow now |\n`/name` |\n`/upgrade-laravel` , `/docs`\n|\n\nThe key design rule: **agents are thin.** An agent is a 25–75 line role persona that loads skills as its playbook. It does not duplicate skill content. Knowledge lives in exactly one place — the skill — and agents are just personas pointing at it.\n\nHere's the agent frontmatter:\n\n```\n---\nname: code-reviewer\ncolor: orange              # red=security, orange=quality, green=build/ship,\n                           # pink=docs/business, blue=design, cyan=audit, yellow=support\ndescription: Use this agent when...   # third-person, trigger-oriented\ntools: Read, Grep, Glob, Bash, Skill  # optional allowlist; omit for all tools\n---\n```\n\nThat `tools`\n\nline is the fix for Problem 1. Reviewer, auditor and security roles ship with a read-only allowlist — no `Write`\n\n, no `Edit`\n\n. The reviewer *can't* rewrite your code while reviewing it. That's not a prompt asking nicely, that's a tool boundary.\n\nThe `description`\n\nfield is the routing key. Claude matches your natural request against agent descriptions, which is why they're written in third person and trigger-oriented rather than as instructions to the agent.\n\nOne command. It installs everything and cleans up the old names:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash\n```\n\nPrefer the plugin? Same result, from inside Claude Code:\n\n```\n/plugin marketplace add nasrulhazim/claude\n```\n\nPick one — installing both duplicates everything.\n\nThe installer handles this for you: it finds the old directories in `~/.claude/skills/`\n\n, removes them, and prints the mapping at the end of the run. Nothing orphaned, nothing competing for the same trigger phrases.\n\n| Old | New |\n|---|---|\n`api-lifecycle` |\n`project-api` |\n`faq-generator` |\n`project-faq` |\n`roadmap-generator` |\n`project-roadmap` |\n`self-update` |\n`project-conventions` |\n\nOnly thing left for you: update any notes or scripts still calling the old names.\n\nThe repo was renamed, so an old local clone needs a nudge before `bash install.sh`\n\nwill work:\n\n```\ngit remote set-url origin https://github.com/nasrulhazim/claude.git\ngit pull\n```\n\nThe curl install always fetches the latest installer, so it's never affected.\n\n**29 skills**, up from 14. The new ones worth knowing:\n\n| Skill | What it does |\n|---|---|\n`project-laravel` |\nKickoff conventions enforcer and code scaffolder |\n`kickoff-patch` |\nPatch an existing project to the latest Kickoff baseline via category-grouped 3-way merge |\n`project-ddd` |\nPragmatic DDD — domain discovery, migration planning, boundary enforcement |\n`project-sync` |\nSync `CLAUDE.md` conventions across multiple Kickoff projects |\n`project-inventory` |\nDiscover and inventory all Claude Code projects, with an HTML dashboard |\n`git-workflow` / `gh-workflow`\n|\nConventional commits, releases, hooks / GitHub CLI automation |\n`log-monitor` |\nProduction log analysis, error triage, GitHub issue creation |\n`soc-analyst` |\nSecurity triage, investigation, remediation, hardening |\n`repo-research` |\nDeep codebase analysis with structured research docs and diagrams |\n`dev-summary` |\nMulti-repo development stats, timelines, contributor analytics |\n\n**20 agents** covering every SDLC phase. Rather than listing all of them, here's the mental model — the chains:\n\n| Scenario | Chain |\n|---|---|\nFeature |\nproject-manager → business-analyst → software-architect + database-engineer → laravel-developer / api-engineer → code-reviewer + qa-engineer → devops-engineer |\nIncident |\nsupport-analyst (triage) → security-analyst or performance-engineer (diagnose) → laravel-developer (fix) → tech-writer (post-mortem) |\nSecurity assurance |\nsecurity-analyst (defensive audit) → penetration-tester (scoped, local/staging) → laravel-developer (fix) → security-analyst (re-verify) |\nRelease |\nqa-engineer (suite green) → devops-engineer (changelog, tag, deploy) → tech-writer (release notes) |\n\nTwo agents are built specifically to fan out in parallel: `package-maintainer`\n\n(across `~/Packages`\n\n) and `fleet-auditor`\n\n(read-only sweeps for drift and inventory across many repos). That's Problem 2 solved — *\"fan out package-maintainer across these 10 packages\"* is now a single instruction.\n\n**When to reach for which:**\n\n| Use a… | When |\n|---|---|\n| Skill | You need knowledge/method in the current session |\n| Agent | You want to delegate a role-shaped task, or fan out |\n| Command | You want a repeatable workflow entry point (`/name` ) |\n\nEverything above installs globally to `~/.claude/`\n\n. That's great for me and useless for my team — a teammate cloning the repo gets none of it.\n\n[Kickoff 1.36.0](https://github.com/cleaniquecoders/kickoff/releases/tag/1.36.0) fixes that by committing a curated roster into the project itself.\n\nThe mechanism is delightfully boring: Kickoff already mirrors `stubs/`\n\nrecursively into every scaffolded app. Drop the assets into `stubs/.claude/`\n\nand they land in every new project with **zero installer changes**.\n\nWhat ships into generated projects:\n\n| Type | Count | Contents |\n|---|---|---|\n| Agents | 12 | api-engineer, code-reviewer, database-engineer, devops-engineer, laravel-developer, performance-engineer, qa-engineer, security-analyst, software-architect, tech-writer, ui-designer, upgrade-specialist |\n| Skills | 17 | project-laravel, livewire-flux, pest-testing, code-quality, php-best-practices, design-patterns, project-api, project-ddd, git-workflow, gh-workflow, ci-cd-pipeline, kickoff-patch, log-monitor, project-conventions, project-docs, project-roadmap, project-faq |\n| Commands | 3 | upgrade-laravel, upgrade-livewire, docs |\n\nNote the curation. The global toolkit has 20 agents and 29 skills; the project bundle has 12 and 17. `sales-planner`\n\n, `svg-logo-system`\n\n, `business-card`\n\n, `courseware-builder`\n\n— those are *my* business tools, not something a Laravel app repo needs. Kickoff itself also carries its own `.claude/`\n\n(5 agents, 8 skills) tuned for package development.\n\n**Refreshing the bundle:**\n\n```\n# Defaults to ~/Packages/claude, or pass a path\nbin/sync-claude-assets\nbin/sync-claude-assets /path/to/claude\n```\n\nIdempotent, with the curated lists at the top of the script so you can edit what's included. The bundle is a **snapshot** — it doesn't auto-track the toolkit. Re-run the sync each Kickoff release.\n\nTwo gotchas from the release notes:\n\n`boost:install --skills`\n\nstill runs during scaffolding and writes package-named skills alongside these. If a name ever collides, re-run `bin/sync-claude-assets`\n\n.| Layer | Lives in | Good for |\n|---|---|---|\n| Global | `~/.claude/` |\nYour personal roster — business skills, brand tools, multi-repo agents |\n| Project |\n`.claude/` (committed) |\nTeam-shared conventions that must apply to this codebase |\n\nMy rule: **if a teammate needs it to work on this repo, it goes in the project. If it's how I personally work, it stays global.**\n\nA code reviewer that knows the project's Kickoff conventions belongs in the repo — committed, versioned, reviewed like any other code. My logo designer does not.\n\nThis is also why `project-conventions`\n\n(the renamed `self-update`\n\n) matters more than it looks. It maintains `CLAUDE.md`\n\nas you correct Claude during a session. Committed to the repo, that file becomes shared institutional memory — gotchas one developer discovered on Tuesday are available to everyone on Wednesday.\n\nThe contributing rules encode the lessons above:\n\n`metadata`\n\nwith `compatible_agents`\n\nand `tags`\n\n; put templates and patterns in `references/`\n\n`bash generate-manifest.sh`\n\nbefore committing; `migrations.txt`\n\nRules 3 and 5 are the ones I'd steal even if you never touch my repo.\n\nRule 3 keeps knowledge single-sourced. The moment an agent starts explaining *how* to write a Pest test instead of delegating to `pest-testing`\n\n, you have two copies of that knowledge drifting apart.\n\nRule 5 is what makes renaming survivable. Without a migration file, every rename leaves a landmine in every user's `~/.claude/`\n\n— a stale skill with overlapping triggers, silently competing with its replacement. Four lines of `old:new`\n\ntext turn a breaking change into a clean, self-announcing upgrade.\n\nThe installer stays Bash 3.2-compatible, incidentally, so macOS's stock `/bin/bash`\n\nworks without anyone installing anything.\n\nThe February version of this idea was: *give Claude a reusable module of expertise instead of a long prompt.* That still holds.\n\nWhat I got wrong was assuming expertise was the only missing piece. A skill tells Claude how to review code. It doesn't stop Claude from writing code while reviewing. It doesn't let you say \"do this role across twenty repos.\" It doesn't survive a rename.\n\nSkills carry knowledge. Agents carry role and permission. Commands carry workflow. Three layers, one repo, one installer that knows how to upgrade itself.\n\n```\ncurl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash\n```\n\n**Toolkit:** [github.com/nasrulhazim/claude](https://github.com/nasrulhazim/claude)\n\n**Kickoff:** [github.com/cleaniquecoders/kickoff](https://github.com/cleaniquecoders/kickoff)\n\nPRs open — especially agents. If you've found a role boundary worth encoding, I want to see it.", "url": "https://wpnews.pro/news/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands", "canonical_source": "https://dev.to/nasrulhazim/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands-12no", "published_at": "2026-08-03 11:38:29+00:00", "updated_at": "2026-08-03 11:44:50.727557+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools", "large-language-models"], "entities": ["Nasrul Hazim", "Claude Code", "Kickoff", "nasrulhazim/claude", "nasrulhazim/agent-skills", "Pest", "Livewire", "PHPStan"], "alternates": {"html": "https://wpnews.pro/news/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands", "markdown": "https://wpnews.pro/news/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands.md", "text": "https://wpnews.pro/news/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands.txt", "jsonld": "https://wpnews.pro/news/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands.jsonld"}}