# Skills Were Only Half the Answer: Upgrading to Agents, Skills and Commands

> Source: <https://dev.to/nasrulhazim/skills-were-only-half-the-answer-upgrading-to-agents-skills-and-commands-12no>
> Published: 2026-08-03 11:38:29+00:00

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`

files that taught Claude Code my Laravel conventions so I'd stop re-explaining Pest, Action classes and Livewire 4 every session.

It worked. But after a few months of daily use, I hit a ceiling that skills alone couldn't fix.

Today I rewrote the repo. New name, new structure, three layers instead of one: ** nasrulhazim/claude**.

And 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).

This post is the upgrade guide.

Before (`agent-skills` ) |
After (`claude` ) |
|
|---|---|---|
| Repo | `nasrulhazim/agent-skills` |
`nasrulhazim/claude` |
| Content | 14 skills | 29 skills, 20 agents, 10 commands |
| Installs to | `~/.claude/skills/` |
`~/.claude/{skills,agents,commands}/` |
| Install methods | curl script | curl script or plugin marketplace |
| Renames | manual cleanup | automatic via `migrations.txt`
|
| Project-level | copy skills by hand | bundled by Kickoff 1.36.0 |

**Upgrade in one line:**

```
curl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash
```

The installer detects your old skills, removes the renamed ones, and tells you what changed. Read on for what to watch out for.

A skill answers *"how should this be done?"* It carries knowledge and method — Pest patterns, PHPStan workflow, Livewire component structure.

What it doesn't answer is *"who is doing it, and what are they allowed to touch?"*

That distinction turned out to matter a lot. Concretely:

**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.

**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.

**Problem 3 — skills doing two jobs.** `self-update`

was maintaining `CLAUDE.md`

. `api-lifecycle`

covered design through governance. Fine names in isolation, but they didn't compose into a system I could reason about.

So the rewrite split one concept into three.

| Layer | Answers | Loaded | Example |
|---|---|---|---|
Skill |
How is this done? |
On demand, by trigger phrase or `/name`
|
`pest-testing` , `code-quality`
|
Agent |
Who does it, with what tools? |
By delegation, explicit or automatic |
`code-reviewer` , `qa-engineer`
|
Command |
Run this workflow now |
`/name` |
`/upgrade-laravel` , `/docs`
|

The 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.

Here's the agent frontmatter:

```
---
name: code-reviewer
color: orange              # red=security, orange=quality, green=build/ship,
                           # pink=docs/business, blue=design, cyan=audit, yellow=support
