Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 50 additions & 50 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,34 +57,34 @@ moicle/
│ │ ├── bootstrap.md
│ │ ├── brainstorm.md
│ │ └── marketing.md
│ └── skills/ # Nested namespace: /group:action
│ └── skills/ # nested in repo, flattened to /group-action on install
│ ├── feature/
│ │ ├── new/ # /feature:new
│ │ ├── refactor/ # /feature:refactor
│ │ ├── api/ # /feature:api
│ │ └── deprecate/ # /feature:deprecate
│ │ ├── new/ # /feature-new
│ │ ├── refactor/ # /feature-refactor
│ │ ├── api/ # /feature-api
│ │ └── deprecate/ # /feature-deprecate
│ ├── fix/
│ │ ├── hotfix/ # /fix:hotfix
│ │ ├── root-cause/ # /fix:root-cause
│ │ ├── incident/ # /fix:incident
│ │ └── pr-comment/ # /fix:pr-comment
│ │ ├── hotfix/ # /fix-hotfix
│ │ ├── root-cause/ # /fix-root-cause
│ │ ├── incident/ # /fix-incident
│ │ └── pr-comment/ # /fix-pr-comment
│ ├── review/
│ │ ├── branch/ # /review:branch
│ │ ├── pr/ # /review:pr
│ │ ├── architect/ # /review:architect
│ │ └── tdd/ # /review:tdd
│ │ ├── branch/ # /review-branch
│ │ ├── pr/ # /review-pr
│ │ ├── architect/ # /review-architect
│ │ └── tdd/ # /review-tdd
│ ├── research/
│ │ ├── web/ # /research:web
│ │ ├── spike/ # /research:spike
│ │ └── onboarding/ # /research:onboarding
│ │ ├── web/ # /research-web
│ │ ├── spike/ # /research-spike
│ │ └── onboarding/ # /research-onboarding
│ ├── docs/
│ │ ├── write/ # /docs:write
│ │ └── sync/ # /docs:sync
│ │ ├── write/ # /docs-write
│ │ └── sync/ # /docs-sync
│ └── marketing/
│ ├── content/ # /marketing:content
│ ├── seo-blog/ # /marketing:seo-blog
│ ├── logo/ # /marketing:logo
│ └── video/ # /marketing:video
│ ├── content/ # /marketing-content
│ ├── seo-blog/ # /marketing-seo-blog
│ ├── logo/ # /marketing-logo
│ └── video/ # /marketing-video
├── package.json
└── README.md
```
Expand Down Expand Up @@ -144,54 +144,54 @@ Comprehensive marketing plan wizard - combines logo design, video content, and c

## Skills (21)

Skills are nested under 5 namespaces. Folder path becomes the trigger: `skills/<group>/<action>/SKILL.md` → `/<group>:<action>`. Old trigger phrases stay in `description` so Claude still auto-invokes the right skill from natural language.
Skills are organized into 6 groups in this repo as `skills/<group>/<action>/SKILL.md`. Claude Code only scans skills **one level deep** and uses the **folder name** as the slash-command name — it does not recurse into nested group folders. So the installer **flattens** each nested skill to a single-level `<group>-<action>` entry: `skills/fix/root-cause/` → `~/.claude/skills/fix-root-cause/` → `/fix-root-cause`. A hyphen is used (not a colon) because `:` is an invalid filename character on Windows. Old trigger phrases stay in `description` so Claude still auto-invokes the right skill from natural language.

See `README.md` for the decision matrix when multiple skills overlap.

### `/feature:*` — Build & Change
### `/feature-*` — Build & Change
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/feature:new` | "implement feature", "add feature", "build feature", "create feature" |
| `/feature:refactor` | "refactor", "clean up", "improve code", "restructure", "migrate to ddd" |
| `/feature:api` | "integrate api", "add endpoint", "new api", "connect api" |
| `/feature:deprecate` | "deprecate", "remove feature", "sunset", "phase out" |
| `/feature-new` | "implement feature", "add feature", "build feature", "create feature" |
| `/feature-refactor` | "refactor", "clean up", "improve code", "restructure", "migrate to ddd" |
| `/feature-api` | "integrate api", "add endpoint", "new api", "connect api" |
| `/feature-deprecate` | "deprecate", "remove feature", "sunset", "phase out" |

