Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:24:50 +08:00
commit 532dda1435
18 changed files with 2564 additions and 0 deletions

82
commands/cleanup.md Normal file
View File

@@ -0,0 +1,82 @@
---
allowed-tools: Bash(jj workspace:*), Bash(jj log:*)
description: Remove empty or stale jj workspaces
model: claude-haiku-4-5
---
## Context
- Available workspaces: !`jj workspace list`
- Current workspace: !`jj workspace list | grep '*'`
## Your Task
Clean up empty or stale jj workspaces.
**What are jj workspaces?**
Jujutsu workspaces allow you to have multiple working copies of your repository simultaneously. Each workspace can work on different revisions independently.
**When to use cleanup:**
- After finishing work in a temporary workspace
- When you have orphaned workspaces from interrupted work
- To reclaim disk space from unused workspaces
- Regular maintenance to keep workspace list clean
**Steps:**
1. **List all workspaces:**
```bash
jj workspace list
```
2. **Check each workspace status:**
For each workspace (except the current one), check if it's empty or stale:
```bash
jj log -r <workspace-name>@ --no-graph -T 'if(empty, "empty", "has_changes")'
```
3. **Remove empty/stale workspaces:**
```bash
jj workspace forget <workspace-name>
```
**Safety notes:**
- Never remove the current workspace (marked with `*`)
- `jj workspace forget` doesn't delete files, it just removes the workspace tracking
- You can always recreate a workspace if needed
- This is a maintenance operation, not a destructive one
**Example workflow:**
```bash
# List workspaces
jj workspace list
# Output:
# default: sqxoqmn 7a9a3c5 (empty) (no description set)
# * feature-work: rlzxqmpv 0c4a1b2 Add login feature
# old-bugfix: xyz123ab (empty) (no description set)
# Remove empty workspaces
jj workspace forget default
jj workspace forget old-bugfix
# Verify
jj workspace list
# Output:
# * feature-work: rlzxqmpv 0c4a1b2 Add login feature
```
**What if I don't have multiple workspaces?**
If you only have one workspace (the default), this command won't do anything. Workspaces are optional - they're useful for:
- Working on multiple features simultaneously
- Code review without switching commits
- Parallel development on different branches
Show final state: !`jj workspace list`

77
commands/commit.md Normal file
View File

@@ -0,0 +1,77 @@
---
allowed-tools: Bash(jj log:*), Bash(jj diff:*), Bash(jj commit:*), Bash(jj describe:*), Bash(jj new:*), Bash(jj status:*), Bash(jj file track:*)
argument-hint: [message]
description: Stack a commit with intelligent message generation
model: claude-haiku-4-5
---
!# Determine workflow state
# Check if current commit has a description
has_description=$(jj log -r @ --no-graph -T 'if(description, "has", "none")')
# Check if current commit is empty
is_empty=$(jj log -r @ --no-graph -T 'if(empty, "empty", "has_changes")')
!# Handle workflow logic
if [ "$is_empty" = "empty" ] && [ "$has_description" = "none" ]; then
# Empty commit with no description - need changes first
echo " **Current commit is empty with no description**"
echo ""
jj log -r @ -T 'concat("Current: ", change_id.short(), " (empty)")' --no-graph
echo ""
echo "💡 **Tip:** Make some changes first, then use \`/jj:commit\` to describe and stack"
exit 0
fi
!# Track any untracked files before committing
jj file track . 2>/dev/null || true
!# Determine action based on user argument
if [ -n "$ARGUMENTS" ]; then
# User provided explicit message - use it directly
if [ "$has_description" = "has" ]; then # Current commit already described, create new on top
echo "📦 **Creating new commit:** $ARGUMENTS"
echo ""
jj new -m "$ARGUMENTS" 2>/dev/null || true
echo "✅ **New commit created, ready for changes**"
else # Describe current commit using jj commit (describes @ and creates new working copy)
echo "📝 **Committing changes:** $ARGUMENTS"
echo ""
jj commit -m "$ARGUMENTS" 2>/dev/null || { # Fallback to describe if no changes
jj describe -m "$ARGUMENTS"
echo "💡 **Tip:** No changes to commit, description updated"
}
echo "✅ **Committed and created new working copy**"
fi
exit 0
fi
## Context
- Status: !`jj status`
- Changes: !`jj diff -r @`
## Task
Create commit for changes above. New files already tracked.
**Workflow:**
- Has "plan:" description → Update with actual work: `jj commit -m "message"`
- Has other description → Stack new commit: `jj new -m "message"`
- Needs description → Commit changes: `jj commit -m "message"`
Use conventional commit (feat/fix/refactor/docs/test/chore), under 72 chars, `-m` flag.
Note: `jj commit` describes @ and creates new working copy in one command.
Result: !`jj log -r @ -T 'concat(change_id.short(), ": ", description)' --no-graph`

90
commands/split.md Normal file
View File

