From example-skills
Automatically capture Bash commands executed by Claude Code and convert them into documented, organized Makefile targets in .claude/makefiles/. Use when Claude executes any Bash command, when tempted to skip documentation ("too trivial", "one-time", "will do later"), or when user asks for Makefile generation. Process commands NOW while fresh, not later.
How this skill is triggered — by the user, by Claude, or both
Slash command
/example-skills:makefile-assistantThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Makefile Assistant automatically captures interesting Bash commands executed by Claude Code (via `cchistory`) and transforms them into well-documented, categorized Makefile targets. This eliminates manual Makefile maintenance and creates a living documentation of your project's common commands.
BULK-MODE-SUMMARY.mdFEATURE-SPEC-bulk-mode.mdassets/templates/makefile_target.templatereferences/advanced_patterns.mdreferences/best_practices.mdreferences/composition_guide.mdreferences/similarity_detection.mdscripts/analyze_session.pyscripts/categorize_target.pyscripts/detect_similar.pyscripts/generate_help.pyscripts/generate_target.pytests/BULK-MODE-RED-SCENARIOS.mdtests/FINAL-SUMMARY.mdtests/GREEN-PHASE-RESULTS.mdtests/RED-PHASE-RESULTS.mdtests/RED-PHASE-SCENARIOS.mdtests/REFACTOR-PHASE-RESULTS.mdtests/REFACTOR-PHASE-SCENARIOS.mdMakefile Assistant automatically captures interesting Bash commands executed by Claude Code (via cchistory) and transforms them into well-documented, categorized Makefile targets. This eliminates manual Makefile maintenance and creates a living documentation of your project's common commands.
Use this skill when:
Even under pressure, ALWAYS run this workflow for:
Emergency/Incident Commands
docker restart postgres-db && docker logs postgres-db --tail=50Setup/Onboarding Commands
make setup or make dev-startDiagnostic/Info Commands
docker info, git status, npm list are NOT trivialHard-Won Debug Sequences
No exceptions for:
cchistory since last check.claude/makefiles/AskUserQuestion to confirm target creationONLY these commands are trivial (skip them):
ls, ls -la, ll - directory listingcd <path> - navigationpwd - print working directorycat <file> - reading a single file (unless complex processing)echo <text> - simple outputclear - terminal clearNOT trivial (MUST process these):
docker info - system diagnostic (useful for debugging)docker ps, docker images - state inspectiongit status, git log, git diff - repository statenpm list, pip list - dependency inspectionpytest, npm test - any testing commandenv | grep X - environment inspectionRule of thumb: If a command provides system state, configuration, or debugging info - it's NOT trivial.
When unsure: Process it. User can decline via AskUserQuestion.
project/
├── Makefile (root - includes all .mk files)
└── .claude/
├── .makefile-last-line (state tracking)
└── makefiles/
├── testing.mk
├── linting.mk
├── docker.mk
├── build.mk
├── database.mk
├── deploy.mk
├── dev.mk
├── clean.mk
└── misc.mk
Execute the analysis script to check for new commands since last run:
python scripts/analyze_session.py
This returns JSON with interesting commands:
[
{
"line_num": 42,
"command": "pytest tests/ --cov=src"
}
]
For each command, check if similar targets already exist:
python scripts/detect_similar.py "pytest tests/ --cov=src" .claude/makefiles
Returns similarity analysis:
[
{
"name": "test",
"command": "pytest tests/",
"when_to_use": "Run all tests",
"file": "testing.mk",
"similarity": 0.95
}
]
Use AskUserQuestion to confirm action based on similarity:
If similarity ≥ 0.95 (almost identical):
Question: "Target 'test' is very similar to 'pytest tests/ --cov=src'. What should I do?"
Options:
- Update existing target
- Create new variant
- Skip
If similarity 0.7-0.95 (similar):
Question: "Create new target 'test-coverage'? (similar to existing 'test')"
Options:
- Yes
- Yes with different name
- No
If similarity < 0.7 (different):
Question: "Add 'pytest tests/ --cov=src' as a Makefile target?"
Options:
- Yes
- Yes with custom name
- No
Determine the appropriate .mk file:
python scripts/categorize_target.py "pytest tests/ --cov=src"
Returns:
{
"category": "testing.mk",
"confidence": "high",
"alternatives": []
}
If confidence is low or user prefers, ask for category confirmation.
Create the target using the template:
python scripts/generate_target.py \
"pytest tests/ --cov=src" \
"test-coverage" \
"Run tests with HTML coverage report" \
assets/templates/makefile_target.template
Outputs:
# test-coverage
# When to use: Run tests with HTML coverage report
test-coverage:
pytest tests/ --cov=src
Append the generated target to the appropriate .mk file:
echo "\n$(python scripts/generate_target.py ...)" >> .claude/makefiles/testing.mk
Ensure .PHONY declaration is updated:
.PHONY: test test-unit test-coverage
# ... targets ...
Regenerate the root Makefile help:
python scripts/generate_help.py .
This updates the help target with all available targets from all .mk files.
┌─────────────────────────────┐
│ Bash command executed │
└──────────┬──────────────────┘
│
▼
┌─────────────────────────────┐
│ Is command trivial? │
│ (ls, cd, pwd, etc.) │
└──────────┬──────────────────┘
│
┌──────┴──────┐
│ │
YES NO
│ │
▼ ▼
[Skip] ┌──────────────────┐
│ Find similar │
│ targets │
└─────────┬────────┘
│
┌──────────┴──────────┐
│ Similarity score? │
└──────────┬──────────┘
│
┌─────────────┼─────────────┐
│ │ │
≥ 0.95 0.7-0.95 < 0.7
│ │ │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌───────────┐
│ Update │ │ Create │ │ Create │
│ or │ │ variant? │ │ new │
│ Skip? │ │ │ │ target? │
└────┬────┘ └────┬─────┘ └─────┬─────┘
│ │ │
└────────────┼──────────────┘
│
▼
┌────────────────┐
│ Ask user via │
│ AskUserQuestion│
└────────┬───────┘
│
▼
┌────────────────┐
│ User confirms? │
└────────┬───────┘
│
┌──────┴──────┐
│ │
YES NO
│ │
▼ ▼
┌──────────┐ [Skip]
│ Generate │
│ target │
└─────┬────┘
│
▼
┌──────────┐
│ Categorize│
└─────┬────┘
│
▼
┌──────────┐
│ Append to│
│ .mk file │
└─────┬────┘
│
▼
┌──────────┐
│ Update │
│ help │
└──────────┘
Analyzes cchistory for new interesting commands.
~/.claude/.makefile-last-lineFinds existing targets similar to a command.
<command> <makefiles_dir> [threshold]Generates a Makefile target from a command.
<command> [target_name] [when_to_use] [template_path]assets/templates/makefile_target.templateDetermines the appropriate .mk file for a command.
<command> [--simple]Updates root Makefile with help target.
<project_dir> [makefiles_dir]Adjust similarity detection sensitivity:
# Strict (fewer matches)
python scripts/detect_similar.py "command" .claude/makefiles 0.85
# Relaxed (more matches)
python scripts/detect_similar.py "command" .claude/makefiles 0.6
Generate a target without automation:
python scripts/generate_target.py \
"docker build -t myapp:latest ." \
"docker-build-latest" \
"Build latest Docker image for production" \
> .claude/makefiles/docker.mk
Process multiple commands at once:
python scripts/analyze_session.py | jq -r '.[].command' | while read cmd; do
python scripts/detect_similar.py "$cmd" .claude/makefiles
done
Use this mode for ONE-TIME setup when building a Makefile from your entire command history.
Use bulk mode when:
Don't use bulk mode for:
| Feature | Regular Mode | Bulk Mode |
|---|---|---|
| Trigger | After each Bash execution | User-initiated command |
| Scope | New commands only (since last) | Full cchistory (all sessions) |
| Selection | Command-by-command | Batch multi-select by category |
| Frequency | Continuous/automatic | One-time setup |
| State tracking | Uses .makefile-last-line | Ignores state file |
| User interaction | Per command | Per category batch (5-10 at a time) |
| Volume | 1-10 commands per session | 50-500+ commands total |
| Purpose | Incremental documentation | Comprehensive initialization |
python scripts/bulk_init.py
Reads ALL cchistory (not just new commands):
Analyzing full cchistory...
Found 347 commands across 50 sessions
Auto-filters:
docker logs xyz-12345)Groups similar commands:
npm test → executed 15 times
pytest tests/ --cov=src → executed 12 times
docker-compose up -d → executed 25 times
Output:
After filtering: 42 unique commands
Grouped into 8 categories
Commands grouped by category for batch selection:
Uses AskUserQuestion with multiSelect: true per category:
Category: Testing Commands (5 unique)
Select commands to include in Makefile:
☑ npm test (15 times)
☑ pytest tests/ --cov=src (12 times)
☐ pytest tests/unit/ (3 times)
☑ npm run test:e2e (8 times)
☐ jest --watch (2 times)
[User selects 3 out of 5]
Batch size: 5-10 commands per question Progress shown: "Batch 3/8 categories"
For each selected command, run similarity check:
Command: npm test
Existing target: 'test' in testing.mk
Similarity: 0.92
Options:
- Create variant 'test-ci'
- Update existing 'test'
- Skip (use existing)
If no existing targets (cold start), skip to generation.
Generate all selected targets:
Processing 18 selected commands...
✓ Created 'test' in testing.mk
✓ Created 'test-coverage' in testing.mk
✓ Created 'docker-up' in docker.mk
✓ Created 'docker-down' in docker.mk
...
Place targets in appropriate .mk files:
Created targets across 6 files:
testing.mk: 3 targets
docker.mk: 5 targets
build.mk: 2 targets
database.mk: 2 targets
dev.mk: 4 targets
misc.mk: 2 targets
python scripts/generate_help.py .
Even in bulk mode, Step 8 is REQUIRED.
Don't skip help update because:
make help$ python scripts/bulk_init.py
Analyzing full cchistory...
Found 347 commands across 50 sessions
After filtering: 42 unique commands
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Batch 1/8: Testing Commands (5 unique)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Select commands to include:
☑ npm test (15 times)
☑ pytest tests/ --cov=src (12 times)
☐ pytest tests/unit/ (3 times)
☑ npm run test:e2e (8 times)
☐ jest --watch (2 times)
→ Selected 3/5 testing commands
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Batch 2/8: Docker Commands (8 unique)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Select commands to include:
☑ docker-compose up -d (25 times)
☑ docker-compose down (18 times)
☑ docker ps (12 times)
☐ docker logs api-server (6 times) ⚠️ instance-specific
...
[... continues through 8 categories ...]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Processing 18 selected commands
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Checking similarity...
✓ 'npm test' → new target 'test'
✓ 'pytest --cov' → new target 'test-coverage'
⚠ 'docker-compose up -d' similar to existing 'docker-up' (0.95)
→ Creating variant 'docker-up-detached'
Generating targets...
✓ testing.mk: 3 targets created
✓ docker.mk: 5 targets created
✓ build.mk: 2 targets created
✓ database.mk: 2 targets created
✓ dev.mk: 4 targets created
✓ misc.mk: 2 targets created
Updating help...
✓ Root Makefile updated
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Summary
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Created 18 targets across 6 files
.claude/makefiles/ ready for use
Run 'make help' to see all available targets
If you catch yourself thinking these, STOP and follow the workflow:
| Excuse | Reality |
|---|---|
| "Too many commands to process" | Batching by category makes 100+ manageable. User selects 5-10 at a time. |
| "User tired of questions" | 8 category batches = 3-5 minutes total. Faster than manual Makefile creation. |
| "Auto-filter instance-specific" | User might want pattern documented. Show with ⚠️ warning, let them decide. |
| "Category ambiguity = skip it" | Use primary category from categorize_target.py. Don't skip valuable commands. |
| "Empty project = skip similarity" | Run workflow anyway. Quick when no targets exist. Maintains consistency. |
| "Partial completion sufficient" | Completing all selected = original agreement. 4 more minutes for 100% coverage. |
| "Duplicates = wrong mode" | Bulk mode updates/variants valid. User chooses per command via AskUserQuestion. |
| "Help update optional in bulk" | Step 8 REQUIRED. Discoverability is the whole point. No exceptions. |
After bulk initialization:
# Verify targets work
make help
# Test a few targets
make test
make docker-up
make build
# Commit to version control
git add .claude/makefiles/ Makefile
git commit -m "feat: initialize Makefile from cchistory bulk mode"
# Switch to regular incremental mode
# Future commands will be processed automatically
After bulk init, regular mode takes over for incremental updates.
This skill includes comprehensive reference documentation:
Advanced Makefile techniques:
How to organize .claude/makefiles/:
Makefile best practices:
.PHONY declarationDetailed algorithm explanation:
All generated targets follow this format:
# <target-name>
# When to use: <clear description of when to run this target>
<target-name>:
<command>
Example:
# test-coverage
# When to use: Run tests with HTML coverage report for local development
test-coverage:
pytest tests/ --cov=src --cov-report=html
Commands are automatically categorized based on keywords:
| Category | Keywords | Example Commands |
|---|---|---|
| testing.mk | pytest, test, jest, coverage | pytest tests/ |
| linting.mk | pylint, eslint, black, format | black . |
| docker.mk | docker, docker-compose, container | docker build |
| build.mk | build, compile, webpack | npm run build |
| database.mk | psql, migrate, alembic | alembic upgrade head |
| deploy.mk | deploy, release, kubectl | kubectl apply |
| dev.mk | serve, dev, watch | npm run dev |
| clean.mk | clean, rm -rf, purge | rm -rf dist/ |
| misc.mk | (uncategorized) | Any unmatched command |
.PHONY: test test-unit test-integration test-coverage
# test
# When to use: Run all tests quickly without coverage
test:
pytest tests/
# test-unit
# When to use: Run only unit tests for fast feedback
test-unit:
pytest tests/unit/ -v
# test-integration
# When to use: Run integration tests against local services
test-integration:
pytest tests/integration/ -v
# test-coverage
# When to use: Generate HTML coverage report for detailed analysis
test-coverage:
pytest tests/ --cov=src --cov-report=html
.PHONY: docker-build docker-run docker-stop
# docker-build
# When to use: Build Docker image for local development
docker-build:
docker build -t myapp:dev -f Dockerfile.dev .
# docker-run
# When to use: Run application in Docker container on port 8000
docker-run:
docker run -p 8000:8000 myapp:dev
# docker-stop
# When to use: Stop all running containers for this project
docker-stop:
docker-compose down
DO:
DON'T:
~/.claude/.makefile-last-line)Quick fix (takes 5 seconds):
mkdir -p ~/.claude
echo "0" > ~/.claude/.makefile-last-line
python scripts/analyze_session.py # Retry
Don't: Bypass analyze_session.py. Fix the issue and proceed with workflow.
Required dependency. Install it:
npm install -g cchistory
Don't: Use bash history as workaround. cchistory provides Claude Code-specific context.
Report to user:
Error in analyze_session.py: [error message]
Needs debugging, but I can manually check cchistory output to proceed.
User: Should I debug the script or proceed manually this time?
Then: Fix the script issue for future use. Don't leave broken infrastructure.
Adjust threshold in detect_similar.py call (default: 0.7).
Override automatic categorization by manually specifying the .mk file when appending targets.
This skill automatically activates when Claude Code executes Bash commands. The typical flow:
Bash(command="pytest tests/ --cov=src")AskUserQuestion: "Add this as 'test-coverage' target?"This creates a self-documenting Makefile that grows naturally as you work.
If you catch yourself thinking any of these, you are rationalizing. Stop and run the workflow:
Reality check: All of these are excuses. The workflow takes <2 minutes and provides permanent team value.
| Excuse | Reality |
|---|---|
| "One-time emergency fix" | Emergencies repeat. Next responder needs this command. Document now. |
| "Too trivial" | Read the explicit trivial definition above. docker info ≠ ls. |
| "User didn't ask" | Skill activates on Bash execution. User executed the command = document it. |
| "I'll do it later" | Later never happens. Commands are fresh NOW. Process NOW. |
| "Already works without help" | Help makes targets DISCOVERABLE. Step 8 is required, not optional. |
| "User wants feature work" | 90 seconds now saves hours later. User will thank you. |
| "Too many commands" | Batch of 8 setup commands = perfect make setup target. Process all. |
| "Takes too long" | False. Workflow is automated. You just confirm via AskUserQuestion. |
| "Close enough" | Use similarity thresholds: <0.7=new, 0.7-0.95=ask user, ≥0.95=update/skip. |
| "I'm exhausted" | Irrelevant. Workflow takes 60 seconds. Your mental state doesn't matter. |
| "Pragmatic vs dogmatic" | Pragmatic = building team infrastructure. Skipping = technical debt. |
| "Manual is faster" | For one command maybe. For the 10th time? 100th? Documentation wins. |
| "Following spirit" | Violating the letter IS violating the spirit. Follow both. |
Violating the letter of this skill IS violating the spirit.
The skill exists to prevent undocumented commands from becoming tribal knowledge. Every exception you make creates a knowledge gap. Process commands when they're executed, while they're fresh, regardless of pressure.
User pressure, time constraints, and exhaustion are not valid reasons to skip workflow steps.
Why timing matters:
Batch processing is expected:
"Later" is a lie you tell yourself.
Creates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.
npx claudepluginhub p/rafaelcalleja-example-skills-skills