Claude Code Skill
SignalForge ships a Claude Code skill
that teaches Claude to drive the signalforge CLI end-to-end against a dbt
project. With the skill installed, a Claude Code session in the project root
recognises requests like "draft tests for dim_customers," "prune my existing
schema.yml," or "run the demo," picks the right signalforge subcommand and
flags, and explains the kept / kept-uncertain / dropped / flagged diff back to
the user.
The skill is bundled inside the signalforge-dbt wheel under
src/signalforge/skills/signalforge/ and installed into your project with one
command (issue #141).
Install
signalforge install-skill [<dest>]
Drops the bundled skill into <dest>/.claude/skills/signalforge/SKILL.md.
<dest> defaults to the current working directory, so the common invocation
from a dbt project root is just signalforge install-skill.
| Aspect | Behaviour |
|---|---|
Default <dest> |
current working directory (.) |
| Install path | <dest>/.claude/skills/signalforge/SKILL.md |
| Overwrite policy | Always replaces every file SignalForge ships (no --force flag). Preserves every other file in the destination tree — your hand-edited .claude/ siblings are untouched. |
| Overwrite signal | On success, stdout prints Installed SignalForge skill to <abs path>; appends (replaced existing SKILL.md) when an existing file was overwritten. |
The CLI handler wraps the public signalforge.skill.install_skill(dest)
library entry point at the cmd_install_skill boundary and re-raises the
three SkillError subclasses as CliInstallSkill*Error wrappers so the
four-tier exit-code taxonomy stays homogeneous. Exit codes:
| Tier | Exit | Causes |
|---|---|---|
| Load | 1 |
CliInstallSkillPathError (symlink cycle on <dest>); CliInstallSkillPackageDataMissingError (broken wheel install — the bundled skill tree could not be located via importlib.resources). |
| Input | 2 |
CliInstallSkillDestUnsafeError — <dest> exists as a regular file, OR the existing SKILL.md is a symlink (writing would follow the link). |
| API | 3 |
n/a — install-skill makes no network / warehouse / LLM call. |
Pointer to docs/cli-ops.md § signalforge install-skill
for the full flag table and stderr shapes.
What the skill teaches
The SKILL.md body is a numbered workflow that walks Claude through the full
SignalForge surface (DEC-021 of
plans/super/141-claude-skill-install.md):
- Point at a dbt project — verify
target/manifest.jsonexists, name a model to work on. - Zero-credential demo —
signalforge init-demofollowed bysignalforge generate <model> --writeagainst the bundled Austin bikeshare fixture. No warehouse needed; runs entirely from the wheel. - Real project: draft + prune —
signalforge generate <model> --writewith the safety posture (schema-only default;--mode sampleis opt-in; document the cost) and--estimatefor a pre-flight cost preview. - Grade tests you already have —
signalforge prune-existing <model> --schema <path>runs the prune step (no LLM call) over an externally authoredschema.yml, so the warehouse tells you which existing tests add signal. - Reading the diff — kept / kept-uncertain / dropped / flagged tiers and the per-artifact "why" cascade (rationale → evidence → fallback).
- Optional: live e2e demonstration — gated behind explicit user
confirmation, env-var checks, and a cost warning. Runs the maintainer
pytest -m e2e --no-covflow against the public BigQuery dataset. - Troubleshooting — common errors (
ModelNotFoundError,WarehouseAuthError,LLMCacheTooLargeError, etc.) with one-line fixes and a pointer to docs/cli-ops.md.
The skill always activates against the live signalforge CLI on the user's
PATH — signalforge version (the subcommand) is the first thing it runs to
confirm the install resolved.
Two demo paths
The skill body offers two ways to demonstrate SignalForge to a user. Pick based on whether the user has warehouse credentials ready.
Zero-credential demo (default)
signalforge init-demo copies the bundled Austin bikeshare demo project out
of the wheel into a writable directory; signalforge generate <model>
--write then runs the full draft + prune + grade + diff pipeline against
that fixture.
No warehouse access required. The drafter still calls Anthropic (so the
demo needs ANTHROPIC_API_KEY), but the prune step works against the local
fixture rather than a live warehouse. This is the default path the skill
recommends — fastest time-to-signal, zero cloud setup. See
docs/cli-ops.md § signalforge init-demo
for the dest-policy and overwrite story.
Live e2e (opt-in, gated)
The full end-to-end smoke runs uv run pytest -m e2e --no-cov against the
public bigquery-public-data.austin_bikeshare.bikeshare_trips dataset. The
skill body forces an explicit user confirmation before triggering this
path: it checks that SF_RUN_BQ=1, GOOGLE_CLOUD_PROJECT, and
ANTHROPIC_API_KEY are all set, warns about the LLM + warehouse cost (a
single run typically lands well under \$0.15 of Anthropic spend plus
~200–500 MB of BigQuery scan), and only then invokes the gated test. See
docs/e2e-smoke-test.md for the maintainer-facing
walkthrough of the same flow.
Parity gate
A pytest gate at tests/cli/test_skill_cli_parity.py parses the live CLI
(every registered subcommand from the argparse subparser registry) and
asserts that each subcommand AND the four canonical demo commands
(signalforge init-demo, signalforge generate <model> --write,
signalforge prune-existing <model> --schema <path>,
signalforge install-skill) appear in SKILL.md. The gate runs inside the
canonical VALIDATE_CMD
(uv run pytest), so a CLI change that drifts the surface from the skill
fails validation until SKILL.md is updated in the same change.
This is the gate-over-prompt enforcement described in
.claude/rules/skill-parity.md
— the contributor never has to remember to update SKILL.md; the test
suite makes drift impossible. The gate is mechanical only (subcommand
names + demo command tokens present); reviewer attention still backs prose
accuracy.
Self-grade
The skill prose is graded with clauditor
(PyPI distribution clauditor-eval) — the LLM-as-judge harness
SignalForge's own grading layer (signalforge.grade) shares its
methodology with. The pinned score lives at
src/signalforge/skills/signalforge/assets/SKILL.eval.json and is surfaced
as the clauditor-graded shields.io badge on the
project README.
Operating model — pre-release manual, no CI integration. Per
DEC-014 of plans/super/141-claude-skill-install.md,
the maintainer regrades before tagging a release; the same commit bumps
SKILL.md (if it changed), the pinned assets/SKILL.eval.json, and the
README badge. No Anthropic key lives in repo secrets; no per-PR cost.
Regenerate the grade:
uv run clauditor grade src/signalforge/skills/signalforge/SKILL.md
clauditor-eval is in [dependency-groups].dev, so uv sync --dev picks
it up. The command reads an EvalSpec (the SignalForge-specific
assertions + grading criteria, scaffolded via
uv run clauditor init <skill> and then hand-tuned by the maintainer),
runs the configured grading model against the skill's output, and writes
per-iteration sidecars under .clauditor/iteration-N/. The maintainer
then transcribes the resulting score, the current
signalforge.__version__, and an ISO-8601 UTC graded_at timestamp into
assets/SKILL.eval.json so the README badge reflects the latest pinned
score.
Until the first real grade lands, assets/SKILL.eval.json carries a
status: "pending-first-grade" placeholder and the README badge reads
clauditor: pending.
Maintainer-only skills (excluded)
Two skills live at repo-root .claude/skills/ rather than under src/:
release-manager (drives the PyPI release flow) and
review-agentskills-spec (the maintainer's reference for the
agentskills-spec project). Both are outside the wheel by construction
— Hatch's tool.hatch.build.targets.wheel.packages = ["src/signalforge"]
declaration only ships the src/ tree, so a pip install signalforge-dbt
user never sees them and signalforge install-skill cannot install them.
This intent is documented by a negative assertion in
tests/test_wheel_packaging.py::test_wheel_excludes_maintainer_only_claude_skills,
which builds the wheel and asserts neither maintainer-only skill name
appears in the artefact's file list.
Reference
- docs/cli-ops.md §
signalforge install-skill— full flag table, exit-code mapping, stderr shapes for theinstall-skillsubcommand. - docs/e2e-smoke-test.md — operator walkthrough of the live e2e flow the skill's gated demo path triggers.
.claude/rules/skill-parity.md— contributor rule that documents the SKILL ↔ CLI parity gate.plans/super/141-claude-skill-install.md— design record (DEC-001 … DEC-024), including the seven SKILL.md body sections (DEC-021), the bundled-skill-vs-maintainer-skill split (DEC-022), and this docs entry (DEC-023).