-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Overview
Add skills support to ballast alongside the existing rules system. Skills are invocable behaviors (triggered on demand) rather than always-on context rules. This issue tracks the full implementation across all supported AI agents (Cursor, Claude Code, OpenCode, Codex) and all supported languages (TypeScript, Python, Go).
The first skill to ship is owasp-security-scan — a cross-language OWASP Top 10 security audit that covers Go, TypeScript, and Python, making it a perfect fit for ballast's own monorepo users.
Background: Rules vs Skills
| Rules | Skills | |
|---|---|---|
| Behavior | Always-on context guidance | Invoked on demand (e.g. /owasp-security-scan) |
| Install path (Claude) | .claude/rules/*.md |
.claude/skills/*.skill |
| Install path (Cursor) | .cursor/rules/*.mdc |
.cursor/rules/*.mdc with alwaysApply: false |
| Triggered by | Every conversation | Explicit user invocation |
Target Formats Per Agent
| Agent | Install path | Format |
|---|---|---|
| Claude Code | .claude/skills/<name>.skill |
Zip archive (SKILL.md + references/) |
| Cursor | .cursor/rules/<name>.mdc |
.mdc with alwaysApply: false frontmatter |
| OpenCode | .opencode/skills/<name>.md |
Flat markdown (body only) |
| Codex | .codex/rules/<name>.md |
Flat markdown rule file |
Implementation Phases
Phase 1 — Repository Structure
- Extract
owasp-security-scan.skillzip intoskills/common/owasp-security-scan/ - Establish
skills/directory layout mirroringagents/:skills/ └── common/ └── owasp-security-scan/ ├── SKILL.md └── references/ ├── owasp-mapping.md ├── remediation-guide.md ├── ci-workflow.md └── tool-config.md - Delete the top-level
owasp-security-scan.skillzip artifact
No per-target template files are needed — Cursor frontmatter is generated programmatically from the description field in SKILL.md.
Phase 2 — Config File Extension
Extend .rulesrc.json with an optional skills array (fully backward-compatible):
{
"target": "claude",
"agents": ["linting", "cicd"],
"skills": ["owasp-security-scan"]
}- TypeScript: add
skills?: string[]toRulesConfiginconfig.ts - Python: update
load_config/save_configto read/writeskills - Go: add
Skills []string \json:"skills,omitempty"`torulesConfig` struct
Phase 3 — Skill Discovery (all 3 CLIs)
Add parallel skill discovery alongside existing agent discovery:
-
COMMON_SKILL_IDS,listSkills(),isValidSkill(),getSkillDir()in TypeScript (agents.ts) - Same in Python (
cli.py) - Same in Go (
main.go)
Language-specific skills (skills/typescript/, skills/python/, skills/go/) are scaffolded but empty for now.
Phase 4 — Skill Build Functions (all 3 CLIs)
Each CLI needs 4 functions:
| Function | Output |
|---|---|
buildClaudeSkill(id) |
In-memory zip (SKILL.md + references/) |
buildCursorSkillFormat(id) |
alwaysApply: false frontmatter + SKILL.md body |
buildSkillMarkdown(id) |
SKILL.md body only (no frontmatter) |
getSkillDestination(id, target) |
Correct install path per target |
Zip implementation: Python and Go use stdlib (zipfile, archive/zip) — no new deps. TypeScript needs jszip (or similar) added as a prod dependency.
- TypeScript: implement in
build.ts, addjszipdep - Python: implement in
cli.pyusingzipfilestdlib - Go: implement in
main.gousingarchive/zipstdlib
Phase 5 — Install Logic & CLI Flags
Add --skill <id> and --all-skills flags to the existing install subcommand (consistent with --agent/--all):
ballast-typescript install --target claude --skill owasp-security-scan
ballast-python install --target cursor --all-skills
ballast-go install --target claude --skill owasp-security-scan --agent lintingInstall flow per skill:
- Validate skill ID
- Compute destination path
- Skip if exists and
--forcenot set - Build target-specific output
- Write file (create parent dirs)
- Persist skill IDs to
.rulesrc.json - Append
## Installed skillssection toCLAUDE.md/AGENTS.mdindex files
- TypeScript:
installSkills()ininstall.ts, wire flags incli.ts - Python:
install_skills()incli.py, wire--skill/--all-skillsargs - Go:
installSkills()inmain.go, wire flags - CLI wrapper (
cli/ballast): forward--skillto backend CLIs
Phase 6 — Sync & Embed Updates
| CLI | Required change |
|---|---|
| TypeScript | New sync:skills script; add "skills" to package.json files |
| Python | Add skills/**/* to pyproject.toml package-data |
| Go | Add //go:embed skills/** + var embeddedSkillsFS embed.FS; sync skills/ into Go package dir |
- TypeScript sync script
- Python package-data update
- Go embed + sync
Phase 7 — Tests
Each CLI gets skill-specific tests covering:
-
buildClaudeSkill→ valid zip with correct internal paths (<id>/SKILL.md,<id>/references/*.md) -
buildCursorSkillFormat→alwaysApply: falsein frontmatter, description from SKILL.md -
getSkillDestination→ correct path for all 4 targets -
Install integration: install to tmpdir, assert file at expected path
-
Skip/force behavior
-
Config persistence (
.rulesrc.jsonupdated withskillsarray) -
TypeScript tests (
build.test.ts,install.test.ts) -
Python tests (
test_cli.py) -
Go tests (
main_test.go)
Phase 8 — Index File Updates
Update CLAUDE.md and AGENTS.md generation to include a separate ## Installed skills section when skills are installed (distinct from ## Installed agent rules).
- TypeScript index builder
- Python index builder
- Go index builder
Key Design Decisions
- Zip at install time (not pre-built): keeps source as plain markdown, easy to audit, no stale binary artifacts in the repo
- No template files for skills: Cursor frontmatter is generated from SKILL.md
descriptionfield programmatically — notemplates/cursor-frontmatter.yamlneeded --skillflag, not a new subcommand: consistent with--agent, minimal CLI surface change- No language prefix in skill filenames:
owasp-security-scan.skillregardless of language — skill names must be stable for invocation - Common skills only initially:
skills/typescript/,skills/python/,skills/go/directories scaffolded but empty until language-specific skills are identified
Files Changed (expected)
skills/common/owasp-security-scan/SKILL.md(new)skills/common/owasp-security-scan/references/*.md(new)packages/ballast-typescript/src/agents.ts— skill discoverypackages/ballast-typescript/src/build.ts— skill build functionspackages/ballast-typescript/src/install.ts—installSkills()packages/ballast-typescript/src/config.ts—skills?fieldpackages/ballast-typescript/src/cli.ts—--skill/--all-skillsflagspackages/ballast-python/ballast/cli.py— all Python skill logicpackages/ballast-go/cmd/ballast-go/main.go— all Go skill logic + embedcli/ballast/main.go— forward--skillto backends- Test files for all three CLIs