### `/fix:*` — Bugs & Incidents
### `/fix-*` — Bugs & Incidents
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/fix:hotfix` | "fix bug", "hotfix", "urgent fix", "production issue" |
| `/fix:root-cause` | "deep debug", "trace bug", "find root cause", "hard bug" |
| `/fix:incident` | "incident", "outage", "production down", "service down" |
| `/fix:pr-comment` | "fix pr comment", "fix review comment", "address pr feedback" |
| `/fix-hotfix` | "fix bug", "hotfix", "urgent fix", "production issue" |
| `/fix-root-cause` | "deep debug", "trace bug", "find root cause", "hard bug" |
| `/fix-incident` | "incident", "outage", "production down", "service down" |
| `/fix-pr-comment` | "fix pr comment", "fix review comment", "address pr feedback" |

### `/review:*` — Review & Quality
### `/review-*` — Review & Quality
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/review:branch` | "review changes", "review branch", "check branch", "review before pr" |
| `/review:pr` | "review pr", "check pr", "review code", "pr review" |
| `/review:architect` | "architect-review", "architecture review", "review ddd" |
| `/review:tdd` | "tdd", "test first", "test driven", "red green refactor" |
| `/review-branch` | "review changes", "review branch", "check branch", "review before pr" |
| `/review-pr` | "review pr", "check pr", "review code", "pr review" |
| `/review-architect` | "architect-review", "architecture review", "review ddd" |
| `/review-tdd` | "tdd", "test first", "test driven", "red green refactor" |

### `/research:*` — Explore & Learn
### `/research-*` — Explore & Learn
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/research:web` | "research", "tìm giải pháp", "find best practice", "so sánh giải pháp" |
| `/research:spike` | "spike", "prototype", "poc", "explore" |
| `/research:onboarding` | "explain codebase", "onboard", "new to project", "understand project" |
| `/research-web` | "research", "tìm giải pháp", "find best practice", "so sánh giải pháp" |
| `/research-spike` | "spike", "prototype", "poc", "explore" |
| `/research-onboarding` | "explain codebase", "onboard", "new to project", "understand project" |

### `/docs:*` — Project Documentation
### `/docs-*` — Project Documentation
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/docs:write` | "document", "generate docs", "write docs" |
| `/docs:sync` | "sync docs", "sync documentation", "doc sync" |
| `/docs-write` | "document", "generate docs", "write docs" |
| `/docs-sync` | "sync docs", "sync documentation", "doc sync" |

### `/marketing:*` — Brand & Content (wrapped by `/marketing` command)
### `/marketing-*` — Brand & Content (wrapped by `/marketing` command)
| Skill | Trigger phrases (auto-invoke) |
|-------|------------------------------|
| `/marketing:content` | "write content", "content strategy", "content plan", "newsletter" |
| `/marketing:seo-blog` | "write seo blog", "seo blog", "evergreen post", "compare post", "blog for AI" |
| `/marketing:logo` | "design logo", "create logo", "brand identity" |
| `/marketing:video` | "create video", "video content", "video script" |
| `/marketing-content` | "write content", "content strategy", "content plan", "newsletter" |
| `/marketing-seo-blog` | "write seo blog", "seo blog", "evergreen post", "compare post", "blog for AI" |
| `/marketing-logo` | "design logo", "create logo", "brand identity" |
| `/marketing-video` | "create video", "video content", "video script" |

## Development

Expand Down
76 changes: 38 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,78 +118,78 @@ moicle install --target antigravity --global

### Skills (21)

