rtk-ai/rtk
View on GitHubfeat(registry): rewrite-layer normalization for pnpm --filter
Open
#513 opened on Mar 11, 2026
area:clieffort-mediumenhancementhelp wantedpriority:medium
Repository metrics
- Stars
- (48,085 stars)
- PR merge metrics
- (Avg merge 11d 1h) (45 merged PRs in 30d)
Description
Part of #512 — pnpm workspace filter support.
Phase 1: src/discover/registry.rs
1a. Add PNPM_FILTER_RE to the existing lazy_static! block
static ref PNPM_FILTER_RE: Regex = Regex::new(
r"^pnpm\s+(?:--filter|-F)\s+(\S+)\s+(.+)$"
).unwrap();
1b. Add strip_pnpm_workspace_flag()
fn strip_pnpm_workspace_flag(cmd: &str) -> Option<(&str, &str)> {
PNPM_FILTER_RE.captures(cmd).and_then(|caps| {
let m1 = caps.get(1)?;
let m2 = caps.get(2)?;
Some((&cmd[m1.start()..m1.end()], &cmd[m2.start()..m2.end()]))
})
}
1c. Add inject_pnpm_filter()
fn inject_pnpm_filter(rtk_cmd: &str, workspace: &str) -> String {
let mut parts = rtk_cmd.splitn(3, ' ');
let rtk = parts.next().unwrap_or("rtk");
let cmd = parts.next().unwrap_or("");
match parts.next() {
Some(rest) => format!("{} {} --pnpm-filter {} {}", rtk, cmd, workspace, rest),
None => format!("{} {} --pnpm-filter {}", rtk, cmd, workspace),
}
}
1d. Extract rewrite_core() from rewrite_segment()
Extract the classify+rule-match+prefix-replace logic into a standalone fn that operates on pre-cleaned commands (no env prefix). This avoids recursive rewrite_segment() calls that would re-trigger env prefix stripping, head -N special cases, etc.
1e. Update rewrite_segment()
New structure: env_prefix strip → head check → RTK_DISABLED check → pnpm filter strip → rewrite_core() → re-add env_prefix
if let Some((workspace, inner_cmd)) = strip_pnpm_workspace_flag(cmd_clean) {
if let Some(rewritten) = rewrite_core(inner_cmd, excluded) {
return Some(format!("{}{}", env_prefix, inject_pnpm_filter(&rewritten, workspace)));
}
let pnpm_cmd = format!("pnpm {}", inner_cmd);
if let Some(rewritten) = rewrite_core(&pnpm_cmd, excluded) {
return Some(format!("{}{}", env_prefix, inject_pnpm_filter(&rewritten, workspace)));
}
return None;
}
1f. Update classify_command() for rtk discover
After env prefix strip, before RegexSet check:
if let Some((_workspace, inner_cmd)) = strip_pnpm_workspace_flag(cmd_clean) {
let inner_class = classify_command(inner_cmd);
if matches!(inner_class, Classification::Supported { .. }) {
return inner_class;
}
let pnpm_cmd = format!("pnpm {}", inner_cmd);
return classify_command(&pnpm_cmd);
}
Recursion is safe: inner_cmd won't start with pnpm --filter.
Tests to add
rewrite_command("pnpm --filter web prettier --check .", &[]) → "rtk prettier --pnpm-filter web --check ."
rewrite_command("pnpm -F web tsc --noEmit", &[]) → "rtk tsc --pnpm-filter web --noEmit"
rewrite_command("pnpm --filter web vitest run", &[]) → "rtk vitest --pnpm-filter web run"
rewrite_command("pnpm --filter web list", &[]) → "rtk pnpm --pnpm-filter web list"
rewrite_command("pnpm --filter @scope/pkg lint", &[]) → "rtk lint --pnpm-filter @scope/pkg"
rewrite_command("sudo pnpm --filter web prettier", &[]) → "sudo rtk prettier --pnpm-filter web"
rewrite_command("pnpm list", &[]) → "rtk pnpm list" (unchanged)
rewrite_command("pnpm --filter web unknown-cmd", &[]) → None
classify_command("pnpm --filter web prettier") → Supported
classify_command("pnpm --filter web list") → Supported