Free SKILL.md scraped from GitHub. Clone the repo or copy the file directly into your Claude Code skills directory.
npx versuz@latest install kevinzai-commander-skills-cowork-plugin-buildergit clone https://github.com/KevinZai/commander.gitcp commander/SKILL.MD ~/.claude/skills/kevinzai-commander-skills-cowork-plugin-builder/SKILL.md---
name: cowork-plugin-builder
description: |
Guide for building custom Cowork plugins that leverage CC Commander skills. Covers plugin
anatomy (manifest, handler, permissions), 5 example plugins, packaging CC Commander skills
as plugins, local testing, and publishing to the plugin directory.
triggers:
- /cowork-plugins
- /plugin-builder
- /cowork-plugin
- build cowork plugin
- create cowork plugin
- cowork plugin builder
- package skill as plugin
disable-model-invocation: true
---
# Cowork Plugin Builder
## Overview
Cowork plugins extend Claude Desktop's autonomous execution with custom capabilities. This skill teaches you how to package CC Commander skills, hooks, and workflows as installable Cowork plugins.
## Plugin Anatomy
Every Cowork plugin consists of three files:
```
my-plugin/
manifest.json # Plugin metadata, permissions, configuration
handler.js # Entry point -- receives events, returns results
README.md # Usage docs (optional but recommended)
```
### manifest.json
```json
{
"name": "bible-daily-standup",
"version": "1.0.0",
"description": "Automated daily standup using CC Commander task-commander patterns",
"author": "Kevin Z",
"license": "MIT",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["tasks/**", "output/**", ".claude/**"],
"write": ["output/standups/**", "tasks/todo.md"]
},
"terminal": {
"commands": ["git log *", "git status", "git diff --stat *"]
}
},
"config": {
"outputDir": {
"type": "string",
"default": "output/standups",
"description": "Directory for standup reports"
},
"includeGitLog": {
"type": "boolean",
"default": true,
"description": "Include git activity in standup"
},
"lookbackHours": {
"type": "number",
"default": 24,
"description": "Hours of activity to include"
}
},
"triggers": {
"schedule": "0 9 * * 1-5",
"manual": true
},
"bible": {
"skills": ["session-startup", "task-commander"],
"mode": "normal"
}
}
```
### handler.js
```javascript
#!/usr/bin/env node
'use strict';
/**
* Plugin handler receives a context object on stdin and writes
* results to stdout. The context includes:
* - project: absolute path to project directory
* - config: merged plugin config (defaults + user overrides)
* - trigger: what triggered this run (schedule, manual, webhook)
* - previousRun: summary of last execution (if any)
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
let data = '';
process.stdin.on('data', chunk => data += chunk);
process.stdin.on('end', () => {
try {
const ctx = JSON.parse(data);
const result = run(ctx);
console.log(JSON.stringify(result));
} catch (e) {
console.log(JSON.stringify({
status: 'error',
error: e.message
}));
process.exit(1);
}
});
function run(ctx) {
const { project, config } = ctx;
// Read task state
const todoPath = path.join(project, 'tasks', 'todo.md');
const tasks = fs.existsSync(todoPath)
? fs.readFileSync(todoPath, 'utf8')
: 'No tasks/todo.md found.';
// Git activity
let gitLog = 'Git log disabled.';
if (config.includeGitLog) {
try {
gitLog = execSync(
`git log --since="${config.lookbackHours} hours ago" --oneline`,
{ cwd: project, encoding: 'utf8', timeout: 10000 }
).trim() || 'No commits in the lookback window.';
} catch {
gitLog = 'Not a git repository or git unavailable.';
}
}
// Build standup report
const date = new Date().toISOString().split('T')[0];
const report = [
`# Daily Standup -- ${date}`,
'',
'## Task Status',
tasks,
'',
'## Recent Git Activity',
'```',
gitLog,
'```',
'',
`Generated by bible-daily-standup plugin at ${new Date().toISOString()}`
].join('\n');
// Write output
const outDir = path.join(project, config.outputDir);
fs.mkdirSync(outDir, { recursive: true });
const outPath = path.join(outDir, `${date}.md`);
fs.writeFileSync(outPath, report);
return {
status: 'success',
artifact: outPath,
summary: `Standup written to ${outPath}`
};
}
```
### Permission Model
Plugins declare permissions in `manifest.json`. Cowork enforces them at runtime:
| Permission | Scope | Example |
|---|---|---|
| `filesystem.read` | Glob patterns for read access | `["src/**", "*.md"]` |
| `filesystem.write` | Glob patterns for write access | `["output/**"]` |
| `terminal.commands` | Allowed shell command patterns | `["git *", "npm test"]` |
| `browser.urls` | Allowed URL patterns | `["https://api.github.com/*"]` |
| `network.hosts` | Allowed outbound hosts | `["localhost:3110"]` |
Users approve permissions on first install. Changes require re-approval.
## Example Plugins
### 1. Daily Standup Plugin
Generates a standup report from task state and git history.
```json
{
"name": "bible-daily-standup",
"version": "1.0.0",
"description": "Morning standup from tasks/todo.md + git log",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["tasks/**", "output/**"],
"write": ["output/standups/**"]
},
"terminal": { "commands": ["git log *", "git status"] }
},
"triggers": { "schedule": "0 9 * * 1-5" },
"bible": { "skills": ["session-startup", "task-commander"] }
}
```
**Handler logic:**
1. Read `tasks/todo.md` for current task state
2. Run `git log --since="24 hours ago"` for recent activity
3. Identify blockers (items marked `[blocked]`)
4. Generate markdown standup report
5. Write to `output/standups/{date}.md`
### 2. Code Review Bot Plugin
Automatically reviews new PRs and posts feedback.
```json
{
"name": "bible-code-review-bot",
"version": "1.0.0",
"description": "Auto-review PRs using CC Commander coding-standards skill",
"entry": "handler.js",
"permissions": {
"filesystem": { "read": ["**"] },
"terminal": { "commands": ["git *", "gh pr *", "npx tsc --noEmit"] },
"network": { "hosts": ["api.github.com"] }
},
"config": {
"severity": {
"type": "string",
"default": "medium",
"description": "Minimum severity to report (low, medium, high, critical)"
},
"autoApprove": {
"type": "boolean",
"default": false,
"description": "Auto-approve PRs with no issues found"
}
},
"triggers": {
"webhook": "github.pull_request.opened",
"manual": true
},
"bible": { "skills": ["coding-standards", "review", "security-reviewer"] }
}
```
**Handler logic:**
1. Receive PR event (number, branch, author)
2. Checkout PR branch locally
3. Run typecheck (`npx tsc --noEmit`)
4. Analyze diff against coding-standards skill rules
5. Check for security issues per pentest-checklist skill
6. Write review to `output/reviews/pr-{number}.md`
7. Post review comment via `gh pr review`
### 3. Dependency Updater Plugin
Checks and updates dependencies with safety checks.
```json
{
"name": "bible-dependency-updater",
"version": "1.0.0",
"description": "Safe dependency updates with test verification",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["package*.json", "pnpm-lock.yaml", "src/**", "tests/**"],
"write": ["package*.json", "pnpm-lock.yaml", "output/deps/**"]
},
"terminal": {
"commands": [
"npm outdated *", "npm audit *", "npm update *",
"pnpm outdated *", "pnpm update *",
"npx tsc --noEmit", "npm test", "pnpm test",
"git *"
]
}
},
"config": {
"updateType": {
"type": "string",
"default": "minor",
"description": "Max update level: patch, minor, major"
},
"createPR": {
"type": "boolean",
"default": true,
"description": "Create PR for updates"
}
},
"triggers": { "schedule": "0 6 * * 1" },
"bible": { "skills": ["verification-loop"] }
}
```
**Handler logic:**
1. Run `npm outdated` / `pnpm outdated` to list available updates
2. Filter by update type (patch/minor/major)
3. For each update: install, typecheck, run tests
4. If tests pass: keep update. If tests fail: revert and log.
5. Create branch `deps/update-{date}` with passing updates
6. Write report to `output/deps/{date}.md`
7. Optionally create PR via `gh pr create`
### 4. Test Runner Plugin
Runs test suite and generates coverage report.
```json
{
"name": "bible-test-runner",
"version": "1.0.0",
"description": "Scheduled test runner with coverage tracking",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["src/**", "tests/**", "vitest.config.*", "package.json"],
"write": ["output/tests/**", "coverage/**"]
},
"terminal": {
"commands": ["npm test *", "pnpm test *", "npx vitest *", "npx jest *"]
}
},
"config": {
"coverageThreshold": {
"type": "number",
"default": 80,
"description": "Minimum coverage percentage"
},
"failOnDecrease": {
"type": "boolean",
"default": true,
"description": "Fail if coverage decreased since last run"
}
},
"triggers": {
"schedule": "0 */6 * * *",
"manual": true
},
"bible": { "skills": ["tdd-workflow", "verification-loop"] }
}
```
**Handler logic:**
1. Run test suite with coverage enabled
2. Parse coverage report (JSON format)
3. Compare against previous run (stored in `output/tests/coverage-history.json`)
4. Flag coverage decreases if `failOnDecrease` is true
5. Write report to `output/tests/{date}.md`
6. Update coverage history
### 5. Report Generator Plugin
Batch-generates reports from templates and data sources.
```json
{
"name": "bible-report-generator",
"version": "1.0.0",
"description": "Generate reports from templates using CC Commander patterns",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["templates/**", "data/**", "output/**"],
"write": ["output/reports/**"]
},
"terminal": {
"commands": ["git log *", "wc *"]
}
},
"config": {
"templateDir": {
"type": "string",
"default": "templates/reports",
"description": "Directory containing report templates"
},
"dataDir": {
"type": "string",
"default": "data",
"description": "Directory containing data sources"
}
},
"triggers": {
"schedule": "0 17 * * 5",
"manual": true
},
"bible": { "skills": ["business-analytics"] }
}
```
**Handler logic:**
1. Scan template directory for `.md` templates
2. For each template: load data sources referenced in frontmatter
3. Fill template variables from data
4. Generate formatted report
5. Write to `output/reports/{template-name}-{date}.md`
## Packaging CC Commander Skills as Plugins
### Step-by-Step
1. **Identify the skill** -- pick a SKILL.md from `~/.claude/skills/`
2. **Extract the logic** -- determine what tools/commands the skill uses
3. **Create manifest** -- declare permissions matching the skill's requirements
4. **Write handler** -- implement the skill's workflow in JavaScript
5. **Test locally** -- verify with `cowork test` command
6. **Package** -- zip the plugin directory
### Skill-to-Plugin Mapping
```
SKILL.md section -> manifest.json field
---
name -> name (prefix with "bible-")
description -> description
triggers -> triggers
allowed-tools -> permissions (map tool names to plugin permissions)
```
### Converting a Skill
Example: converting `overnight-runner` skill to a plugin.
**Original skill uses:**
- Bash (terminal commands)
- Read/Write (filesystem access)
- Checkpoint files
**Plugin manifest:**
```json
{
"name": "bible-overnight-runner",
"version": "1.0.0",
"entry": "handler.js",
"permissions": {
"filesystem": {
"read": ["tasks/**", "output/**", "CLAUDE.md"],
"write": ["tasks/checkpoint.json", "output/**", "logs/**"]
},
"terminal": {
"commands": [
"git *", "npm *", "pnpm *", "npx *",
"node *", "terminal-notifier *"
]
}
},
"config": {
"maxRetries": { "type": "number", "default": 5 },
"retryDelaySeconds": { "type": "number", "default": 1800 },
"notifyOnComplete": { "type": "boolean", "default": true }
},
"triggers": {
"schedule": "0 1 * * *",
"manual": true
}
}
```
**Handler wraps the retry/checkpoint pattern:**
```javascript
function run(ctx) {
const checkpointPath = path.join(ctx.project, 'tasks', 'checkpoint.json');
let checkpoint = { status: 'not-started', completedItems: 0 };
try {
checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
} catch {
// Fresh start
}
if (checkpoint.status === 'complete') {
return { status: 'success', summary: 'Already complete.' };
}
// Execute batch with checkpoint updates
// (handler delegates to Claude for actual processing)
return {
status: 'delegated',
task: `Resume from checkpoint: ${JSON.stringify(checkpoint)}`,
skills: ['overnight-runner'],
maxTurns: 100
};
}
```
## Testing Plugins Locally
### Manual Test
```bash
# Create test input
echo '{"project":"/path/to/project","config":{"outputDir":"output/test"},"trigger":"manual"}' | node handler.js
```
### Cowork Test Command
```bash
# Validate manifest
cowork plugin validate ./my-plugin/
# Dry run (no side effects)
cowork plugin test ./my-plugin/ --dry-run
# Full test run
cowork plugin test ./my-plugin/ --project /path/to/test-project
```
### Test Checklist
- [ ] Handler reads stdin JSON without error
- [ ] Handler writes valid JSON to stdout
- [ ] All file paths stay within declared permissions
- [ ] Terminal commands match declared patterns
- [ ] Config defaults produce valid behavior
- [ ] Error cases return `{ "status": "error", "error": "message" }`
- [ ] No hardcoded paths (use `ctx.project` as base)
- [ ] No secrets in manifest or handler
## Publishing to Plugin Directory
### Package Structure
```bash
# Create distributable
cd my-plugin/
zip -r bible-my-plugin-1.0.0.zip manifest.json handler.js README.md
```
### Plugin Directory Submission
1. **Test thoroughly** -- local testing must pass all checklist items
2. **Version correctly** -- follow semver (major.minor.patch)
3. **Write README** -- include usage examples and configuration reference
4. **Submit** -- push to plugin registry or share as a zip
### Versioning
- **Patch** (1.0.1) -- bug fixes, no config changes
- **Minor** (1.1.0) -- new features, backward-compatible config
- **Major** (2.0.0) -- breaking config changes, new permissions
## Best Practices
1. **Minimal permissions** -- request only what the plugin needs
2. **Fail gracefully** -- always return valid JSON, even on error
3. **Idempotent** -- running twice should not corrupt state
4. **Checkpoint state** -- write progress to disk for crash recovery
5. **No secrets in code** -- use environment variables or vault references
6. **Test with real projects** -- synthetic tests miss permission edge cases
7. **Document config** -- every config field needs a description
8. **Respect cost limits** -- if delegating to Claude, set maxTurns
9. **Prefix with "cc-"** -- clear naming convention for CC Commander-derived plugins
10. **Include skill references** -- the `bible.skills` field in manifest helps users understand provenance