description: Use this agent when...   # third-person, trigger-oriented
tools: Read, Grep, Glob, Bash, Skill  # optional allowlist; omit for all tools
---
```

That `tools`

line is the fix for Problem 1. Reviewer, auditor and security roles ship with a read-only allowlist — no `Write`

, no `Edit`

. The reviewer *can't* rewrite your code while reviewing it. That's not a prompt asking nicely, that's a tool boundary.

The `description`

field 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.

One command. It installs everything and cleans up the old names:

```
curl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash
```

Prefer the plugin? Same result, from inside Claude Code:

```
/plugin marketplace add nasrulhazim/claude
```

Pick one — installing both duplicates everything.

The installer handles this for you: it finds the old directories in `~/.claude/skills/`

, removes them, and prints the mapping at the end of the run. Nothing orphaned, nothing competing for the same trigger phrases.

| Old | New |
|---|---|
`api-lifecycle` |
`project-api` |
`faq-generator` |
`project-faq` |
`roadmap-generator` |
`project-roadmap` |
`self-update` |
`project-conventions` |

Only thing left for you: update any notes or scripts still calling the old names.

The repo was renamed, so an old local clone needs a nudge before `bash install.sh`

will work:

```
git remote set-url origin https://github.com/nasrulhazim/claude.git
git pull
```

The curl install always fetches the latest installer, so it's never affected.

**29 skills**, up from 14. The new ones worth knowing:

| Skill | What it does |
|---|---|
`project-laravel` |
Kickoff conventions enforcer and code scaffolder |
`kickoff-patch` |
Patch an existing project to the latest Kickoff baseline via category-grouped 3-way merge |
`project-ddd` |
Pragmatic DDD — domain discovery, migration planning, boundary enforcement |
`project-sync` |
Sync `CLAUDE.md` conventions across multiple Kickoff projects |
`project-inventory` |
Discover and inventory all Claude Code projects, with an HTML dashboard |
`git-workflow` / `gh-workflow`
|
Conventional commits, releases, hooks / GitHub CLI automation |
`log-monitor` |
Production log analysis, error triage, GitHub issue creation |
`soc-analyst` |
Security triage, investigation, remediation, hardening |
`repo-research` |
Deep codebase analysis with structured research docs and diagrams |
`dev-summary` |
Multi-repo development stats, timelines, contributor analytics |

**20 agents** covering every SDLC phase. Rather than listing all of them, here's the mental model — the chains:

| Scenario | Chain |
|---|---|
Feature |
project-manager → business-analyst → software-architect + database-engineer → laravel-developer / api-engineer → code-reviewer + qa-engineer → devops-engineer |
Incident |
support-analyst (triage) → security-analyst or performance-engineer (diagnose) → laravel-developer (fix) → tech-writer (post-mortem) |
Security assurance |
security-analyst (defensive audit) → penetration-tester (scoped, local/staging) → laravel-developer (fix) → security-analyst (re-verify) |
Release |
qa-engineer (suite green) → devops-engineer (changelog, tag, deploy) → tech-writer (release notes) |

Two agents are built specifically to fan out in parallel: `package-maintainer`

(across `~/Packages`

) and `fleet-auditor`

(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.

**When to reach for which:**

| Use a… | When |
|---|---|
| Skill | You need knowledge/method in the current session |
| Agent | You want to delegate a role-shaped task, or fan out |
| Command | You want a repeatable workflow entry point (`/name` ) |

Everything above installs globally to `~/.claude/`

. That's great for me and useless for my team — a teammate cloning the repo gets none of it.

[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.

The mechanism is delightfully boring: Kickoff already mirrors `stubs/`

recursively into every scaffolded app. Drop the assets into `stubs/.claude/`

and they land in every new project with **zero installer changes**.

What ships into generated projects:

| Type | Count | Contents |
|---|---|---|
| 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 |
| 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 |
| Commands | 3 | upgrade-laravel, upgrade-livewire, docs |

Note the curation. The global toolkit has 20 agents and 29 skills; the project bundle has 12 and 17. `sales-planner`

, `svg-logo-system`

, `business-card`

, `courseware-builder`

— those are *my* business tools, not something a Laravel app repo needs. Kickoff itself also carries its own `.claude/`

(5 agents, 8 skills) tuned for package development.

**Refreshing the bundle:**

```
# Defaults to ~/Packages/claude, or pass a path
bin/sync-claude-assets
bin/sync-claude-assets /path/to/claude
```

Idempotent, 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.

Two gotchas from the release notes:

`boost:install --skills`

still runs during scaffolding and writes package-named skills alongside these. If a name ever collides, re-run `bin/sync-claude-assets`

.| Layer | Lives in | Good for |
|---|---|---|
| Global | `~/.claude/` |
Your personal roster — business skills, brand tools, multi-repo agents |
| Project |
`.claude/` (committed) |
Team-shared conventions that must apply to this codebase |

My 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.**

A 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.

This is also why `project-conventions`

(the renamed `self-update`

) matters more than it looks. It maintains `CLAUDE.md`

as 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.

The contributing rules encode the lessons above:

`metadata`

with `compatible_agents`

and `tags`

; put templates and patterns in `references/`

`bash generate-manifest.sh`

before committing; `migrations.txt`

Rules 3 and 5 are the ones I'd steal even if you never touch my repo.

Rule 3 keeps knowledge single-sourced. The moment an agent starts explaining *how* to write a Pest test instead of delegating to `pest-testing`

, you have two copies of that knowledge drifting apart.

Rule 5 is what makes renaming survivable. Without a migration file, every rename leaves a landmine in every user's `~/.claude/`

— a stale skill with overlapping triggers, silently competing with its replacement. Four lines of `old:new`

text turn a breaking change into a clean, self-announcing upgrade.

The installer stays Bash 3.2-compatible, incidentally, so macOS's stock `/bin/bash`

works without anyone installing anything.

The February version of this idea was: *give Claude a reusable module of expertise instead of a long prompt.* That still holds.

What 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.

Skills carry knowledge. Agents carry role and permission. Commands carry workflow. Three layers, one repo, one installer that knows how to upgrade itself.

```
curl -fsSL https://raw.githubusercontent.com/nasrulhazim/claude/main/install.sh | bash
```

**Toolkit:** [github.com/nasrulhazim/claude](https://github.com/nasrulhazim/claude)

**Kickoff:** [github.com/cleaniquecoders/kickoff](https://github.com/cleaniquecoders/kickoff)

PRs open — especially agents. If you've found a role boundary worth encoding, I want to see it.
