aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/dot_claude/skills/tuicr
diff options
context:
space:
mode:
Diffstat (limited to 'dot_claude/skills/tuicr')
-rw-r--r--dot_claude/skills/tuicr/SKILL.md110
-rwxr-xr-xdot_claude/skills/tuicr/executable_tuicr-wrapper.sh102
2 files changed, 212 insertions, 0 deletions
diff --git a/dot_claude/skills/tuicr/SKILL.md b/dot_claude/skills/tuicr/SKILL.md
new file mode 100644
index 0000000..2f8e728
--- /dev/null
+++ b/dot_claude/skills/tuicr/SKILL.md
@@ -0,0 +1,110 @@
+---
+name: tuicr
+description: Review local git changes with tuicr TUI via zellij floating pane
+---
+
+# tuicr - TUI Change Reviewer
+
+Launch the `tuicr` TUI tool in a zellij floating pane to interactively review
+local git changes.
+
+## Usage
+
+```
+/tuicr [directory]
+```
+
+Or simply mention wanting to review changes with tuicr.
+
+## How It Works
+
+Since coding agents cannot run interactive TUI applications directly, this
+skill uses a zellij workaround:
+
+1. Detects if the current agent session is running inside zellij (`$ZELLIJ`).
+2. If yes: opens tuicr in a floating pane, blocks until it exits, then reads
+ any exported instructions back from a temp file.
+3. If no: instructs the user to restart the agent inside zellij.
+
+## Determining the Directory
+
+**Important:** You must determine the correct git repository directory based on
+context.
+
+Consider:
+
+- The user's current working directory
+- Any repository they've been working in during the session
+- Explicit directory mentioned in their request
+- The git status output if available
+
+Common patterns:
+
+- "review my changes" → use current working directory
+- "review changes in myproject" → find that repo path
+- After editing files → use the directory of those files
+
+## Workflow
+
+1. **Determine target directory** (cwd, recent file ops, ask if ambiguous).
+
+2. **Run the wrapper** with a 10-minute timeout:
+
+ ```bash
+ <skill-directory>/tuicr-wrapper.sh [directory]
+ ```
+
+ **IMPORTANT:** Always set `timeout: 600000` (10 minutes) on the Bash tool
+ call. The script blocks on a FIFO until tuicr exits; without the extended
+ timeout the agent may background it after 2 minutes.
+
+3. **Handle the result**:
+ - Success → tuicr opened in a floating pane, user reviewed and exited.
+ - Not in zellij → relay the instructions to the user.
+ - Not a git repo → ask for the correct path.
+
+4. **Process instructions from tuicr output**:
+
+ ```
+ === TUICR INSTRUCTIONS ===
+ <instructions here>
+ === END TUICR INSTRUCTIONS ===
+ ```
+
+ If present, parse and execute them. If absent, ask the user to paste from
+ clipboard.
+
+## Configuration
+
+| Variable | Default | Description |
+| ----------------- | ---------- | ---------------------------------------------- |
+| `TUICR_PANE_MODE` | `floating` | `floating` (overlay) or `split` (horizontal) |
+| `TUICR_SPLIT_DIR` | `down` | When `split`: `down`, `up`, `right`, or `left` |
+
+Example:
+
+```bash
+TUICR_PANE_MODE=split TUICR_SPLIT_DIR=down \
+ <skill-directory>/tuicr-wrapper.sh /path/to/repo
+```
+
+## Zellij Tips (relay to user if needed)
+
+- Move focus between panes: `Alt-h/j/k/l`
+- Close the floating pane: press `q` inside tuicr (pane auto-closes)
+- Toggle floating pane visibility: `Ctrl-p` then `w`
+- Zoom current pane: `Ctrl-p` then `f`
+
+## Error Handling
+
+| Error | Action |
+| ------------------- | ---------------------------------------------------------------------------------------------------- |
+| Not in zellij | Tell the user to restart the agent inside zellij |
+| Not a git repo | Ask user for correct directory |
+| tuicr not installed | Tell user `tuicr` is provisioned via nix; run `home-manager switch` (VM) or `just nix-switch` (host) |
+
+## When NOT to use
+
+- User just wants `git diff` output (use git directly)
+- Reviewing remote/PR changes (use `gh` CLI or web)
+- User explicitly asks for non-interactive review
diff --git a/dot_claude/skills/tuicr/executable_tuicr-wrapper.sh b/dot_claude/skills/tuicr/executable_tuicr-wrapper.sh
new file mode 100755
index 0000000..d3457fa
--- /dev/null
+++ b/dot_claude/skills/tuicr/executable_tuicr-wrapper.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+# tuicr-wrapper: open tuicr in a zellij floating pane (or split) from a
+# non-TTY context (e.g. claude-code, copilot CLI). Blocks on a FIFO until
+# the spawned tuicr process exits, then emits any instructions written by
+# tuicr's --output to stdout, wrapped in markers the agent recognises.
+#
+# Adapted from agavra/tuicr's tmux-based reference wrapper.
+# See: dot_claude/skills/tuicr/SKILL.md
+set -euo pipefail
+
+TARGET_DIR="${1:-$PWD}"
+
+if [ -z "${ZELLIJ:-}" ]; then
+ cat <<'EOF' >&2
+ERROR: not running inside a zellij session.
+
+Restart the agent from inside a zellij session and try again:
+
+ zellij
+ # then, inside zellij:
+ claude # or: copilot
+EOF
+ exit 1
+fi
+
+if ! command -v tuicr >/dev/null 2>&1; then
+ cat <<'EOF' >&2
+ERROR: 'tuicr' is not installed.
+
+Provisioned via nix; rebuild your profile:
+
+ # host (Arch):
+ just nix-switch
+
+ # remote-dev VM:
+ cd ~/.local/share/dotfiles/remote-dev
+ home-manager switch --impure --flake .#vm -b backup
+EOF
+ exit 1
+fi
+
+if ! git -C "$TARGET_DIR" rev-parse --git-dir >/dev/null 2>&1; then
+ echo "ERROR: '$TARGET_DIR' is not a git repository" >&2
+ exit 1
+fi
+
+# Refuse to nest if another tuicr is already running (zellij has no
+# tmux-style 'list-panes | grep'; pgrep is the closest cross-pane probe).
+if pgrep -x tuicr >/dev/null 2>&1; then
+ echo "ERROR: tuicr is already running in this session" >&2
+ exit 1
+fi
+
+# Per-invocation tmpdir holds:
+# done - FIFO; child writes one byte on exit, parent blocks read
+# output - tuicr --output target (instructions to relay back)
+TMPDIR_TUICR="$(mktemp -d -t tuicr.XXXXXX)"
+DONE_FIFO="$TMPDIR_TUICR/done"
+OUTPUT_FILE="$TMPDIR_TUICR/output"
+trap 'rm -rf "$TMPDIR_TUICR"' EXIT
+mkfifo "$DONE_FIFO"
+: >"$OUTPUT_FILE"
+
+PANE_MODE="${TUICR_PANE_MODE:-floating}"
+SPLIT_DIR="${TUICR_SPLIT_DIR:-down}"
+
+# Child command: cd into the repo, run tuicr exporting instructions, then
+# signal the parent regardless of exit status.
+CHILD_CMD="cd $(printf %q "$TARGET_DIR") && \
+ tuicr --output $(printf %q "$OUTPUT_FILE"); \
+ printf done > $(printf %q "$DONE_FIFO")"
+
+case "$PANE_MODE" in
+ floating)
+ zellij action new-pane --floating \
+ --cwd "$TARGET_DIR" \
+ -- bash -lc "$CHILD_CMD" >/dev/null
+ ;;
+ split)
+ zellij action new-pane \
+ --direction "$SPLIT_DIR" \
+ --cwd "$TARGET_DIR" \
+ -- bash -lc "$CHILD_CMD" >/dev/null
+ ;;
+ *)
+ echo "ERROR: invalid TUICR_PANE_MODE='$PANE_MODE' (expected floating|split)" >&2
+ exit 1
+ ;;
+esac
+
+# Block until the child writes its sentinel.
+read -r _ <"$DONE_FIFO"
+
+# Relay instructions back to the agent if tuicr wrote any.
+if [ -s "$OUTPUT_FILE" ]; then
+ echo "=== TUICR INSTRUCTIONS ==="
+ cat "$OUTPUT_FILE"
+ echo
+ echo "=== END TUICR INSTRUCTIONS ==="
+else
+ echo "tuicr exited with no instructions" >&2
+fi