From chameleon
Use when the user explicitly invokes /chameleon-auto-idiom to auto-derive high-quality team idioms from repo evidence, or accepts the offer after /chameleon-init or /chameleon-refresh when idioms.md has no active idioms
How this skill is triggered — by the user, by Claude, or both
Slash command
/chameleon:chameleon-auto-idiomThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Derive **legit, high-value team idioms** from repo evidence and append them to
Derive legit, high-value team idioms from repo evidence and append them to
.chameleon/idioms.md via the structured teach path. The whole point of this
skill is the complement: it only proposes guidance that chameleon does NOT
already capture — not in conventions.json, not in principles.md, not in
rules.json, not already taught in idioms.md. Everything it produces is
deduplicated twice: once by you against the coverage map, once deterministically
by check_idiom_candidates.
status="active" only appends.
If a candidate contradicts an existing idiom, do not write it — surface the
conflict and ASK the user whether the old idiom should be deprecated. Only
an explicit "yes, deprecate it" authorizes a deprecation. Note the
mechanics so you don't destroy guidance: calling
teach_profile_structured(slug=<existing active slug>, status="deprecated")
does NOT just flip a status flag — it OVERWRITES that idiom's body with
whatever rationale/example/counterexample you pass. To deprecate without
losing the original guidance, re-pass the original body (read it from
idioms.md first) plus a deprecation note. Never edit idioms.md directly.novel from
check_idiom_candidates AND (b) approved by the user. Skipped candidates
are reported, never silently written./chameleon-auto-idiom./chameleon-init or /chameleon-refresh makes
when the profile has zero active idioms.idioms.md without dictating each idiom..chameleon/profile.json in the repo — run /chameleon-init first./chameleon-teach
(faster, no mining).teach_competing_import via /chameleon-teach (it drives the lint engine,
not just prose)..chameleon/profile.json exists in the
repo root. If missing, suggest /chameleon-init and stop.chameleon-mcp::get_idiom_coverage(repo=<abs-repo-path>). From data:
existing_idioms.active — slugs + summaries already taught. Do not
re-derive these.covered.principles — auto-derived principles. Do not restate them.covered.competing_imports, covered.import_preferences — wrapper and
import preferences already enforced.covered.naming, covered.inheritance, covered.error_handling,
covered.convention_kinds — structured conventions already injected at
edit time.covered.class_contract — per-archetype DSL macros, class decorators, and
required methods already derived. A bare restatement is covered; an idiom
that EXPLAINS the full contract a base/decorator implies (which macros are
mandatory, which method every subclass defines, and why) can still be novel
— see step 3.covered.lint_sources — formatting/lint topics already in rules.json.
Formatting is NEVER idiom-worthy.
If status is untrusted, stop and tell the user to run /chameleon-trust
(an untrusted profile withholds all content; active_count: 0 there does
NOT mean the profile has no idioms).
checks_skipped is a hard gate, not a footnote, scoped per dimension:idioms.md listed → the duplicate check itself ran blind; trust NO
novel verdict until it is repaired (/chameleon-refresh).conventions.json listed → the naming / inheritance / competing-import
dedup ran blind; a novel verdict on a candidate touching those
dimensions is UNVERIFIED — do not write it until repaired.principles.md listed → the covered-by-principle check ran blind; treat a
novel verdict on a candidate that restates a general principle as
unverified.rules.json listed → the covered-by-lint check ran blind.archetypes.json listed → the archetype LIST you mine from is
incomplete, but the naming/inheritance/competing dedup is unaffected (it
reads conventions.json). Mine cautiously; dedup still holds.
Report every skipped artifact..chameleon/profile.summary.md, the canonical witness file of each major
archetype, 3-5 additional representative files per major archetype, and
the repo's own docs (README, CONTRIBUTING, docs/, code comments near the
patterns). Hunt the dimensions AST analysis fundamentally cannot infer —
see the candidate sources table below. Verify the occurrence count with
a repo-wide grep before drafting — counting from the witness + summary
alone undercounts and risks promoting a one-off to an idiom. Cite the
grep numbers as evidence (e.g. "169 wrapper imports vs 4 raw").
When covered.class_contract[<arch>] or
covered.inheritance[<arch>].dominant_base shows a framework/gem base or
decorator, read 3-5 of that archetype's members and capture the FULL contract
it implies: which DSL macros are mandatory, which method(s) every subclass
defines, and the order. The base/decorator alone is covered; the body
contract it implies usually is not. Cite the macro/method names and the grep
count as evidence.
3b. Pull drift-derived anti-patterns. Call
chameleon-mcp::get_drift_antipatterns(repo=<abs-repo-path>). For each
archetype it returns, the listed rules are conventions edits there repeatedly
bumped against (count is how often), and violation_edits is how often edits
drifted off-pattern. These point at where a counterexample earns its place:
open a flagged file for that archetype, read the actual off-pattern form the
rule names, and let it shape that candidate's counterexample — the tool
stores no wrong-way code, so you write the form from the file, never invent it.
When you save such a candidate, set source to note the drift origin, e.g.
"drift: import-preference-violation x6". Skip an archetype with no flagged
rules; do not manufacture an anti-pattern the history does not evidence.slug — ^[a-z][a-z0-9-]{2,63}$, descriptive.rationale — what to do AND why the team does it (one to three
sentences; the why is mandatory — extract it from code comments, docs,
or the visible consequence, never invent it; if the why is genuinely
unknowable, write "team convention" and say so in chat).example — real code from the repo, trimmed to the pattern.counterexample — what NOT to write (the thing a model would plausibly
produce without the idiom).archetype — set when the idiom is scoped to one archetype; OMIT the
field entirely for repo-wide idioms.chameleon-mcp::check_idiom_candidates(repo=<abs-repo-path>, candidates=[...]).
duplicate / covered → drop, and report each with its reasons. Never
reword a duplicate/covered candidate just to slip it past the gate —
that reintroduces the redundancy the gate exists to prevent.slug-exists-in-deprecated, or one ending :deprecated
(e.g. similar-to-idiom:zod-at-boundary:deprecated), means the candidate
re-derives a pattern the team DELIBERATELY deprecated. Don't silently
drop it as a generic duplicate — surface it to the user as "the team
already moved away from this; want it back?" so they can decide.invalid → fix the field and re-check, or drop.quality_warnings on a novel candidate → improve it (add the missing
example/counterexample, fatten a thin rationale) and re-check. Prefer
fewer, better idioms over volume.chameleon-mcp::teach_profile_structured(repo=..., slug=..., rationale=..., example=..., counterexample=..., archetype=..., status="active", source=...). Pass source as the provenance string: the 2-3 evidence file
paths you verified the occurrences in, plus the ref they were derived from
when known (e.g. "src/lib/api.ts, src/services/http.ts @ <production-ref-sha>").
This records where an auto-derived idiom came from so a poisoned one is
traceable and the trust gate shows its origin before /chameleon-trust.
Success/failure lives at data.status in the envelope ("success" /
"failed"), NOT at the top level — the call returns
{"api_version": "1", "data": {"status": ..., "idioms_added": ...}}.
Surface any failed envelope verbatim; do not silently mangle a slug to
force a write./chameleon-trust.| Dimension | What to look for | Where |
|---|---|---|
| Mandatory wrappers with a why | All call sites go through one helper; raw API absent or rare | service/util dirs, canonical witnesses |
| Domain vocabulary | One term used consistently where a synonym would be natural | model/class names, user copy, docs |
| Auth/security invariants | Every entry point applies the same guard | controllers, middleware, API routes |
| Money/time/precision handling | Integer cents, UTC-only, a single date lib via one helper | helpers + their call sites |
| Transaction/consistency patterns | Multi-write flows always wrapped the same way | services, jobs, models |
| Deprecated-vs-new API splits | Old and new pattern coexist; recent files use only the new | git-recent files vs older siblings |
| Cross-cutting conventions | Pagination, error envelopes, event naming, feature-flag usage | shared modules + consumers |
| Test data conventions | Factories-not-fixtures, builder helpers, network stubbing rules | spec/test dirs |
| Base-class / decorator contract | An archetype has a framework/gem dominant_base or class decorator (covered.class_contract), and its members share a body shape: typed DSL macros + a required method (ActiveInteraction string/integer + def execute; NestJS @Injectable + execute). Propose the full shape as one idiom even though the bare base is covered-by-inheritance. | canonical witness + 3-5 archetype members |
covered.naming, covered.lint_sources). The teach skill's anti-patterns
apply here verbatim.covered.competing_imports.covered.inheritance ("inherit from X" alone);
error-handling shape in covered.error_handling. The CONTRACT a base implies
(its mandatory DSL macros + required methods) is a candidate — see the
base-class/decorator contract row above.covered.principles line.body_shape is measured, not taught.| Failure | Action |
|---|---|
get_idiom_coverage → no profile in this repo | Suggest /chameleon-init, stop. |
get_idiom_coverage / check_idiom_candidates → status: untrusted | The profile isn't trusted; both tools withhold content. Tell the user to run /chameleon-trust, then re-run. Do NOT mine or write — active_count: 0 here is "withheld", not "no idioms". |
check_idiom_candidates → failed validation | Fix the batch shape (≤ 32 objects, slug + rationale each) and retry once. |
teach_profile_structured → slug already exists | The gate should have caught it; pick a new slug, re-check, re-present that one candidate. |
teach_profile_structured → another /chameleon-teach is in progress | Retry shortly; writes are flock-serialized. |
| Zero novel candidates survive | Honest outcome — report "profile + existing idioms already cover what the repo evidences" and suggest /chameleon-teach for tribal knowledge only humans hold. |
For each candidate ask: would a competent model, given chameleon's existing injection for this repo, plausibly write the counterexample? If no — the idiom adds nothing; drop it. If the rationale would be true of most codebases ("write clear code", "handle errors"), it's not a team idiom; drop it. One idiom = one actionable rule.
npx claudepluginhub crisnahine/chameleon --plugin chameleonCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.