@@ -0,0 +1,90 @@
---
allowed-tools: Bash(jj log:*), Bash(jj diff:*), Bash(jj status:*), Bash(jj new:*), Bash(jj move:*), Bash(jj describe:*), Bash(~/bin/jj-ai-desc.py:*)
argument-hint: <pattern>
description: Split unwanted changes into new child commit with AI description
model: claude-haiku-4-5
---
!# Validate pattern argument
if [ -z "$ARGUMENTS" ]; then
echo "❌ **Error: Pattern required**"
echo ""
echo "**Usage:** \`/jj:split <pattern>\`"
echo ""
echo "**Common patterns:**"
echo "- \`test\` - Test and spec files"
echo "- \`docs\` - Documentation (*.md, README, CHANGELOG)"
echo "- \`config\` - Config files (*.json, *.yaml, *.toml)"
echo "- Custom glob patterns (e.g., \`*.md\`, \`src/**/*.test.ts\`)"
echo ""
echo "**What it does:**"
echo "1. Keeps wanted changes in current commit (@)"
echo "2. Moves unwanted (matching pattern) changes to new child commit"
echo "3. Auto-generates description for child commit"
echo ""
echo "**Example:** \`/jj:split test\` - splits test files into new child commit"
exit 0
fi
## Context
- Current status: !`jj status`
- Current commit: !`jj log -r @ --no-graph -T 'concat(change_id.short(), ": ", description)'`
- Changed files: !`jj diff -r @ --summary`
## Your Task
Split unwanted changes matching pattern "$ARGUMENTS" from current commit (@) into a new child commit with an AI-generated description.
**Pattern Expansion:**
- `test` → Match test files: `*test*.{py,js,ts,jsx,tsx,java,go,rs,cpp,c,h}`, `*spec*.{py,js,ts,jsx,tsx}`, `test_*.py`, `*_test.go`, `*Test.java`
- `docs` → Match documentation: `*.md`, `README*`, `CHANGELOG*`, `LICENSE*`, `docs/**/*`
- `config` → Match config files: `*.json`, `*.yaml`, `*.yml`, `*.toml`, `*.ini`, `*.conf`, `.*.rc`, `.*ignore`
- Custom patterns → Use as-is (glob syntax)
**Workflow:**
1. **Identify matching files** - Show which files in current commit match the pattern
2. **Create child commit** - `jj new @` to create empty child where split changes will go
3. **Move matching changes** - `jj move --from @- -p 'glob:pattern'` to move unwanted files from parent to child
4. **Generate description** - Use `~/bin/jj-ai-desc.py @` to analyze split changes and generate commit message
5. **Show result** - Display final commit structure
**Result structure:**
```
@ (new child): unwanted changes with AI description
@- (original): wanted changes, original description preserved
```
**Important notes:**
- Use multiple `-p` flags for multiple patterns: `jj move --from @- -p 'glob:*.md' -p 'glob:README*'`
- Always quote glob patterns: `'glob:pattern'`
- The original commit description stays intact, only the unwanted changes move
- If no files match, inform user and suggest alternatives
- After moving, the AI will analyze what was split and generate an appropriate description
**Example execution:**
```bash
# Split test files
jj new @
jj move --from @- -p 'glob:**/*test*.py' -p 'glob:**/*_test.py'
~/bin/jj-ai-desc.py @
# Split documentation
jj new @
jj move --from @- -p 'glob:*.md' -p 'glob:README*' -p 'glob:docs/**'
~/bin/jj-ai-desc.py @
# Split config files
jj new @
jj move --from @- -p 'glob:*.json' -p 'glob:*.yaml' -p 'glob:*.toml'
~/bin/jj-ai-desc.py @
```
**Final verification:**
Show the result: !`jj log -r '@|@-' -T 'concat(change_id.short(), ": ", description)'`

78
commands/squash.md Normal file
View File

@@ -0,0 +1,78 @@
---
allowed-tools: Bash(jj log:*), Bash(jj diff:*), Bash(jj status:*), Bash(jj squash:*)
argument-hint: [revision]
description: Merge commits in the stack
model: claude-haiku-4-5
---
## Context
- Current status: !`jj status`
- Current commit: !`jj log -r @ --no-graph -T 'concat(change_id.short(), ": ", description)'`
- Parent commit: !`jj log -r @- --no-graph -T 'concat(change_id.short(), ": ", description)'`
- Recent stack: !`jj log -r 'ancestors(@, 5)' -T 'concat(change_id.short(), ": ", description)' --no-graph`
## Your Task
Merge commits in the jujutsu stack.
**Usage Modes:**
1. **Default (no argument):** Merge current commit (@) into its parent (@-)
```bash
jj squash
```
This moves all changes from @ into @-, then abandons @.
2. **With revision:** Merge a specific revision into its parent
```bash
jj squash -r <revision>
```
Useful for cleaning up a specific commit in the stack.
**When to use:**
- Multiple WIP commits for the same feature
- Cleaning up incremental work before sharing
- Combining related changes into a single commit
- Fixing typos or small changes that belong in the parent
**Workflow:**
1. Explain what will be merged (which commits, what changes)
2. Execute the squash operation
3. Show the result with `jj log` and confirm the changes
**Important:**
- Squashing is safe - you can undo with `jj undo`
- Use `jj squash -i` for interactive mode to select specific changes
- Consider if you should update the description after squashing
**Example scenarios:**
**Scenario 1: Merge current WIP into parent**
```bash
# Before: @ = "WIP: fix tests", @- = "Add login feature"
jj squash
# After: @ = "Add login feature" (now includes test fixes)
```
**Scenario 2: Merge specific revision**
```bash
# Merge revision abc123 into its parent
jj squash -r abc123
```
**Scenario 3: Interactive squash**
```bash
# Choose which changes to move
jj squash -i
```
Show result: !`jj log -r 'ancestors(@, 3)' -T 'concat(change_id.short(), ": ", description)' --no-graph`