Skills are grouped into 6 namespaces. Type `/<group>:<tab>` in Claude Code to see all skills in a group.
Skills are grouped by a `<group>-` prefix. Type `/<group>-` then `Tab` in Claude Code to see all skills in a group.

**`/feature:*` — Build & Change**
**`/feature-*` — Build & Change**

| Skill | When to use |
|-------|-------------|
| `/feature:new` | Build a new feature end-to-end following DDD |
| `/feature:refactor` | Restructure existing module to DDD or improve internals |
| `/feature:api` | Add a new endpoint or integrate an external API |
| `/feature:deprecate` | Safely sunset a feature, API, or module |
| `/feature-new` | Build a new feature end-to-end following DDD |
| `/feature-refactor` | Restructure existing module to DDD or improve internals |
| `/feature-api` | Add a new endpoint or integrate an external API |
| `/feature-deprecate` | Safely sunset a feature, API, or module |

**`/fix:*` — Bugs & Incidents**
**`/fix-*` — Bugs & Incidents**

| Skill | When to use |
|-------|-------------|
| `/fix:hotfix` | Fix a bug fast with a rollback plan |
| `/fix:root-cause` | Hard-to-trace bug that has been "fixed" multiple times |
| `/fix:incident` | Production outage / on-call workflow |
| `/fix:pr-comment` | Address review comments on an existing PR |
| `/fix-hotfix` | Fix a bug fast with a rollback plan |
| `/fix-root-cause` | Hard-to-trace bug that has been "fixed" multiple times |
| `/fix-incident` | Production outage / on-call workflow |
| `/fix-pr-comment` | Address review comments on an existing PR |

**`/review:*` — Review & Quality**
**`/review-*` — Review & Quality**

| Skill | When to use |
|-------|-------------|
| `/review:branch` | Self-review your branch BEFORE pushing / opening PR |
| `/review:pr` | Review someone else's open PR |
| `/review:architect` | DDD compliance check (called by `/feature:new` / `/feature:refactor`) |
| `/review:tdd` | Drive implementation with test-first discipline |
| `/review-branch` | Self-review your branch BEFORE pushing / opening PR |
| `/review-pr` | Review someone else's open PR |
| `/review-architect` | DDD compliance check (called by `/feature-new` / `/feature-refactor`) |
| `/review-tdd` | Drive implementation with test-first discipline |

**`/research:*` — Explore & Learn**
**`/research-*` — Explore & Learn**

| Skill | When to use |
|-------|-------------|
| `/research:web` | Search the web for solutions / best practices |
| `/research:spike` | Time-boxed prototype to learn / decide |
| `/research:onboarding` | Get up to speed on a new codebase |
| `/research-web` | Search the web for solutions / best practices |
| `/research-spike` | Time-boxed prototype to learn / decide |
| `/research-onboarding` | Get up to speed on a new codebase |

**`/docs:*` — Project Documentation**
**`/docs-*` — Project Documentation**

| Skill | When to use |
|-------|-------------|
| `/docs:write` | Author docs manually (README / API / ARCH / CONTRIB) |
| `/docs:sync` | Auto-generate structured docs from codebase with review loop |
| `/docs-write` | Author docs manually (README / API / ARCH / CONTRIB) |
| `/docs-sync` | Auto-generate structured docs from codebase with review loop |

**`/marketing:*` — Brand & Content** (wrapped by the `/marketing` command)
**`/marketing-*` — Brand & Content** (wrapped by the `/marketing` command)

| Skill | When to use |
|-------|-------------|
| `/marketing:content` | Multi-post content strategy (pillars, calendar, channels) |
| `/marketing:seo-blog` | Write ONE evergreen blog post optimized for Search + AI tools |
| `/marketing:logo` | Logo + brand identity specification |
| `/marketing:video` | Video script, storyboard, production plan |
| `/marketing-content` | Multi-post content strategy (pillars, calendar, channels) |
| `/marketing-seo-blog` | Write ONE evergreen blog post optimized for Search + AI tools |
| `/marketing-logo` | Logo + brand identity specification |
| `/marketing-video` | Video script, storyboard, production plan |

