rtk-ai/rtk · error
gt: no subcommand specified
Error message
gt: no subcommand specified
What it means
RTK's gt (Graphite) handler run_other requires at least one subcommand and bails on an empty args slice before doing anything. Known subcommands (create, branch) go through dedicated filtered paths; unknown ones are forwarded to git routing, but an empty invocation has no route at all.
Source
Thrown at src/cmds/git/gt_cmd.rs:127
pub fn run_sync(args: &[String], verbose: u8) -> Result<i32> {
run_gt_filtered(&["sync"], args, verbose, "gt_sync", filter_gt_sync)
}
pub fn run_restack(args: &[String], verbose: u8) -> Result<i32> {
run_gt_filtered(&["restack"], args, verbose, "gt_restack", filter_gt_restack)
}
pub fn run_create(args: &[String], verbose: u8) -> Result<i32> {
run_gt_filtered(&["create"], args, verbose, "gt_create", filter_gt_create)
}
pub fn run_branch(args: &[String], verbose: u8) -> Result<i32> {
run_gt_filtered(&["branch"], args, verbose, "gt_branch", filter_identity)
}
pub fn run_other(args: &[OsString], verbose: u8) -> Result<i32> {
if args.is_empty() {
anyhow::bail!("gt: no subcommand specified");
}
let subcommand = args[0].to_string_lossy();
let rest: Vec<String> = args[1..]
.iter()
.map(|a| a.to_string_lossy().into())
.collect();
// gt passes unknown subcommands to git, so "gt status" = "git status".
// Route known git commands to RTK's git filters for token savings.
match subcommand.as_ref() {
"status" => crate::git::run(crate::git::GitCommand::Status, &rest, None, verbose, &[]),
"diff" => crate::git::run(crate::git::GitCommand::Diff, &rest, None, verbose, &[]),
"show" => crate::git::run(crate::git::GitCommand::Show, &rest, None, verbose, &[]),
"add" => crate::git::run(crate::git::GitCommand::Add, &rest, None, verbose, &[]),
"push" => crate::git::run(crate::git::GitCommand::Push, &rest, None, verbose, &[]),
"pull" => crate::git::run(crate::git::GitCommand::Pull, &rest, None, verbose, &[]),
"fetch" => crate::git::run(crate::git::GitCommand::Fetch, &rest, None, verbose, &[]),View on GitHub (pinned to d977e1c316)
Solutions
- Pass a subcommand: `rtk gt create`, `rtk gt submit`, or a git-backed one like `rtk gt status` (routed to RTK's git filter)
- Use `rtk proxy gt` for gt's own bare-CLI behavior
- Check for non-empty args in wrapper scripts before calling rtk
Example fix
# before
rtk gt # bail!("gt: no subcommand specified")
# after
rtk gt create --merge
# unknown subcommands are forwarded to git, so this also works:
rtk gt status # == git status, token-optimized Defensive patterns
Strategy: validation
Validate before calling
bash: if [ $# -eq 0 ]; then echo "usage: rtk gt <subcommand> [args...]" >&2 exit 2 fi rtk gt "$@"
Type guard
rust:
fn has_gt_subcommand(args: &[std::ffi::OsString]) -> bool {
!args.is_empty()
} Try / catch
rust:
if let Err(e) = gt_cmd::run_other(&args, verbose) {
if e.to_string().contains("gt: no subcommand specified") {
eprintln!("usage: rtk gt <subcommand> (create, submit, or any git command)");
std::process::exit(2);
}
return Err(e);
} Prevention
- Pass a concrete gt verb (create, submit, sync) or a git-routable one (status, log)
- Check forwarded variables are non-empty before `rtk gt $VAR`
- Use `rtk proxy gt` for bare gt behavior
When it happens
Trigger: Running `rtk gt` with zero arguments (src/cmds/git/gt_cmd.rs:128 `args.is_empty()`). Also `rtk gt "$GT_CMD"` where GT_CMD is unset, or a wrapper function invoked without positionals.
Common situations: Shell wrappers that conditionally build the gt command and forward it unquoted; agents calling `rtk gt` bare expecting a help screen; scripts copied from a context where the subcommand variable was populated.
Related errors
- dotnet: no subcommand specified
- go: no subcommand specified
- sbt: no subcommand specified
- --codex cannot be combined with --opencode
- --codex cannot be combined with --claude-md
AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16).
Data as JSON: /api/errors/445ad27b000f25d2.
Report an issue: GitHub.