AST Visitor Pattern for Unions
prisma/orm
Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants.
Describes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill.
$ npx skills add rtk-ai/rtk --skill design-patterns -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install rtk-ai/rtk design-patterns --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/design-patterns .claude/skills/design-patterns && rm -rf skills-srcUse ~/.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/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .claude/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patternsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add rtk-ai/rtk --skill design-patterns -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install rtk-ai/rtk design-patterns --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/design-patterns .agents/skills/design-patterns && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .agents/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add rtk-ai/rtk --skill design-patterns -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install rtk-ai/rtk design-patterns --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/design-patterns .cursor/skills/design-patterns && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .cursor/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/rtk-ai/rtk.git --path .claude/skills/design-patterns--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add rtk-ai/rtk --skill design-patterns -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install rtk-ai/rtk design-patterns --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/design-patterns .gemini/skills/design-patterns && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .gemini/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install rtk-ai/rtk design-patternsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add rtk-ai/rtk --skill design-patterns -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/design-patterns .github/skills/design-patterns && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .github/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add rtk-ai/rtk --skill design-patterns -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install rtk-ai/rtk design-patterns --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rtk-ai/rtk.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/design-patterns .opencode/skills/design-patterns && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "design-patterns" agent skill from https://github.com/rtk-ai/rtk/tree/develop/.claude/skills/design-patterns into .opencode/skills/design-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "design-patterns", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
design-patternsDescribes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill.
RTK's filter module architecture is the subject of this pattern guide, which is aimed at CLI tool code rather than web or service code. Each pattern comes with a use-when rule and a Rust example from RTK: Newtype to stop primitives such as command names, paths and token counts being mixed up, Builder for structs with four or more optional fields, and State Machine for parsing multi-section output such as pytest results.
It also covers Trait Objects for command dispatch, RAII for temp files and SQLite connections, Strategy for swappable filter modes such as compact and summary, and Extension Traits for adding methods to types like str. It states limits as well: Builder is overkill for one to three obvious fields, and RTK's static match dispatch in main.rs is intentional until it passes about 20 commands. The skill only needs file reading and search tools.
Read from SKILL.md and the folder at commit e0b2e85. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadGrepGlobFrom allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are rust).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
RTK Rust Design Patterns loads about 1.9k tokens when it runs. Until then it costs about 48 tokens; SKILL.md has 260 words of instructions outside code blocks.
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.
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.
The full file from rtk-ai/rtk at commit e0b2e85, republished under its Apache-2.0 licence (© rtk-ai). 260 words, ~1,859 tokens.
.claude/skills/design-patterns/SKILL.md (or your agent's skills folder).Patterns that apply to RTK's filter module architecture. Focused on CLI tool patterns, not web/service patterns.
Use when: wrapping primitive types to prevent misuse (command names, paths, token counts).
// Without Newtype — easy to mix up
fn track(input_tokens: usize, output_tokens: usize) { ... }
track(output_tokens, input_tokens); // Silent bug!
// With Newtype — compile error on swap
pub struct InputTokens(pub usize);
pub struct OutputTokens(pub usize);
fn track(input: InputTokens, output: OutputTokens) { ... }
track(OutputTokens(100), InputTokens(400)); // Compile error ✅// Practical RTK example: command name validation
pub struct CommandName(String);
impl CommandName {
pub fn new(s: &str) -> Result<Self> {
if s.contains(';') || s.contains('|') || s.contains('`') {
anyhow::bail!("Invalid command name: shell metacharacters");
}
Ok(Self(s.to_string()))
}
pub fn as_str(&self) -> &str { &self.0 }
}Use when: a struct has 4+ optional fields, many with defaults.
#[derive(Default)]
pub struct FilterConfig {
max_lines: Option<usize>,
strip_ansi: bool,
show_warnings: bool,
truncate_at: Option<usize>,
}
impl FilterConfig {
pub fn new() -> Self { Self::default() }
pub fn max_lines(mut self, n: usize) -> Self { self.max_lines = Some(n); self }
pub fn strip_ansi(mut self, v: bool) -> Self { self.strip_ansi = v; self }
pub fn show_warnings(mut self, v: bool) -> Self { self.show_warnings = v; self }
}
// Usage — readable, no positional arg confusion
let config = FilterConfig::new()
.max_lines(50)
.strip_ansi(true)
.show_warnings(false);When NOT to use Builder: if the struct has 1-3 fields with obvious meaning. Over-engineering for simple cases.
Use when: parsing multi-section output (test results, build output) where context changes behavior.
// RTK example: pytest output parsing
#[derive(Debug, PartialEq)]
enum ParseState {
LookingForTests,
InTestOutput,
InFailureSummary,
Done,
}
fn parse_pytest(input: &str) -> String {
let mut state = ParseState::LookingForTests;
let mut failures = Vec::new();
for line in input.lines() {
match state {
ParseState::LookingForTests => {
if line.contains("FAILED") || line.contains("ERROR") {
state = ParseState::InFailureSummary;
failures.push(line);
}
}
ParseState::InFailureSummary => {
if line.starts_with("=====") { state = ParseState::Done; }
else { failures.push(line); }
}
ParseState::Done => break,
_ => {}
}
}
failures.join("\n")
}Use when: different command families need the same interface. Avoids massive match arms.
// Define a common interface for filters
pub trait OutputFilter {
fn filter(&self, input: &str) -> Result<String>;
fn command_name(&self) -> &str;
}
pub struct GitFilter;
pub struct CargoFilter;
impl OutputFilter for GitFilter {
fn filter(&self, input: &str) -> Result<String> { filter_git(input) }
fn command_name(&self) -> &str { "git" }
}
// RTK currently uses match-based dispatch in main.rs (simpler, no dynamic dispatch overhead)
// Trait objects are useful if filter registry becomes dynamic (e.g., TOML-loaded plugins)Note: RTK's current match dispatch in main.rs is intentional — static dispatch, zero overhead. Only move to trait objects if the match arm count exceeds ~20 commands.
Use when: managing resources that need cleanup (temp files, SQLite connections).
// RTK tee.rs — RAII for temp output files
pub struct TeeFile {
path: PathBuf,
}
impl TeeFile {
pub fn create(content: &str) -> Result<Self> {
let path = tee_path()?;
fs::write(&path, content)
.with_context(|| format!("Failed to write tee file: {}", path.display()))?;
Ok(Self { path })
}
pub fn path(&self) -> &Path { &self.path }
}
// No explicit cleanup needed — file persists intentionally (rotation handled separately)
// If cleanup were needed: impl Drop { fn drop(&mut self) { let _ = fs::remove_file(&self.path); } }Use when: a command has multiple filtering modes (e.g., compact vs. verbose).
pub enum FilterMode {
Compact, // Show only failures/errors
Summary, // Show counts + top errors
Full, // Pass through unchanged
}
pub fn apply_filter(input: &str, mode: FilterMode) -> String {
match mode {
FilterMode::Compact => filter_compact(input),
FilterMode::Summary => filter_summary(input),
FilterMode::Full => input.to_string(),
}
}Use when: you need to add methods to types you don't own (like &str for RTK-specific parsing).
pub trait RtkStrExt {
fn is_error_line(&self) -> bool;
fn is_warning_line(&self) -> bool;
fn token_count(&self) -> usize;
}
impl RtkStrExt for str {
fn is_error_line(&self) -> bool {
self.starts_with("error") || self.contains("[E")
}
fn is_warning_line(&self) -> bool {
self.starts_with("warning")
}
fn token_count(&self) -> usize {
self.split_whitespace().count()
}
}
// Usage
if line.is_error_line() { ... }
let tokens = output.token_count();| Situation | Pattern | Avoid |
|---|---|---|
New *_cmd.rs filter module | Standard module pattern (see CLAUDE.md) | Over-abstracting |
| 4+ optional config fields | Builder | Struct literal |
| Multi-phase output parsing | State Machine | Nested if/else |
| Type-safe wrapper around string | Newtype | Raw String |
Adding methods to &str | Extension Trait | Free functions |
| Resource with cleanup | RAII / Drop | Manual cleanup |
| Dynamic filter registry | Trait Object | Match sprawl |
// ❌ Generic over-engineering for one command
pub trait Filterable<T: CommandArgs + Send + Sync + 'static> { ... }
// ✅ Just write the function
pub fn filter_git_log(input: &str) -> Result<String> { ... }
// ❌ Singleton registry with global state
static FILTER_REGISTRY: Mutex<HashMap<String, Box<dyn Filter>>> = ...;
// ✅ Match in main.rs — simple, zero overhead, easy to trace
// ❌ Async traits for "future-proofing"
#[async_trait]
pub trait Filter { async fn apply(&self, input: &str) -> Result<String>; }
// ✅ Synchronous — RTK is single-threaded by design
pub trait Filter { fn apply(&self, input: &str) -> Result<String>; }© rtk-ai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/design-patterns of rtk-ai/rtk.
Open the folder on GitHubat commit e0b2e85
RTK Rust Design Patterns 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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| RTK Rust Design Patterns this skillrtk-ai/rtk | 83k | — | ~1.9k | Automated safety check: Pass | Apache-2.0 | |
| AST Visitor Pattern for Unionsprisma/orm | 48k | — | ~830 | Automated safety check: Pass | Apache-2.0 | |
| Typed Dependencies with fp-go EffectIBM/fp-go | 2k | — | ~4.3k | Automated safety check: Pass | Apache-2.0 | |
| Rust Architectsergigp/yarrtube | 127 | — | ~6.1k | Automated safety check: Pass | MIT | |
| Migrate Core Code to Submodulestinyhumansai/openhuman | 41k | — | ~2.6k | Automated safety check: Pass | GPL-3.0 | |
| Swiftui View RefactorDimillian/Skills | 4k | 5 repos | ~2k | Automated safety check: Pass | MIT |
prisma/orm
Replaces a plain TypeScript union plus switch statements with frozen subclasses and a visitor interface when several places dispatch on the same variants.
IBM/fp-go
Teaches an agent to write fp-go v2 services with the Effect type, carrying dependencies in its type parameter instead of in context.Context or parameters.
sergigp/yarrtube
Architecture, naming, and testing conventions guidelines for architecting Rust codebases.
tinyhumansai/openhuman
Plans and carries out moving non-host-specific code and its tests from the OpenHuman core into vendored tiny submodule libraries, then releases the submodule and re-pins the host.
Dimillian/Skills
Refactor and review SwiftUI view files with strong defaults for small dedicated subviews, MV-over-MVVM data flow, stable view trees, explicit dependency injection, and correct Observation usage.
farm-fe/farm
Guide for writing idiomatic Rust code based on Apollo GraphQL's best practices handbook.
rtk-ai/rtk
Enforces red-green-refactor for Rust work, with idiomatic test patterns, a naming convention and a pre-commit gate of cargo fmt, clippy and test.
rtk-ai/rtk
Enforces red-green-refactor for new RTK output filters in Rust, using real captured fixtures, snapshot tests with insta and token-savings assertions.
rtk-ai/rtk
Reviews RTK's Rust code for over-engineering and verbose patterns, applying idioms like iterator chains and early returns while protecting a specific list of constraints from being simplified away.
rtk-ai/rtk
Audits open GitHub issues, categorizes them, flags duplicates and linked PRs in three phases, with optional deep analysis and comments posted only after validation.
rtk-ai/rtk
Audits a repository's open pull requests, deep-reviews chosen ones and drafts review comments that are only posted after you approve them.
rtk-ai/rtk
Runs issue triage and PR triage in parallel, then cross-analyzes the results to flag duplicate coverage, security gaps, P0 issues with no PR, and PR conflicts.
Categories
Describes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill. RTK's filter module architecture is the subject of this pattern guide, which is aimed at CLI tool code rather than web or service code. Each pattern comes with a use-when rule and a Rust example from RTK: Newtype to stop primitives such as command names, paths and token counts being mixed up, Builder for structs with four or more optional fields, and State Machine for parsing multi-section output such as pytest results.
RTK Rust Design Patterns fits situations like: designing a new filter module in RTK; refactoring an existing module to a clearer pattern; deciding whether trait objects are warranted over the current match dispatch.
Run `npx skills add rtk-ai/rtk --skill design-patterns -a claude-code`. Or copy the skill folder (.claude/skills/design-patterns in rtk-ai/rtk) into .claude/skills/design-patterns in your project. Claude Code loads it when a task matches its description.
Run `npx skills add rtk-ai/rtk --skill design-patterns -a codex`. Or copy the skill folder (.claude/skills/design-patterns in rtk-ai/rtk) into .agents/skills/design-patterns in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rtk-ai/rtk --skill design-patterns -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/design-patterns, .gemini/skills/design-patterns, .github/skills/design-patterns and .opencode/skills/design-patterns in your project.
SKILL.md names no scripts, command-line tools or credentials: RTK Rust Design Patterns is instructions for the agent only. Our summary lists: The RTK Rust codebase. Its frontmatter pre-approves these tools: Read, Grep, Glob.
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.
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.
RTK Rust Design Patterns is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 1.9k tokens (SKILL.md is roughly 7.4k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with RTK Rust Design Patterns: AST Visitor Pattern for Unions (prisma/orm, 48k stars), Typed Dependencies with fp-go Effect (IBM/fp-go, 2k stars), Rust Architect (sergigp/yarrtube, 127 stars) and Migrate Core Code to Submodules (tinyhumansai/openhuman, 41k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
rtk-ai (a GitHub organization) maintains it in rtk-ai/rtk, which has 82,568 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on October 7, 2026.
Source: rtk-ai/rtk on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.