### Skill decision matrix

When more than one skill could fit, use this matrix:

| Situation | Use | Not |
|-----------|-----|-----|
| Bug just happened in prod, need fix in <1h | `/fix:hotfix` | `/fix:root-cause` (too slow) |
| Bug keeps coming back after "fixes" | `/fix:root-cause` | `/fix:hotfix` (will repeat) |
| About to push / open PR | `/review:branch` | `/review:pr` (that's for others') |
| Reviewing teammate's PR | `/review:pr` | `/review:branch` (that's for own branch) |
| Want to verify DDD compliance only | `/review:architect` | `/review:pr` (broader scope) |
| Don't know the right solution yet | `/research:web` | `/research:spike` (skip if you can decide from docs) |
| Need to validate an idea by building | `/research:spike` | `/feature:new` (commit only after spike) |
| Writing README / API docs by hand | `/docs:write` | `/docs:sync` (overkill for single file) |
| Generating full docs site from codebase | `/docs:sync` | `/docs:write` (manual is slower) |
| Bug just happened in prod, need fix in <1h | `/fix-hotfix` | `/fix-root-cause` (too slow) |
| Bug keeps coming back after "fixes" | `/fix-root-cause` | `/fix-hotfix` (will repeat) |
| About to push / open PR | `/review-branch` | `/review-pr` (that's for others') |
| Reviewing teammate's PR | `/review-pr` | `/review-branch` (that's for own branch) |
| Want to verify DDD compliance only | `/review-architect` | `/review-pr` (broader scope) |
| Don't know the right solution yet | `/research-web` | `/research-spike` (skip if you can decide from docs) |
| Need to validate an idea by building | `/research-spike` | `/feature-new` (commit only after spike) |
| Writing README / API docs by hand | `/docs-write` | `/docs-sync` (overkill for single file) |
| Generating full docs site from codebase | `/docs-sync` | `/docs-write` (manual is slower) |

### Backward compatibility

Old trigger phrases still work — they're kept in the skill `description` so Claude auto-invokes the right skill when the user says e.g. "deep debug", "hotfix", "review changes". The namespace `/group:action` is the new explicit invocation form.
Old trigger phrases still work — they're kept in the skill `description` so Claude auto-invokes the right skill when the user says e.g. "deep debug", "hotfix", "review changes". The flattened name `/group-action` is the explicit invocation form.

## Architecture-First Approach

Expand Down
12 changes: 8 additions & 4 deletions src/commands/install/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
getArchitectureDir,
getClaudeDir,
getFiles,
getDirs,
listSkillsNested,
} from '../../utils/symlink.js';
import { printInstalled } from './print.js';

