Created
January 7, 2026 23:16
-
-
Save ernesto-jimenez/8ffe1b36f753c7930d70ffdfeded101f to your computer and use it in GitHub Desktop.
Small utilities to work with jj and Claude Code. See: https://bsky.app/profile/ernesto-jimenez.com/post/3m44izya6ac2n
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "$schema" = "https://jj-vcs.github.io/jj/latest/config-schema.json" | |
| [aliases] | |
| clstart = ["util", "exec", "--", "bash", "-c", """ | |
| set -euo pipefail | |
| # Require exactly one argument | |
| if [ "$#" -ne 1 ]; then | |
| echo "Error: You must name the workspace." | |
| exit 1 | |
| fi | |
| workspace="${1//[^a-zA-Z0-9]/-}" | |
| source="$(jj workspace root | sed -e 's/-workspaces\\/.*//')" | |
| mkdir -p "$source-workspaces" | |
| target="$source-workspaces/$workspace" | |
| # If workspace doesn't exist, create it | |
| if [ ! -d "$target" ]; then | |
| echo "Creating workspace '$target'" | |
| jj workspace add "$target" | |
| fi | |
| session=$(basename $target) | |
| # If tmux session doesn't exist, create it | |
| if ! tmux has-session -t "$session" 2>/dev/null; then | |
| # Create a new detached session | |
| echo "Creating tmux session '$session'" | |
| tmux new-session -c "$target" -d -s "$session" | |
| echo "Session '$session' created." | |
| # If .jj-workspace-setup.sh exists in $source, run it | |
| if [ -f "$source/.jj-workspace-setup.sh" ]; then | |
| echo "Configuring session." | |
| $source/.jj-workspace-setup.sh "$target" | |
| fi | |
| else | |
| echo "Session '$session' already exists." | |
| fi | |
| if [ -z "$TMUX" ]; then | |
| tmux attach -t "=$session" | |
| else | |
| tmux switch-client -t "=$session" | |
| fi | |
| """, ""] | |
| clstop = ["util", "exec", "--", "bash", "-c", """ | |
| set -euo pipefail | |
| # Require exactly one argument | |
| if [ "$#" -ne 1 ]; then | |
| echo "Error: You must name the workspace." | |
| exit 1 | |
| fi | |
| workspace="${1//[^a-zA-Z0-9]/-}" | |
| source="$(jj workspace root | sed -e 's/-workspaces\\/.*//')" | |
| target="$workspace" | |
| name=$(basename "$target") | |
| jj workspace forget "$name" || true | |
| rm -rf "$source-workspaces/$target" | |
| if tmux has-session -t "$name" 2>/dev/null; then | |
| tmux kill-session -t "$name" | |
| echo "Session '$name' stopped." | |
| else | |
| echo "Session '$name' does not exist." | |
| fi | |
| """, ""] | |
| clresolve = [ | |
| "util", | |
| "exec", | |
| "--", | |
| "bash", | |
| "-c", | |
| """ | |
| set -euo pipefail | |
| revision=${1:-@-} | |
| if [ "$#" -eq 1 ]; then | |
| jj new $revision | |
| fi | |
| echo "Resolving conflicts in $revision" | |
| claude --permission-mode=plan "resolve conflicts in $(jj resolve -r @- --list | awk '{print "@"$1}' | paste -sd' ' -). You can look for recent changes to the conflicted files with 'jj log -r \\"latest(..@ & files({file}))\\" -s' and check the actual changes with 'jj show {change_id}'" | |
| """, | |
| "", | |
| ] | |
| claude-checkpoint = ["util", "exec", "--", "bash", "-c", """ | |
| set -euo pipefail | |
| is_empty=$(jj show @ -T 'self.empty()' --no-pager) | |
| if [ "$is_empty" = "true" ]; then | |
| echo "No changes to checkpoint." | |
| exit 0 | |
| fi | |
| jj new | |
| author="$1" | |
| # if author is set, describe the previous commit with the author | |
| if [ -n "$author" ]; then | |
| jj describe -r @- -m "$author" | |
| fi | |
| """, ""] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "$schema": "https://json.schemastore.org/claude-code-settings.json", | |
| "hooks": { | |
| "PreToolUse": [ | |
| { | |
| "matcher": "Task", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "jj claude-checkpoint || true" | |
| } | |
| ] | |
| } | |
| ], | |
| "PostToolUse": [ | |
| { | |
| "matcher": "Task", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "jj claude-checkpoint 'claude@tessl.io' >> /tmp/claude-checkpoint.log 2>&1 || true" | |
| } | |
| ] | |
| } | |
| ], | |
| "Stop": [ | |
| { | |
| "matcher": "", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "jj claude-checkpoint 'Claude <claude@tessl.io>' >> /tmp/claude-checkpoint.log 2>&1 || true" | |
| } | |
| ] | |
| } | |
| ], | |
| "Notification": [ | |
| { | |
| "matcher": "", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "jq -r .message | say" | |
| } | |
| ] | |
| }, | |
| { | |
| "matcher": "", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "jq -r .message | terminal-notifier -title 'Claude Code needs you' -sender com.anthropic.claudefordesktop" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment