· Paul Lukic · 7 min read · coographnamingslash-commandsuxmigration

Eleven Names, One Namespace: Unifying Coograph Under /coograph-*

Coograph's skills and slash commands used to live under three different prefixes. As of today, every shipped command starts with /coograph-. Here's why, what changed, and how existing projects pick it up automatically.

In this post

A tool you have to remember is a tool you don’t use. That was the most honest way to describe the state of Coograph’s command surface up until this week.

If you wanted to start a new ticket, you typed /project:new-ticket (or sometimes just new-ticket, depending on which tool was hosting Claude). If you wanted to propose a spec change, you typed openspec-propose. To rebuild the code graph: rebuild-code-graph. To run the planner: /project:plan. Three prefixes — openspec-, /project:, and bare names — for skills that all ship as one product. The autocomplete menu was a coin flip.

As of PR #10 (closes #9), there is exactly one prefix.

Diagram showing the eleven old skill and slash-command names — openspec-propose, openspec-apply, openspec-archive, openspec-explore, new-ticket, rebuild-code-graph, /project:plan, /project:review, /project:verify, /project:debug, /project:explore — converging via orange arrows into a single rounded panel labeled /coograph-*

The rename map

Skills:

OldNew
openspec-proposecoograph-propose
openspec-applycoograph-apply
openspec-archivecoograph-archive
openspec-explorecoograph-explore
new-ticketcoograph-new-ticket
rebuild-code-graphcoograph-rebuild-graph

Slash commands (Claude Code):

OldNew
/project:plan/coograph-plan
/project:review/coograph-review
/project:verify/coograph-verify
/project:debug/coograph-debug
/project:explore/coograph-search
/project:new-ticket/coograph-new-ticket

coograph-init was already correct, and we left it alone.

The one new name worth a sentence is /coograph-search. The old /project:explore was a tactical codebase Q&A command — “where is this defined, who calls that, find every place we use X.” We had a separate skill called openspec-explore whose actual content was a thinking-mode prompt — pair-programmer-style brainstorming before you write a spec. Both got “explore” in their old name, but they aren’t the same thing, and merging them would have lost a feature. Renaming the codebase-search command to /coograph-search keeps both, and the slash command’s new name finally describes what it does.

Why this was annoying — and why we waited

The old prefixes carried real meaning at the time they were introduced.

openspec-* came from the OpenSpec spec format we adopted for the Plan → Propose → Apply workflow. It was a sensible label for “this skill works on a spec file.” Then we added a thinking-mode prompt and called it openspec-explore, which it wasn’t, and the name started lying to users.

/project:* is Claude Code’s namespace for slash commands a user authors per project. We piggybacked on it because the first three commands (plan, review, debug) felt like project-flow commands, not coograph-specific. But within months we shipped five of them, all coograph-specific. The namespace was the wrong fit.

new-ticket and rebuild-code-graph were just the things that fell through the cracks. They predated any attempt at a prefix.

We waited to fix this because rename PRs are deceptively expensive. The actual git mv is fast. What’s slow is everything downstream: documentation references, agent prompts that mention the old names by string, the migration burden for users with .claude/commands/ files synced months ago. We wanted to do it once.

Three phases in one PR

The shipped change is three phases, which we’ll cover briefly because each one had a separate trap.

Phase 1 — skill rename. Move six directories under .github/skills/, update each SKILL.md frontmatter name: field to match, fix every cross-reference between skills. We caught one collision risk early: the renamed coograph-explore (thinking-mode) would have collided with a slash command also named explore. We split the slash command to /coograph-search to keep both. Phase 1 alone touched ~15 files and was the easy phase.

Phase 2 — slash command move. Move five .claude/commands/project/*.md files to top-level .claude/commands/coograph-*.md, update every prose reference in README.md, CLAUDE.md, the planner agent, MIGRATION.md, plus the workflow docs on this site (in three locales). Doing this after Phase 1 meant the touch order was: rename skills → rename commands that reference skills → update docs that reference commands. Out-of-order edits would have left dangling pointers between commits.

Phase 3 — the sync script. This is the phase that actually decides whether existing users see the change. We’ll spend the rest of the post on it.

How existing projects pick up the rename automatically

Every project that ran /coograph-init registers itself in the coograph repo’s projects.json and gets pulled into a sync loop: when the coograph product repo updates, a post-merge git hook runs .github/sync.py, which walks every registered project and copies template files into it. This is how your local Coograph install stays current without manually re-running init.

The pre-rename sync.py had two gaps that would have made the namespace change invisible to existing users:

  1. It only synced .claude/commands/project/ (the subdirectory). The new coograph-*.md wrappers at the top level of .claude/commands/ were never touched. Users would have seen no new /coograph-* slash commands after pulling.
  2. It only synced .github/skills/ if your project had the vscode tool enabled. Claude-only projects would not have received the new coograph-*/ skill directories.

