Write your first `/gtw` config
One minute of YAML and every `/gtw` subcommand runs the hooks you want — without blocking the main flow if a hook fails.
One minute of YAML and every
/gtwsubcommand runs the hooks you want — without blocking the main flow if a hook fails.
/gtw is a family of subcommands (fix, commit, push, pr, close, sync, back) that wrap the "open a worktree, run an agent, ship a PR" loop into IM-friendly cards. Each subcommand reads its defaults from ~/.nightme/gtw.yml before doing the work — that's where you pin the agent for /gtw pr and the shell commands that should run before/after each step.
The file is optional. A missing or unreadable yml is a silent no-op; a YAML syntax error surfaces as a warning in the command reply, never a hard failure ("hooks are additive, never block main flow").
Minimal example
# ~/.nightme/gtw.yml
fix:
hooks:
after:
- codegraph init # bare-string form: runs `codegraph init` in the worktree
commit:
agent: pi # default agent for /gtw commit when no -a flag
push:
hooks:
after:
- type: shell # explicit mapping form: same effect as the bare-string
run: make lint
That gives you:
/gtw fix <id>— after cutting the worktree, runscodegraph initfrom the worktree directory. Failures are non-fatal; the worktree is still handed to the agent./gtw commit— pickspias the agent (unless you pass-a <other>on the command line)./gtw push— runsmake lintfrom the worktree before pushing.
Schema
The top level is a fixed set of per-command subsections. Each one is independently optional — a partial yml is fine.
fix: CmdConfig # /gtw fix
commit: CmdConfig # /gtw commit
push: CmdConfig # /gtw push
pr: CmdConfig # /gtw pr
close: CmdConfig # /gtw close
sync: CmdConfig # /gtw sync
back: CmdConfig # /gtw back
CmdConfig:
agent: string # optional, default ""
hooks:
before: []Hook # optional, default []
after: []Hook # optional, default []
Hook:
- <bare string> # sugar for: { type: shell, run: <string> }
- { type: shell, run: <string> }
agent controls the default agent for subcommands that invoke one (commit, pr — and fix if you want to pin one per project). See Agent priority below for the resolution order.
hooks.before runs before the subcommand's main work; hooks.after runs after. Hooks execute sequentially in declaration order, with the chat's current working directory as their cwd. Each hook has a 30-minute timeout; a hook that exits non-zero (or times out, or fails to spawn) is logged as a warning and the next hook still runs.
Only type: shell (or the bare-string sugar) is honoured. Unknown hook types are warn-skipped.
Agent priority
When a /gtw subcommand needs to pick an agent — /gtw fix, /gtw commit, and /gtw pr invoke one — it walks three sources in order:
- The
-a/--agentflag on the command line. <cmd>.agentfrom~/.nightme/gtw.yml.- The chat's currently-selected agent (
/use claude).
The first non-empty wins. If the yml names an agent that isn't registered, a warning is emitted and the chat's selected agent is used as the fallback. Leave agent: "" (or omit it entirely) to defer to the chat's /use selection.
Hook environment
Every hook subprocess inherits os.Environ() and gets four GTW_* variables appended on top. PATH / HOME / LANG are not overridden — only added to.
| Variable | Meaning | Source |
|---|---|---|
GTW_REPO_ROOT |
Absolute path of the main repo | yml + git rev-parse --show-toplevel fallback |
GTW_WORKTREE |
Absolute path of the active worktree (or GTW_REPO_ROOT for sync) |
same |
GTW_BRANCH |
Current branch in the worktree ("" if detached) |
git rev-parse --abbrev-ref HEAD |
GTW_DEFAULT_BRANCH |
Upstream default branch name ("" if not discoverable) |
git symbolic-ref refs/remotes/origin/HEAD |
Empty fields are omitted from the env, not exported as empty strings. A hook can detect "not discoverable" without parsing blanks:
hooks:
before:
- "[[ -n \"$GTW_DEFAULT_BRANCH\" ]] && git fetch origin $GTW_DEFAULT_BRANCH"
A fuller example
# ~/.nightme/gtw.yml
fix:
agent: pi
hooks:
# before: []
after:
- codegraph init # prime the codegraph index for the new worktree
commit:
agent: pi
# hooks: {}
push:
agent: pi
# hooks: {}
pr:
agent: pi
# hooks: {}
sync:
agent: "" # empty → fall through to the chat's /use agent
# hooks: {}
Keep it short. The whole point is "every /gtw boots into a ready worktree without me thinking about it" — once you've hit that, more config is usually friction.
When to use config vs. just running setup yourself
Use gtw.yml when |
Do it by hand when |
|---|---|
| Every worktree needs the same setup. | The worktree needs context that only exists in this chat (e.g. an uncommitted secret). |
| The setup is something you can express as a one-liner. | The setup is genuinely one-off and not worth templating. |
| You want the agent to inherit the worktree ready-to-go. | You're experimenting and don't care about repeatability. |
Hooks that fail are surfaced in the command reply (⚠️ hook X exited N) but never abort /gtw — so a broken hook can sit in the yml while you fix it, instead of blocking the whole flow.
What's next
- Use
/gtwfor one-shot fixes — the workflow this config supports. - Install NightMe on macOS & Linux — back to basics if you skipped setup.