Agent skill

Implement Rule

by ewhauser in ewhauser/shuck

Implement a shuck-rs lint rule from its YAML definition in docs/rules/.

MITAuto-check passedDevelopment

Install Implement Rule

skills CLI
$ npx skills add ewhauser/shuck --skill implement-rule -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install ewhauser/shuck implement-rule --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/ewhauser/shuck.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/implement-rule .claude/skills/implement-rule && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
implement-rule
GitHub stars
137
Token cost
~4.8k tokens
SKILL.md length
1,214 words
Files
2
Skills in repo
8
Repo updated
First seen
Licence
MIT

At a glance

Implement a shuck-rs lint rule from its YAML definition in docs/rules/.

  • Works in 8 steps: Understand the rule → Add to the registry → Create the category module (if needed) → …
  • The user asks to implement a rule (e.g.
  • SKILL.md covers Before you start, Step 1: Understand the rule, Step 2: Add to the registry and Step 3: Create the category…, plus 5 more sections
  • Calls cargo

What it does

Implement Rule is an agent skill from ewhauser/shuck. Implement a shuck-rs lint rule from its YAML definition in docs/rules/. Use this skill whenever the user asks to implement a rule (e.g., "implement C003", "implement docs/rules/X001.yaml", "add the unused-assignment rule"), wire up a new lint check, or build out a rule from its definition. This is about writing the Rust code that makes a rule actually detect violations — not about importing rule definitions (that's the import-rules skill).

Its SKILL.md is about 4.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files (for example `evals/evals.json`).

It sits in Development, covering Linting and formatting. It works with Rust. The repository describes itself as: A lightning fast shell linter/formatter/LSP server with zsh support. The licence is MIT.

When your agent uses it

  • The user asks to implement a rule (e.g.
  • Implement docs/rules/X001.yaml
  • Add the unused-assignment rule)
  • Wire up a new lint check

Example prompts

  • “implement C003”
  • “implement docs/rules/X001.yaml”
  • “add the unused-assignment rule”
  • “/implement-rule”

Workflow steps

8 steps, taken from the step headings in SKILL.md.

  1. Understand the rule
  2. Add to the registry
  3. Create the category module (if needed)
  4. Implement the rule
  5. Wire into checker dispatch
  6. Create the test fixture
  7. Run tests and accept snapshots
  8. Summarize

What it can do on your machine

Read from SKILL.md and the folder at commit 904974e. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Implement Rule loads about 4.8k tokens when it runs. Until then it costs about 115 tokens; SKILL.md has 1,214 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~115
When it runs · the whole SKILL.md, loaded when a task matches
~4.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from ewhauser/shuck at commit 904974e, republished under its MIT licence (© ewhauser). 1,214 words, ~4,771 tokens.

Download SKILL.mdSave it as .claude/skills/implement-rule/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
implement-rule
description
Implement a shuck-rs lint rule from its YAML definition in docs/rules/. Use this skill whenever the user asks to implement a rule (e.g., "implement C003", "implement docs/rules/X001.yaml", "add the unused-assignment rule"), wire up a new lint check, or build out a rule from its definition. This is about writing the Rust code that makes a rule actually detect violations — not about importing rule definitions (that's the import-rules skill).

Implement a Lint Rule

This skill turns a YAML rule definition in docs/rules/ into a working lint rule with violation struct, checker dispatch, test fixture, and snapshot test.

Before you start

Read these files to understand the current state:

  1. The YAML rule definition the user wants to implement (e.g., docs/rules/C003.yaml)
  2. crates/shuck-linter/src/registry.rs — to see existing rules and find where to insert
  3. crates/shuck-linter/src/checker.rs — to see current dispatch phases
  4. crates/shuck-linter/src/rules/correctness/unused_assignment.rs — the reference implementation to follow

Also read the semantic model to understand what data is available for the rule:

  • crates/shuck-semantic/src/lib.rs — SemanticModel public API

Step 1: Understand the rule

Read the YAML definition. Key fields:

yaml
new_category: Correctness    # → Category module: correctness, style, performance, portability, security
new_code: C001               # → Rule code used in registry
shellcheck_code: SC2034       # → ShellCheck mapping for suppression
description: ...              # → What the rule detects
examples:                     # → Test cases to base the fixture on

From the description and examples, determine:

  • What semantic data the rule needs (bindings, references, scopes, declarations, source refs, AST, dataflow)
  • Which checker phase is appropriate (see "Choosing the checker phase" below)
  • What false positives to filter out

Step 2: Add to the registry

File: crates/shuck-linter/src/registry.rs

Add an entry to the declare_rules! macro. Choose a PascalCase variant name that clearly describes the violation. Insert it in code-order (C001 before C002, etc.).

rust
declare_rules! {
    ("C001", Category::Correctness, Severity::Warning, UnusedAssignment),
    // Add new rule here in code-sorted order
    ("C003", Category::Correctness, Severity::Warning, NewRuleName),
    ...
}

Severity guidelines:

  • Error — the code is almost certainly wrong (undefined variable, unreachable code)
  • Warning — likely a problem but could be intentional (unused assignment, unquoted expansion)
  • Hint — suggestion, no real risk (style preferences)

If the YAML has a legacy_code (SH-NNN), add a legacy alias in code_to_rule():

rust
"SH-NNN" => Some(Rule::NewRuleName),

If there's a shellcheck_code, add it to crates/shuck-linter/src/suppression/shellcheck_map.rs:

rust
(NNNN, Rule::NewRuleName),  // SCNNNN

Step 3: Create the category module (if needed)

If this is the first rule in a category, create the module structure:

crates/shuck-linter/src/rules/{category}/
├── mod.rs

And register it in crates/shuck-linter/src/rules/mod.rs:

rust
pub mod correctness;
pub mod style;  // new category

The mod.rs should contain a #[cfg(test)] block following the snapshot test pattern:

rust
#[cfg(test)]
mod tests {
    use std::path::Path;

    use test_case::test_case;

    use crate::{LinterSettings, Rule, assert_diagnostics};
    use crate::test::test_path;

    #[test_case(Rule::NewRuleName, Path::new("C003.sh"))]
    fn rules(rule: Rule, path: &Path) -> anyhow::Result<()> {
        let snapshot = format!("{}_{}", rule.code(), path.display());
        let (diagnostics, source) = test_path(
            Path::new("{category}").join(path).as_path(),
            &LinterSettings::for_rule(rule),
        )?;
        assert_diagnostics!(snapshot, diagnostics, &source);
        Ok(())
    }
}

If the category module already exists, just add a new #[test_case] line to the existing rules function.

Step 4: Implement the rule

Create crates/shuck-linter/src/rules/{category}/{rule_name}.rs.

Critical design principle: Rules must be cheap filters over pre-computed facts. Do NOT add direct AST walks, traversal helpers, command normalization, test operand reconstruction, or word/redirect/substitution classification in rule files. If a rule needs new structural data, add it to LinterFacts in crates/shuck-linter/src/facts.rs and consume it from there.

Two data sources

Rules access data through two paths:

  1. checker.facts() — Pre-computed LinterFacts. This is the primary data source for most rules. Facts normalize commands, extract options, classify words, analyze tests, and index structural patterns (pipelines, loops, redirects, substitutions). Prefer facts for anything structural or command-oriented.

  2. checker.semantic() — The SemanticModel. Use this for variable binding/reference analysis (unused assignments, undefined variables, scope queries, call graphs). These rules iterate semantic collections directly.

Violation struct pattern
rust
use crate::{Checker, Rule, Violation};

pub struct RuleName {
    // Fields that provide context for the diagnostic message.
    // Common: `name: String` for variable names.
    // Use no fields if the message is always the same (preferred).
}

impl Violation for RuleName {
    fn rule() -> Rule {
        Rule::RuleName
    }

    fn message(&self) -> String {
        // Concise, lowercase message describing the violation.
        "description of what's wrong".to_owned()
    }
}

Register the module in the category's mod.rs:

rust
pub mod rule_name;
Pattern A: Fact-based rules (most rules)

Filter pre-computed facts, collect spans, report. This is the standard pattern.

Command facts — for rules about specific commands (read, printf, exit, find, xargs, sudo, etc.):

rust
pub fn read_without_raw(checker: &mut Checker) {
    let spans = checker
        .facts()
        .structural_commands()                              // iterator over CommandFact
        .filter(|fact| fact.effective_name_is("read"))      // normalized name (unwraps env/command/sudo)
        .filter(|fact| {
            fact.options()
                .read()                                     // pre-parsed ReadCommandFacts
                .is_some_and(|read| !read.uses_raw_input)
        })
        .filter_map(|fact| fact.body_name_word().map(|word| word.span))
        .collect::<Vec<_>>();

    checker.report_all(spans, || ReadWithoutRaw);
}

Pipeline facts — for rules about piped command sequences:

rust
pub fn find_output_to_xargs(checker: &mut Checker) {
    let spans = checker
        .facts()
        .pipelines()                                        // &[PipelineFact]
        .iter()
        .flat_map(|pipeline| unsafe_find_to_xargs_spans(checker, pipeline))
        .collect::<Vec<_>>();

    checker.report_all_dedup(spans, || FindOutputToXargs);
}

fn unsafe_find_to_xargs_spans(checker: &Checker<'_>, pipeline: &PipelineFact<'_>) -> Vec<Span> {
    pipeline.segments().windows(2).filter_map(|pair| {
        let left = checker.facts().command_for_stmt(pair[0].stmt())?;   // cross-reference
        let right = checker.facts().command_for_stmt(pair[1].stmt())?;

        if !pair[0].effective_name_is("find") || !pair[1].effective_name_is("xargs") {
            return None;
        }
        if left.options().find().is_some_and(|f| f.has_print0)
            && right.options().xargs().is_some_and(|x| x.uses_null_input) {
            return None;  // null-delimited pair is safe
        }
        Some(left.body_span())
    }).collect()
}

Loop header facts — for rules about for/select loop iteration lists:

rust
pub fn find_output_loop(checker: &mut Checker) {
    let spans = checker
        .facts()
        .for_headers()                                      // &[ForHeaderFact]
        .iter()
        .flat_map(|header| header.words().iter())
        .filter(|word| word.contains_find_substitution())   // pre-computed
        .map(|word| word.span())
        .collect::<Vec<_>>();

    checker.report_all(spans, || FindOutputLoop);
}

Test/conditional facts — for rules about [...] and [[...]] tests:

rust
pub fn constant_comparison_test(checker: &mut Checker) {
    let spans = checker
        .facts()
        .commands()
        .iter()
        .filter(|fact| {
            fact.simple_test().is_some_and(simple_test_is_constant)     // SimpleTestFact
                || fact.conditional().is_some_and(conditional_is_constant) // ConditionalFact
        })
        .map(|fact| fact.span())
        .collect::<Vec<_>>();

    checker.report_all(spans, || ConstantComparisonTest);
}

Redirect facts — for rules about redirections on specific commands:

rust
pub fn sudo_redirection_order(checker: &mut Checker) {
    let spans = checker
        .facts()
        .commands()
        .iter()
        .filter(|fact| fact.has_wrapper(WrapperKind::SudoFamily))
        .flat_map(|fact| {
            fact.redirect_facts().iter().filter_map(|redirect| {
                (redirects_output(redirect.redirect().kind)
                    && !redirect.analysis()
                        .is_some_and(|a| a.is_definitely_dev_null()))
                .then(|| redirect.target_span()).flatten()
            })
        })
        .collect::<Vec<_>>();

    checker.report_all_dedup(spans, || SudoRedirectionOrder);
}

Surface fragment facts — for lexer-level patterns (backticks, single quotes, etc.):

rust
// Access via checker.facts().backtick_fragments(), .single_quoted_fragments(), etc.

Word facts — for rules about word expansion contexts:

rust
// Access via checker.facts().word_facts(), .expansion_word_facts(context), .case_subject_facts()
Key fact access methods
MethodReturnsUse for
facts.commands()All command factsGeneral command matching
facts.structural_commands()Top-level commands (iterator)Commands not inside substitutions
facts.pipelines()Pipeline factsMulti-command pipe analysis
facts.for_headers() / facts.select_headers()Loop list factsLoop iteration patterns
facts.lists()List operator factsMixed &&/|| detection
facts.word_facts()Word expansion factsQuoting/expansion analysis
facts.expansion_word_facts(ctx)Words in specific contextContext-filtered word analysis
facts.case_subject_facts()Case subject word factsCase statement analysis
facts.single_quoted_fragments()Single-quoted spansLiteral-in-quotes detection
facts.backtick_fragments()Backtick substitution spansLegacy syntax detection
facts.command_for_stmt(stmt)Command fact by AST nodeCross-referencing pipelines/loops
facts.command_for_command(cmd)Command fact by CommandLookup from AST reference
facts.word_fact(span, ctx)Word fact by span+contextTargeted word lookup
CommandFact key methods
MethodReturnsUse for
fact.effective_name_is(name)boolNormalized name check (unwraps wrappers)
fact.has_wrapper(kind)boolCheck for sudo/env/command wrapping
fact.options()CommandOptionFactsPre-parsed command-specific options
fact.body_name_word()Option<&Word>The body command's name word (for span)
fact.body_span()SpanSpan of the body command
fact.span()SpanFull command span
fact.redirect_facts()&[RedirectFact]Pre-analyzed redirections
fact.simple_test()Option<&SimpleTestFact>[...] test structure
fact.conditional()Option<&ConditionalFact>[[...]] test structure
fact.substitution_facts()&[SubstitutionFact]Command substitution metadata
CommandOptionFacts (pre-parsed per-command data)
MethodReturnsUse for
.read()Option<ReadCommandFacts>read -r detection
.printf()Option<PrintfCommandFacts>Format word extraction
.unset()Option<UnsetCommandFacts>Function mode, operand words
.find()Option<FindCommandFacts>-print0 detection
.xargs()Option<XargsCommandFacts>-0/--null detection
.exit()Option<ExitCommandFacts>Status word and staticness
.sudo_family()Option<SudoFamilyCommandFacts>Invoker type (sudo/doas/run0)
Pattern B: Semantic-based rules (binding/reference rules)

For rules that analyze variable assignments and references, iterate semantic collections directly:

rust
pub fn unused_assignment(checker: &mut Checker) {
    for &binding_id in checker.semantic().unused_assignments() {
        let binding = checker.semantic().binding(binding_id);

        if !is_reportable(binding.kind, binding.attributes) { continue; }
        if binding.attributes.contains(BindingAttributes::EXPORTED) { continue; }
        if matches!(binding.kind, BindingKind::Nameref) { continue; }

        checker.report(
            UnusedAssignment { name: binding.name.to_string() },
            binding.span,
        );
    }
}
Show full SKILL.md (486 more words)Show less
Semantic model methods (for Pattern B only)
MethodReturnsUse for
semantic.bindings()All variable bindingsIterating assignments
semantic.binding(id)Single bindingLooking up by ID
semantic.references()All variable referencesIterating uses
semantic.resolved_binding(ref_id)Binding a reference resolves toDef-use chains
semantic.unresolved_references()References with no bindingUndefined variables
semantic.unused_assignments()Bindings never readDead assignments
semantic.declarations()declare/local/export commandsDeclaration analysis
semantic.source_refs()source/. commandsDynamic source paths
semantic.call_sites_for(name)Where a function is calledFunction call analysis
semantic.call_graph()Reachable/uncalled functionsDead function detection
semantic.scope_kind(id)File/Function/Subshell/PipelineScope-aware rules
Common semantic filtering
rust
// Skip exported variables (consumed by child processes)
if binding.attributes.contains(BindingAttributes::EXPORTED) { continue; }

// Skip function definitions (not regular assignments)
if matches!(binding.kind, BindingKind::FunctionDefinition) { continue; }

// Skip nameref bindings (used indirectly)
if matches!(binding.kind, BindingKind::Nameref) { continue; }

// Skip imported bindings
if matches!(binding.kind, BindingKind::Imported) { continue; }
Anti-patterns to avoid
  • No direct AST walks in rule files. Don't call walk_commands, iter_commands, or recurse through child nodes. If you need structural data, add it to LinterFacts.
  • No command normalization in rules. Use fact.effective_name_is() and fact.has_wrapper() — names are already normalized through env/command/sudo wrappers.
  • No option parsing in rules. Use fact.options().read(), .find(), .xargs(), etc. If a new command needs option analysis, add it to CommandOptionFacts in facts.rs.
  • No word expansion analysis in rules. Use pre-computed WordFact with its expansion analysis, operand class, and static text. Add new word analysis to facts.rs if needed.
  • No test operand reconstruction. Use SimpleTestFact and ConditionalFact with their pre-computed shapes, operator families, and operand classes.
  • No imports from crate::rules::common::* in rule files. Rule-facing shared types come from the crate root (re-exported from common modules).

Step 5: Wire into checker dispatch

File: crates/shuck-linter/src/checker.rs

Add the rule invocation to the appropriate phase method:

rust
fn check_command_facts(&mut self) {
    // ... existing rules ...
    if self.is_rule_enabled(Rule::NewRuleName) {
        rules::category::rule_name::rule_name(self);
    }
}
Choosing the checker phase

Match the rule to the phase based on what data it primarily consumes:

PhaseUse when the rule...Examples
check_bindingsIterates semantic bindings (assignments)UnusedAssignment
check_referencesIterates semantic references (variable uses)UndefinedVariable
check_scopesChecks scope-level properties(reserved)
check_declarationsChecks declare/local/exportLocalTopLevel
check_call_sitesChecks function call patternsOverwrittenFunction
check_source_refsChecks source/. commandsDynamicSourcePath
check_command_factsFilters command facts (name, options, structure)ReadWithoutRaw, InvalidExitStatus, PrintfFormatVariable
check_word_and_expansion_factsFilters word/expansion factsUnquotedExpansion, TrapStringExpansion, CasePatternVar
check_loop_list_and_pipeline_factsFilters pipeline/loop/list factsFindOutputToXargs, FindOutputLoop, LoopFromCommandOutput
check_redirect_and_substitution_factsFilters redirect/substitution factsSudoRedirectionOrder, SubstWithRedirect
check_surface_fragment_factsFilters lexer-level fragment factsLegacyBackticks, SingleQuotedLiteral
check_test_and_conditional_factsFilters test/conditional factsConstantComparisonTest, QuotedBashRegex
check_flowNeeds CFG/dataflow analysisUnreachableAfterExit

Decision guide: If the rule iterates checker.semantic().*, use one of the first six phases. If it iterates checker.facts().*, pick the fact-category phase that matches. Most new rules will use one of the fact-based phases (check_command_facts through check_test_and_conditional_facts).

Step 6: Create the test fixture

File: crates/shuck-linter/resources/test/fixtures/{category}/{CODE}.sh

Write a shell script that exercises both positive cases (should trigger) and negative cases (should not trigger). Use comments to label each section:

bash
#!/bin/sh

# Should trigger: description of case
problematic_code_here

# Should not trigger: description of case
valid_code_here

Cover:

  • The basic violation from the YAML examples
  • Common false-positive scenarios that should NOT trigger
  • Edge cases specific to the rule

Step 7: Run tests and accept snapshots

bash
cargo test -p shuck-linter

The snapshot test will fail the first time (new snapshot). Review the output to confirm it looks correct, then accept:

bash
cargo insta accept --workspace

Run the full test suite to check for regressions:

bash
cargo test --workspace

Step 8: Summarize

After implementation, report:

  • Rule code and name
  • Which checker phase it's dispatched in
  • How many test cases the fixture covers
  • Whether all tests pass

© ewhauser, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in .claude/skills/implement-rule of ewhauser/shuck.

  • SKILL.md
  • evals/evals.json

Open the folder on GitHubat commit 904974e

Compare with similar skills

Implement Rule next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Implement Rule compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Implement Rule this skillewhauser/shuck137—~4.8kAutomated safety check: PassMIT
Rust Best Practicesfarm-fe/farm5.6k3 repos~1.1kAutomated safety check: PassMIT
Doc Commentsbiomejs/biome26k—~3kAutomated safety check: PassApache-2.0
Rust Hygiene Audittsz-org/tsz577—~1.5kAutomated safety check: PassApache-2.0
Releasexin2017338/lynx-proxy502—~1.1kAutomated safety check: PassMIT
Flowmark Markdown Formatterjlevy/repren374—~631Automated safety check: PassMIT

Similar skills

  • Guide for writing idiomatic Rust code based on Apollo GraphQL's best practices handbook.

    5.6k GitHub starsUsed in 3 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Doc Comments

    biomejs/biome

    Official

    A skill your agent uses whenever writing or editing Rust //, ///, or //!

    26k GitHub stars~3k tokensUpdated today
    DevelopmentAuto-check passed
  • Run a deep DRY + code-hygiene audit of the Rust workspace and turn the findings into verified, deduplicated, hierarchical GitHub tech-debt issues.

    577 GitHub stars~1.5k tokensUpdated 28 days ago
    DevelopmentAuto-check passed
  • Release

    xin2017338/lynx-proxy

    Publish a new release version of Lynx Proxy. An agent skill from xin2017338/lynx-proxy.

    502 GitHub stars~1.1k tokensUpdated 23 days ago
    DevelopmentAuto-check passed
  • Formats Markdown with the Flowmark auto-formatter for typographic cleanup and semantic line breaks, and helps adopt it across a repository.

    374 GitHub stars~631 tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Rsigma

    timescale/rsigma

    Use the rsigma CLI and MCP server: engine eval, engine daemon, rule lint, rule draft, rule tune, rule backtest, backend convert, mcp serve.

    159 GitHub stars~1.2k tokensUpdated yesterday
    DevelopmentAuto-check passed

More from ewhauser/shuck

All 8 skills in this repo
  • Profile Shuck Script

    ewhauser/shuck

    Profile shuck scripts and large-corpus fixtures, especially requests to profile a corpus script/fixture, reprofile after a shuck performance change, or produce a hotspot table from a samply profile.

    137 GitHub stars~1.3k tokensUpdated 3 days ago
    Auto-check passed
  • Bench Compare

    ewhauser/shuck

    Compare benchmark performance between two git worktrees (or the current worktree vs main).

    137 GitHub stars~2.4k tokensUpdated 3 days ago
    Auto-check passed
  • Conformance Check

    ewhauser/shuck

    Verify ShellCheck conformance for a shuck rule by running the large corpus test, analyzing deltas, and producing a structured bug document in docs/bugs/.

    137 GitHub stars~3.1k tokensUpdated 3 days ago
    Auto-check passed
  • Fix Rule

    ewhauser/shuck

    Fix a shuck lint rule that has conformance deltas against ShellCheck.

    137 GitHub stars~3.2k tokensUpdated 3 days ago
    Auto-check passed
  • Implement Fix

    ewhauser/shuck

    Implement an autofix for an existing shuck-rs lint rule. An agent skill from ewhauser/shuck.

    137 GitHub stars~3.1k tokensUpdated 3 days ago
    Auto-check passed
  • Spec Writer

    ewhauser/shuck

    Write and update technical design specifications. An agent skill from ewhauser/shuck.

    137 GitHub stars~1.7k tokensUpdated 3 days ago
    Auto-check passed

Works with

Categories

Questions about Implement Rule

What does Implement Rule do?

Implement a shuck-rs lint rule from its YAML definition in docs/rules/. Implement Rule is an agent skill from ewhauser/shuck. Implement a shuck-rs lint rule from its YAML definition in docs/rules/.

When should I use Implement Rule?

Implement Rule fits situations like: the user asks to implement a rule (e.g; implement docs/rules/X001.yaml; add the unused-assignment rule); wire up a new lint check.

How do I install Implement Rule in Claude Code?

Run `npx skills add ewhauser/shuck --skill implement-rule -a claude-code`. Or copy the skill folder (.claude/skills/implement-rule in ewhauser/shuck) into .claude/skills/implement-rule in your project. Claude Code loads it when a task matches its description.

How do I install Implement Rule in Codex?

Run `npx skills add ewhauser/shuck --skill implement-rule -a codex`. Or copy the skill folder (.claude/skills/implement-rule in ewhauser/shuck) into .agents/skills/implement-rule in your project. Codex loads it when a task matches its description.

Can I use Implement Rule in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ewhauser/shuck --skill implement-rule -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/implement-rule, .gemini/skills/implement-rule, .github/skills/implement-rule and .opencode/skills/implement-rule in your project.

What does Implement Rule need to run?

Going by SKILL.md and its folder, Implement Rule needs the command-line tools its instructions call (cargo).

Does Implement Rule access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Implement Rule safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Implement Rule use?

Implement Rule is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Implement Rule use?

About 4.8k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Implement Rule?

Skills that share tags, products or a category with Implement Rule: Rust Best Practices (farm-fe/farm, 5.6k stars), Doc Comments (biomejs/biome, 26k stars), Rust Hygiene Audit (tsz-org/tsz, 577 stars) and Release (xin2017338/lynx-proxy, 502 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Implement Rule?

ewhauser (a GitHub user) maintains it in ewhauser/shuck, which has 137 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on October 5, 2026.

Source: ewhauser/shuck on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.