A third gap — sync only adds, it doesn’t remove — would have left the old openspec-*/, new-ticket/, and rebuild-code-graph/ directories sitting next to the new ones. Autocomplete would have shown both old and new names side-by-side forever.

Phase 3 fixes all three:

# .github/sync.py — new top-level constant

OBSOLETE_PATHS = (
    # 2026-05-18 coograph-skill-rename — old skill dirs
    ".github/skills/openspec-propose",
    ".github/skills/openspec-apply",
    ".github/skills/openspec-archive",
    ".github/skills/openspec-explore",
    ".github/skills/new-ticket",
    ".github/skills/rebuild-code-graph",
    # 2026-05-18 coograph-skill-rename — old slash command wrappers
    ".claude/commands/project/new-ticket.md",
    ".claude/commands/project/plan.md",
    ".claude/commands/project/review.md",
    ".claude/commands/project/verify.md",
    ".claude/commands/project/debug.md",
    ".claude/commands/project/explore.md",
)

A new _cleanup_obsolete(project_path) helper walks that tuple after every sync and removes anything in the list that still exists at the consumer site. Adding entries to OBSOLETE_PATHS is now the canonical way to propagate a rename or removal through the install base — no per-user manual rm commands required.

.github/skills/ was promoted out of the VS Code section into an always-copy block, mirroring what coograph-init already does at install time. And a small block inside the Claude tool path now globs .claude/commands/coograph-*.md and copies each top-level wrapper.

Last thing: a --dry-run flag. Sync is now destructive (cleanup deletes files), so we wanted a way to preview what a sync would do without actually doing it. python .github/sync.py --dry-run reads the registry, logs every action it would take with a [DRY-RUN] prefix, skips _ensure_hooks(), and skips the code-graph rebuild. Cheap insurance against a bad OBSOLETE_PATHS entry.

What you need to do

If your project is registered in projects.json (the default for anyone who ran /coograph-init):

cd path/to/coograph
git pull

That’s it. The post-merge hook fires, sync runs, your project gets the new .claude/commands/coograph-*.md files, your old openspec-*/ skill dirs disappear, your old project/*.md wrappers disappear, and your existing CLAUDE.md and copilot-instructions.md are untouched (those are SKIP_FILES — user-owned).

If you want to preview first:

python .github/sync.py --dry-run

If your project is not registered, or you’re pinned to a pre-rename sync.py, there’s a manual recipe in MIGRATION.md at the coograph repo. Two rm -rf commands and a hand-update of your CLAUDE.md references using a grep we provide.

What we kept on the floor

There is one piece of cleanup we deliberately did not ship in this PR: a check that any code in your repo or your CI references the old names. We have a planned “cross-tool drift checker” — issue #2 in the roadmap — that will catch stale references at lint time. Bundling drift detection into the rename PR was tempting; we said no because the rename is already three phases and we wanted a clean blast radius.

The roadmap entry for issue #9 also still references the old names in its brief field on coograph.com/roadmap, because it’s the historical description of work just shipped. It will come down in a separate PR alongside closing the GitHub issue.

The smaller meta-point

Naming is one of those things where the cost of getting it wrong compounds linearly with usage, and the cost of fixing it scales with reach. We have somewhere between dozens and hundreds of installs (the registry is local, we don’t track) and the rename touched 23 files across two repositories. Six months from now it would have touched twice as many.

If you’re building tooling that humans type at — slash commands, CLI subcommands, anything — the lesson is to pick the canonical prefix on day one and never adopt a second one. We didn’t, and this PR is what catching up looks like.

If you’re a Coograph user, you do nothing. git pull does it for you. That’s the part we’re proudest of.

Cut your AI coding bill 30–80%. Coograph is MIT-licensed and free forever. Pro is bespoke services.