Subcommand Aliases
Many tools like jj, git, cargo, and kubectl organize their commands as subcommands. Subcommand aliases let you create short forms for those subcommands — without losing shell completions or wrapping behavior.
jj ab # → jj abandon
jj b l # → jj branch listamoxide generates a shell function per program that intercepts the subcommand and dispatches to the full form.
Adding Subcommand Aliases
Use --sub to pair each short token with its long expansion:
am add -g jj --sub ab abandon
# jj ab → jj abandon
am add -g jj --sub b branch --sub l list
# jj b l → jj branch listThe colon (:) notation is a shorthand for the same thing — the program and all short tokens joined by colons, followed by the expansion:
am add -g jj:ab abandon
am add -g jj:b:l branch listTIP
Even Shorter form: am a -g jj:ab abandon
The scope flags work exactly like regular aliases:
| Flag | Scope |
|---|---|
-g / --global | Global — always active |
-p <profile> | Profile — active when profile is enabled |
-l / --local | Project — loaded from .aliases |
Nested Subcommand Aliases
Add more colon-separated tokens for nested dispatch:
am add -g jj:b:l branch list
am add -g jj:b:c branch create
am add -g k kubectl
am add -g k:get:po get podsWhen you run jj b l, amoxide dispatches through jj → b → l and expands to jj branch list <other-args>.
When you run k get po, amoxide dispatches through k → get → po and knows k is a alias for kubectl, so it expands to kubectl get pods <other-args>.
Templates in Expansions
Expansions support the same templates as regular aliases:
am add -g jj:anon "log -r 'anon()'"
# jj anon → jj log -r 'anon()'
am add -g jj:e "edit {{1}}"
# jj e abc123 → jj edit abc123
am add -g cargo:t "test --test {{1}} -- {{@}}"
# cargo t integration foo bar → cargo test --test integration -- foo barSee Parameterized Aliases for the full template reference.
Removing Subcommand Aliases
Use the same colon notation with am remove:
am remove -g jj:ab
am remove -g jj:b:lShort form: am r -g jj:ab
How It Works
At shell init (and on every am sync triggered by cd or an am mutation), amoxide generates a wrapper function for each program that has subcommand aliases:
# generated for jj (bash/zsh)
jj() {
case "$1" in
ab) shift; command jj abandon "$@" ;;
b)
case "$2" in
l) shift 2; command jj branch list "$@" ;;
*) command jj "$@" ;;
esac
;;
*) command jj "$@" ;;
esac
}Any subcommand not matching a defined alias passes through to the real jj unchanged. Additional arguments are always forwarded after expansion.
The .aliases File
Project-local subcommand aliases use a [subcommands] section alongside [aliases]:
# .aliases
[aliases]
t = "cargo test"
[subcommands]
"jj:ab" = ["abandon"]
"jj:b:l" = ["branch", "list"]
"jj:anon" = ["log -r 'anon()'"]The key is the colon-joined path, and the value is an array of expansion tokens. The same file format applies in config.toml (global) and profiles.toml (per profile).
Trust Model
Project subcommand aliases are subject to the same trust model as regular project aliases. When you run am trust, amoxide shows both the regular aliases and the subcommand aliases before asking for confirmation — so you always see exactly what you're approving.
See Project Aliases — Trust Model for details.
Listing Subcommand Aliases
am ls displays subcommand aliases grouped by program in the tree view:
🌐 global
│ ├─ ll → ls -lha
│ ╰─◆ jj (subcommands)
│ ├─ ab → abandon
│ ╰─ b l → branch list
│
╰─📁 project (/path/to/project/.aliases)
├─ t → cargo test
╰─◆ cargo (subcommands)
╰─ test → test --test {{1}} -- {{@}}The TUI (am tui) lets you view and manage subcommand aliases interactively.