-
Notifications
You must be signed in to change notification settings - Fork 2.5k
feat: npm/npx routing, pnpm build/typecheck, --skip-env flag #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9dbc117
bfd5646
bc31da8
517a93d
49b3cf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,4 @@ | ||||||||||||||||||||||||||||||||
| mod cargo_cmd; | ||||||||||||||||||||||||||||||||
| mod cc_economics; | ||||||||||||||||||||||||||||||||
| mod ccusage; | ||||||||||||||||||||||||||||||||
| mod config; | ||||||||||||||||||||||||||||||||
|
|
@@ -19,6 +20,7 @@ mod local_llm; | |||||||||||||||||||||||||||||||
| mod log_cmd; | ||||||||||||||||||||||||||||||||
| mod ls; | ||||||||||||||||||||||||||||||||
| mod next_cmd; | ||||||||||||||||||||||||||||||||
| mod npm_cmd; | ||||||||||||||||||||||||||||||||
| mod playwright_cmd; | ||||||||||||||||||||||||||||||||
| mod pnpm_cmd; | ||||||||||||||||||||||||||||||||
| mod prettier_cmd; | ||||||||||||||||||||||||||||||||
|
|
@@ -32,7 +34,7 @@ mod utils; | |||||||||||||||||||||||||||||||
| mod vitest_cmd; | ||||||||||||||||||||||||||||||||
| mod wget_cmd; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| use anyhow::Result; | ||||||||||||||||||||||||||||||||
| use anyhow::{Context, Result}; | ||||||||||||||||||||||||||||||||
| use clap::{Parser, Subcommand}; | ||||||||||||||||||||||||||||||||
| use std::path::PathBuf; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -54,6 +56,10 @@ struct Cli { | |||||||||||||||||||||||||||||||
| /// Ultra-compact mode: ASCII icons, inline format (Level 2 optimizations) | ||||||||||||||||||||||||||||||||
| #[arg(short = 'u', long, global = true)] | ||||||||||||||||||||||||||||||||
| ultra_compact: bool, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /// Set SKIP_ENV_VALIDATION=1 for child processes (Next.js, tsc, lint, prisma) | ||||||||||||||||||||||||||||||||
| #[arg(long = "skip-env", global = true)] | ||||||||||||||||||||||||||||||||
| skip_env: bool, | ||||||||||||||||||||||||||||||||
|
Comment on lines
+60
to
+62
|
||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #[derive(Subcommand)] | ||||||||||||||||||||||||||||||||
|
|
@@ -357,6 +363,26 @@ enum Commands { | |||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /// Cargo commands with compact output | ||||||||||||||||||||||||||||||||
| Cargo { | ||||||||||||||||||||||||||||||||
| #[command(subcommand)] | ||||||||||||||||||||||||||||||||
| command: CargoCommands, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
Comment on lines
+367
to
+371
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /// npm run with filtered output (strip boilerplate) | ||||||||||||||||||||||||||||||||
| Npm { | ||||||||||||||||||||||||||||||||
| /// npm run arguments (script name + options) | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /// npx with intelligent routing (tsc, eslint, prisma -> specialized filters) | ||||||||||||||||||||||||||||||||
| Npx { | ||||||||||||||||||||||||||||||||
| /// npx arguments (command + options) | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #[derive(Subcommand)] | ||||||||||||||||||||||||||||||||
|
|
@@ -391,6 +417,32 @@ enum GitCommands { | |||||||||||||||||||||||||||||||
| Push, | ||||||||||||||||||||||||||||||||
| /// Pull → "ok ✓ <stats>" | ||||||||||||||||||||||||||||||||
| Pull, | ||||||||||||||||||||||||||||||||
| /// Compact branch listing (current/local/remote) | ||||||||||||||||||||||||||||||||
| Branch { | ||||||||||||||||||||||||||||||||
| /// Git branch arguments (supports -d, -D, -m, etc.) | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Fetch → "ok fetched (N new refs)" | ||||||||||||||||||||||||||||||||
| Fetch { | ||||||||||||||||||||||||||||||||
| /// Git fetch arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Stash management (list, show, pop, apply, drop) | ||||||||||||||||||||||||||||||||
| Stash { | ||||||||||||||||||||||||||||||||
| /// Subcommand: list, show, pop, apply, drop, push | ||||||||||||||||||||||||||||||||
| subcommand: Option<String>, | ||||||||||||||||||||||||||||||||
| /// Additional arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Compact worktree listing | ||||||||||||||||||||||||||||||||
| Worktree { | ||||||||||||||||||||||||||||||||
| /// Git worktree arguments (add, remove, prune, or empty for list) | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #[derive(Subcommand)] | ||||||||||||||||||||||||||||||||
|
|
@@ -418,6 +470,18 @@ enum PnpmCommands { | |||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Build (delegates to next build filter) | ||||||||||||||||||||||||||||||||
| Build { | ||||||||||||||||||||||||||||||||
| /// Additional build arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Typecheck (delegates to tsc filter) | ||||||||||||||||||||||||||||||||
| Typecheck { | ||||||||||||||||||||||||||||||||
| /// Additional typecheck arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #[derive(Subcommand)] | ||||||||||||||||||||||||||||||||
|
|
@@ -512,6 +576,28 @@ enum PrismaMigrateCommands { | |||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #[derive(Subcommand)] | ||||||||||||||||||||||||||||||||
| enum CargoCommands { | ||||||||||||||||||||||||||||||||
| /// Build with compact output (strip Compiling lines, keep errors) | ||||||||||||||||||||||||||||||||
| Build { | ||||||||||||||||||||||||||||||||
| /// Additional cargo build arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Test with failures-only output | ||||||||||||||||||||||||||||||||
| Test { | ||||||||||||||||||||||||||||||||
| /// Additional cargo test arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| /// Clippy with warnings grouped by lint rule | ||||||||||||||||||||||||||||||||
| Clippy { | ||||||||||||||||||||||||||||||||
| /// Additional cargo clippy arguments | ||||||||||||||||||||||||||||||||
| #[arg(trailing_var_arg = true, allow_hyphen_values = true)] | ||||||||||||||||||||||||||||||||
| args: Vec<String>, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| fn main() -> Result<()> { | ||||||||||||||||||||||||||||||||
| let cli = Cli::parse(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -564,6 +650,23 @@ fn main() -> Result<()> { | |||||||||||||||||||||||||||||||
| GitCommands::Pull => { | ||||||||||||||||||||||||||||||||
| git::run(git::GitCommand::Pull, &[], None, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| GitCommands::Branch { args } => { | ||||||||||||||||||||||||||||||||
| git::run(git::GitCommand::Branch, &args, None, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| GitCommands::Fetch { args } => { | ||||||||||||||||||||||||||||||||
| git::run(git::GitCommand::Fetch, &args, None, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| GitCommands::Stash { subcommand, args } => { | ||||||||||||||||||||||||||||||||
| git::run( | ||||||||||||||||||||||||||||||||
| git::GitCommand::Stash { subcommand }, | ||||||||||||||||||||||||||||||||
| &args, | ||||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||||
| cli.verbose, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| GitCommands::Worktree { args } => { | ||||||||||||||||||||||||||||||||
| git::run(git::GitCommand::Worktree, &args, None, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Commands::Gh { subcommand, args } => { | ||||||||||||||||||||||||||||||||
|
|
@@ -584,6 +687,12 @@ fn main() -> Result<()> { | |||||||||||||||||||||||||||||||
| cli.verbose, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| PnpmCommands::Build { args } => { | ||||||||||||||||||||||||||||||||
| next_cmd::run(&args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| PnpmCommands::Typecheck { args } => { | ||||||||||||||||||||||||||||||||
| tsc_cmd::run(&args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Commands::Err { command } => { | ||||||||||||||||||||||||||||||||
|
|
@@ -823,6 +932,88 @@ fn main() -> Result<()> { | |||||||||||||||||||||||||||||||
| Commands::Playwright { args } => { | ||||||||||||||||||||||||||||||||
| playwright_cmd::run(&args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Commands::Cargo { command } => match command { | ||||||||||||||||||||||||||||||||
| CargoCommands::Build { args } => { | ||||||||||||||||||||||||||||||||
| cargo_cmd::run(cargo_cmd::CargoCommand::Build, &args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| CargoCommands::Test { args } => { | ||||||||||||||||||||||||||||||||
| cargo_cmd::run(cargo_cmd::CargoCommand::Test, &args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| CargoCommands::Clippy { args } => { | ||||||||||||||||||||||||||||||||
| cargo_cmd::run(cargo_cmd::CargoCommand::Clippy, &args, cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Commands::Npm { args } => { | ||||||||||||||||||||||||||||||||
| npm_cmd::run(&args, cli.verbose, cli.skip_env)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Commands::Npx { args } => { | ||||||||||||||||||||||||||||||||
| if args.is_empty() { | ||||||||||||||||||||||||||||||||
| anyhow::bail!("npx requires a command argument"); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Intelligent routing: delegate to specialized filters | ||||||||||||||||||||||||||||||||
| match args[0].as_str() { | ||||||||||||||||||||||||||||||||
| "tsc" | "typescript" => { | ||||||||||||||||||||||||||||||||
| tsc_cmd::run(&args[1..], cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| "eslint" => { | ||||||||||||||||||||||||||||||||
| lint_cmd::run(&args[1..], cli.verbose)?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| "prisma" => { | ||||||||||||||||||||||||||||||||
| // Route to prisma_cmd based on subcommand | ||||||||||||||||||||||||||||||||
| if args.len() > 1 { | ||||||||||||||||||||||||||||||||
| let prisma_args: Vec<String> = args[2..].to_vec(); | ||||||||||||||||||||||||||||||||
| match args[1].as_str() { | ||||||||||||||||||||||||||||||||
| "generate" => { | ||||||||||||||||||||||||||||||||
| prisma_cmd::run( | ||||||||||||||||||||||||||||||||
| prisma_cmd::PrismaCommand::Generate, | ||||||||||||||||||||||||||||||||
| &prisma_args, | ||||||||||||||||||||||||||||||||
| cli.verbose, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| "db" if args.len() > 2 && args[2] == "push" => { | ||||||||||||||||||||||||||||||||
| prisma_cmd::run( | ||||||||||||||||||||||||||||||||
| prisma_cmd::PrismaCommand::DbPush, | ||||||||||||||||||||||||||||||||
| &args[3..], | ||||||||||||||||||||||||||||||||
| cli.verbose, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||||||||
| // Passthrough other prisma subcommands | ||||||||||||||||||||||||||||||||
| let mut cmd = std::process::Command::new("npx"); | ||||||||||||||||||||||||||||||||
| for arg in &args { | ||||||||||||||||||||||||||||||||
| cmd.arg(arg); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| let status = cmd.status().context("Failed to run npx prisma")?; | ||||||||||||||||||||||||||||||||
| std::process::exit(status.code().unwrap_or(1)); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| let status = std::process::Command::new("npx") | ||||||||||||||||||||||||||||||||
| .arg("prisma") | ||||||||||||||||||||||||||||||||
| .status() | ||||||||||||||||||||||||||||||||
| .context("Failed to run npx prisma")?; | ||||||||||||||||||||||||||||||||
| std::process::exit(status.code().unwrap_or(1)); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| "next" => { | ||||||||||||||||||||||||||||||||
| next_cmd::run(&args[1..], cli.verbose)?; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
| next_cmd::run(&args[1..], cli.verbose)?; | |
| // Route `next` intelligently: | |
| // - If no subcommand: let `next_cmd` decide (typically `build`) | |
| // - If subcommand is `build`: strip it so `next_cmd` does not inject `build` twice | |
| // - Otherwise: passthrough to npm_cmd for other `next` subcommands (e.g. `dev`, `lint`) | |
| if args.len() == 1 { | |
| // `rtk npx next` -> next_cmd default behavior (usually `next build`) | |
| next_cmd::run(&[], cli.verbose)?; | |
| } else if args[1] == "build" { | |
| // `rtk npx next build ...` -> avoid `next build build ...` | |
| next_cmd::run(&args[2..], cli.verbose)?; | |
| } else { | |
| // Passthrough other `next` subcommands unchanged | |
| npm_cmd::run(&args, cli.verbose, cli.skip_env)?; | |
| } |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rtk npx fallback currently calls npm_cmd::run, which executes npm run ... rather than npx .... This will run the wrong tool for any non-script npx usage. Consider introducing a real npx runner (Command::new("npx") with the provided args) and apply the npm-style filtering to its output, or rename this command to reflect that it’s actually npm run.
| // Generic passthrough with npm boilerplate filter | |
| npm_cmd::run(&args, cli.verbose, cli.skip_env)?; | |
| // Generic passthrough: invoke npx directly | |
| let mut cmd = std::process::Command::new("npx"); | |
| for arg in &args { | |
| cmd.arg(arg); | |
| } | |
| let status = cmd.status().context("Failed to run npx command")?; | |
| std::process::exit(status.code().unwrap_or(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filter_json_stringnow returns a generic parse error context ("Failed to parse JSON"). Whenrtk json <file>fails, the error no longer includes the filename (previously it did), which makes debugging harder. Consider adding file context at the call site (e.g.,with_context(|| format!("Failed to parse JSON: {}", file.display()))) or accepting an optional label/path for richer context.