Expand Down Expand Up @@ -55,10 +55,14 @@ const installCommands = (targetDir: string, useSymlink: boolean): FileResult[] =
const installSkills = (targetDir: string, useSymlink: boolean): FileResult[] => {
ensureDir(targetDir);
const skillsDir = path.join(ASSETS_DIR, 'skills');
// Claude Code scans skills one level deep and uses the folder name as the
// slash-command name. Nested groups (skills/<group>/<action>/SKILL.md) are
// flattened to a single-level "<group>-<action>" entry so each becomes
// /<group>-<action>.
const results = fs.existsSync(skillsDir)
? getDirs(skillsDir).map((dir) => {
const target = path.join(targetDir, path.basename(dir));
return useSymlink ? createSymlink(dir, target) : copyDir(dir, target);
? listSkillsNested(skillsDir).map((skill) => {
const target = path.join(targetDir, skill.name);
return useSymlink ? createSymlink(skill.path, target) : copyDir(skill.path, target);
})
: [];
printInstalled('Skills', targetDir, results);
Expand Down
13 changes: 7 additions & 6 deletions src/commands/install/skill-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import chalk from 'chalk';
import path from 'path';
import fs from 'fs';
import type { FileResult, Scope } from '../../types.js';
import { ASSETS_DIR, ensureDir, getEditorConfig, getEditorDir, getFiles, getDirs } from '../../utils/symlink.js';
import { ASSETS_DIR, ensureDir, getEditorConfig, getEditorDir, getFiles, listSkillsNested } from '../../utils/symlink.js';
import { printSummary } from './print.js';
import {
type SkillEditorTarget,
Expand Down Expand Up @@ -41,9 +41,9 @@ const ensureSkillDir = (baseDir: string, name: string): string => {
const installSkillFolder = (
sourceDir: string,
targetSkillsDir: string,
target: SkillEditorTarget
target: SkillEditorTarget,
skillName: string = path.basename(sourceDir)
): FileResult => {
const skillName = path.basename(sourceDir);
const targetDir = ensureSkillDir(targetSkillsDir, skillName);

let status: FileResult['status'] = 'created';
Expand Down Expand Up @@ -111,11 +111,12 @@ const installEditorSkills = (targetDir: string, target: SkillEditorTarget): File
const targetSkillsDir = path.join(targetDir, 'skills');
ensureDir(targetSkillsDir);

// 1. Skill folders → copied verbatim (paths rewritten).
// 1. Skill folders → copied verbatim (paths rewritten). Nested groups are
// flattened to a single-level "<group>-<action>" skill folder.
const skillsDir = path.join(ASSETS_DIR, 'skills');
if (fs.existsSync(skillsDir)) {
for (const dir of getDirs(skillsDir)) {
results.push(installSkillFolder(dir, targetSkillsDir, target));
for (const skill of listSkillsNested(skillsDir)) {
results.push(installSkillFolder(skill.path, targetSkillsDir, target, skill.name));
}
}

Expand Down
11 changes: 8 additions & 3 deletions src/commands/uninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
EDITOR_CONFIGS,
removeItem,
listItems,
listSkillsNested,
getAgentsDir,
getCommandsDir,
getSkillsDir,
Expand Down Expand Up @@ -43,7 +44,9 @@ const getKitFiles = (): Set<string> => {
addFilesFromDir(developersDir);
addFilesFromDir(utilitiesDir);
addFilesFromDir(commandsDir);
addFilesFromDir(skillsDir);
addFilesFromDir(skillsDir); // group folder names, cleans up legacy nested installs
// Flattened skill names (<group>-<action>) created by the current installer.
listSkillsNested(skillsDir).forEach((s) => files.add(s.name));

return files;
};
Expand Down Expand Up @@ -101,7 +104,8 @@ const getCodexManagedNames = (): { architecture: string[]; skills: string[] } =>

const skillsDir = path.join(ASSETS_DIR, 'skills');
if (fs.existsSync(skillsDir)) {
fs.readdirSync(skillsDir).forEach((name) => skills.push(name));
fs.readdirSync(skillsDir).forEach((name) => skills.push(name)); // legacy group folders
listSkillsNested(skillsDir).forEach((s) => skills.push(s.name)); // flattened skills
}

const commandsDir = path.join(ASSETS_DIR, 'commands');
Expand Down Expand Up @@ -158,7 +162,8 @@ const getAntigravityManagedNames = (): { architecture: string[]; skills: string[

const skillsDir = path.join(ASSETS_DIR, 'skills');
if (fs.existsSync(skillsDir)) {
fs.readdirSync(skillsDir).forEach((name) => skills.push(name));
fs.readdirSync(skillsDir).forEach((name) => skills.push(name)); // legacy group folders
listSkillsNested(skillsDir).forEach((s) => skills.push(s.name)); // flattened skills
}

const commandsDir = path.join(ASSETS_DIR, 'commands');
Expand Down
Loading
Loading