Commit 3cd7f8c

HPCesia <me@hpcesia.com>
2026-10-11 12:25:26
agents: update jujutsu skill to jj 0.46.0
Assisted-by: crush:deepseek-v4.1-flash
1 parent a26f5c4
Changed files (1)
modules
dev
agents
skills
jujutsu
modules/dev/agents/skills/jujutsu/SKILL.md
@@ -7,442 +7,446 @@ description: >
 allowed-tools: Bash(jj *)
 ---
 
-# Jujutsu (jj) Version Control System
+# Jujutsu (jj) version control system
 
-This skill helps you work with Jujutsu, a Git-compatible VCS with mutable
-commits and automatic rebasing.
+Jujutsu is a Git-compatible VCS with mutable commits and automatic rebasing.
 
-**Tested with jj v0.37.0** - Commands may differ in other versions.
+Tested with jj v0.46.0. Commands may differ in other versions.
 
-## Important: Automated/Agent Environment
+## Automated and agent environments
 
 When running as an agent:
 
-1. **Always use `--no-pager`** to prevent commands from opening an interactive
-  pager (like `less`), which will hang the agent:
+- Pass `--no-pager` to every command that produces output. A pager such as
+  `less` waits for a keypress and hangs the run. `JJ_PAGER` overrides `ui.pager`
+  when you need a jj-specific setting.
 
 ```bash
-# Always use --no-pager on commands that produce output
-jj --no-pager log          # NOT: jj log
-jj --no-pager diff         # NOT: jj diff
-jj --no-pager show <id>    # NOT: jj show <id>
+jj --no-pager log
+jj --no-pager diff
+jj --no-pager show <id>
 ```
 
-2. **Always use `-m` flags** to provide messages inline rather than relying on
-  editor prompts:
+- Pass messages inline with `-m`. Commands that open an editor fail without a
+  terminal.
 
 ```bash
-# Always use -m to avoid editor prompts
-jj desc -m "message"      # NOT: jj desc
-jj squash -m "message"    # NOT: jj squash (which opens editor)
+jj desc -m "message"
+jj squash -m "message"
 ```
 
-Editor-based commands will fail in non-interactive environments.
+- Confirm mutations with `jj st`. After `squash`, `abandon`, `rebase`, or
+  `restore`, check that the operation did what you expected.
+
+- Avoid the interactive commands. They open a TUI or an editor and hang:
+  `jj arrange`, `jj split`, `jj resolve`, `jj diffedit`, `jj file edit`,
+  `jj squash -i`, and `jj absorb -i`.
 
-3. **Verify operations with `jj st`** after mutations (`squash`, `abandon`,
-`rebase`, `restore`) to confirm the operation succeeded.
+- Use `--no-integrate-operation` to run a command without touching the repo
+  state or the working copy, which helps when a background tool might snapshot
+  at the same time.
 
-## Core Concepts
+## Core concepts
 
-### The Working Copy is a Commit
+### The working copy is a commit
 
-In jj, your working directory is always a commit (referenced as `@`). Changes
-are automatically snapshotted when you run any jj command. There is no staging
-area.
+Your working directory is always a commit, referenced as `@`. Every jj command
+snapshots your changes automatically. There is no staging area, and no need to
+run `jj commit`.
 
-There is no need to run `jj commit`.
+### Commits are mutable
 
-### Commits Are Mutable
+Unlike git, jj commits can be rewritten after you create them. You can change
+the description, squash changes, rebase, and absorb without making new commits.
+See "Essential workflow" for the working pattern.
 
-**CRITICAL**: Unlike git, jj commits can be freely modified after creation. You
-can update descriptions, squash changes, rebase, and absorb — all without
-creating new commits. See "Essential Workflow" below for the recommended working
-pattern.
+### Change IDs vs commit IDs
 
-### Change IDs vs Commit IDs
+- Change ID: a stable identifier such as `tqpwlqmp` that survives a rewrite.
+  Prefer it when referencing commits.
+- Commit ID: a content hash such as `3ccf7581` that changes with the content.
 
-- **Change ID**: A stable identifier (like `tqpwlqmp`) that persists when a
-  commit is rewritten — prefer these when referencing commits
-- **Commit ID**: A content hash (like `3ccf7581`) that changes when commit
-  content changes
+A change ID can name several hidden or divergent commits at once. Add a numeric
+suffix to pick one: `xyz/0` is the newest version and `xyz/1` the one before it.
+So `jj restore --from xyz/1 --to xyz` puts `xyz` back to its previous contents.
 
 ### Revsets
 
-jj uses a revset language to select commits in commands. Common revsets:
+jj selects commits with a revset language. Common revsets:
+
+- `@`, the working copy commit
+- `@-`, the parent of the working copy
+- `::@`, all ancestors of `@`
+- `@::`, all descendants of `@`
+- `trunk()..@`, the commits between trunk and `@`
+- `bookmarks()`, every commit with a bookmark
 
-- `@` — the working copy commit
-- `@-` — the parent of the working copy
-- `::@` — all ancestors of `@`
-- `@::` — all descendants of `@`
-- `trunk()..@` — commits between trunk and `@` (your branch)
-- `bookmarks()` — all commits with bookmarks
+Useful functions added in recent versions: `divergent()`, `merge_point()`,
+`forks()`, `remote_tags()`, `diff_lines()`, `diff_lines_added()`,
+`diff_lines_removed()`, and `builtin_log()` (the default `jj log` revset).
 
-Use revsets with `-r` flags: `jj log -r 'trunk()..@'`
+Pass revsets with `-r`: `jj log -r 'trunk()..@'`.
 
-## Essential Workflow
+String patterns in revsets default to glob matching, so use the `substring:` or
+`exact:` prefix for other kinds. Git-style symbols such as `refs/heads/main` no
+longer resolve to revisions; use the bookmark or tag name.
 
-### Starting Work: Describe First, Then Code
+## Essential workflow
 
-**Always create your commit message before writing code:**
+### Starting work: describe first, then code
 
-Validate that you're on a blank revision with `jj st`. If you are not, you
-should type:
+Write the commit message before the code.
+
+Check that you're on a blank revision with `jj st`. If not, start one:
 
 ```bash
 jj new
 ```
 
+Then describe the work and make the changes:
+
 ```bash
-# First, describe what you intend to do
 jj desc -m "Add user authentication to login endpoint"
-
-# Then make your changes - they automatically become part of this commit
 # ... edit files ...
-
-# Check status
 jj st
 ```
 
-### Creating Atomic Commits
+The edits become part of that commit on their own.
 
-Each commit should represent ONE logical change. Use this format for commit
-messages:
+### Creating atomic commits
+
+Each commit should be one logical change. Message examples:
 
 ```text
-Examples:
-- "Add validation to user input forms"
-- "Fix null pointer in payment processor"
-- "Remove deprecated API endpoints"
-- "Update dependencies to latest versions"
+Add validation to user input forms
+Fix null pointer in payment processor
+Remove deprecated API endpoints
 ```
 
-### Viewing History
+### Viewing history
 
 ```bash
-# View recent commits
 jj --no-pager log
-
-# View with patches
 jj --no-pager log -p
-
-# View specific commit
 jj --no-pager show <change-id>
-
-# View diff of working copy (use --git for familiar +/- format)
 jj --no-pager diff --git
 ```
 
-**IMPORTANT: `jj diff` output format**: The default `jj diff` output uses a
-side-by-side line number format (e.g. `26   26:`) that looks very different from
-git's `+`/`-` prefix format. This is **normal and correct** — it is NOT
-corrupted or showing stale content. However, to avoid confusion,
-**always use `jj diff --git`** to get standard unified diff format with `+`/`-`
-lines.
+`jj show` takes several revisions at once, and `--reversed` shows a commit
+against its parent.
+
+About the `jj diff` format: the default output is a side-by-side line-number
+layout (`26   26:`) that looks nothing like git's `+`/`-` prefixes. It is
+correct, not stale or corrupt. Use `jj diff --git` for a standard unified diff.
 
-### Moving Between Commits
+### Moving between commits
 
 ```bash
-# Create a new empty commit on top of current
 jj new
-
-# Create new commit with message
 jj new -m "Commit message"
-
-# Edit an existing commit (working copy becomes that commit)
 jj edit <change-id>
-
-# Edit the previous commit
 jj prev -e
-
-# Edit the next commit
 jj next -e
 ```
 
-## Refining Commits
+## Refining commits
 
-### Squashing Changes
-
-Move changes from current commit into its parent:
+### Squashing changes
 
 ```bash
-# Squash all changes into parent
 jj squash
 ```
 
-**Note**: `jj squash -i` opens an interactive UI and will hang in agent
-environments. Avoid it.
-
-### Splitting Commits
+`jj squash -i` opens an interactive UI and hangs in an agent environment.
 
-**Warning**: `jj split` is interactive and will hang in agent environments. To
-divide a commit, use `jj restore` to move changes out, then create separate
-commits manually.
+### Splitting commits
 
-### Absorbing Changes
+`jj split` is interactive and hangs in an agent environment. To divide a commit,
+use `jj restore` to move changes out and create the separate commits by hand.
 
-Automatically distribute changes to the commits that last modified those lines:
+### Absorbing changes
 
 ```bash
-# Absorb working copy changes into appropriate ancestor commits
 jj absorb
 ```
 
-### Abandoning Commits
+Distributes working-copy changes to the commits that last touched those lines.
+`jj absorb -i` and `--tool` are interactive; skip them in agent runs.
 
-Remove a commit entirely (descendants are rebased to its parent):
+### Abandoning commits
 
 ```bash
 jj abandon <change-id>
 ```
 
-### Undoing Operations
+Descendants are rebased onto the abandoned commit's parent.
 
-Reverse the last jj operation:
+### Undoing operations
 
 ```bash
 jj undo
+jj redo
 ```
 
-This reverts the repository to its state before the previous command. Useful
-for recovering from mistakes like accidental `abandon`, `squash`, or `rebase`.
+These reverse or reapply the last operation, which recovers from a mistaken
+`abandon`, `squash`, or `rebase`. They refuse to touch an operation from another
+workspace unless you pass `--allow-cross-workspace`. To revert one specific
+operation, use `jj op revert`; the old `jj op undo` was removed.
 
-### Rebasing Commits
-
-Move commits to a different parent:
+### Rebasing commits
 
 ```bash
-# Rebase current branch onto a destination
 jj rebase -d <destination>
-
-# Rebase a specific revision (without descendants) onto a destination
 jj rebase -r <change-id> -d <destination>
-
-# Rebase a revision and all its descendants
 jj rebase -s <change-id> -d <destination>
-
-# Rebase onto trunk (common: update your branch to latest main)
 jj rebase -d main
 ```
 
-### Restoring Files
-
-Discard changes to specific files or restore files from another revision:
+### Restoring files
 
 ```bash
-# Discard all uncommitted changes in working copy (restore from parent)
 jj restore
-
-# Discard changes to specific files
 jj restore path/to/file.txt
-
-# Restore files from a specific revision
 jj restore --from <change-id> path/to/file.txt
 ```
 
-## Working with Bookmarks (Branches)
+## Working with bookmarks
 
-Bookmarks are jj's equivalent to git branches:
+Bookmarks are jj's branches.
 
 ```bash
-# Create a bookmark at current commit
-jj bookmark create my-feature -r@
-
-# Move bookmark to a different commit
+jj bookmark create my-feature -r @
 jj bookmark move my-feature --to <change-id>
-
-# List bookmarks
 jj --no-pager bookmark list
-
-# Delete a bookmark
 jj bookmark delete my-feature
 ```
 
-## Workspaces
+Bookmarks don't advance when you add commits, so move them by hand before
+pushing. `jj bookmark advance [names]` moves bookmarks forward to a target in
+one step, with `--to` defaulting to `@`.
+
+`jj bookmark track` and `untrack` take `--remote`. Without it, every remote
+bookmark with a matching name is tracked or untracked.
+
+## Working with tags
+
+Tags use the same tracking model as bookmarks: fetched tags are tracked by
+default, and tracked tags are pushed by default.
+
+```bash
+jj --no-pager tag list
+jj tag track <name>
+jj tag untrack <name>
+```
+
+`jj tag list` supports `--sort` and can be filtered by revset.
 
-A **workspace** is a working copy plus its associated repo. One repo can have
-multiple workspaces — each with its own working directory and working-copy
-commit (`@`) — all sharing the same commits, operations, and bookmarks. This is
-jj's equivalent of `git worktree`.
+## Workspaces
 
-Useful for running a long build or test in one workspace while editing in
-another. Workspaces are a rarely-needed feature; consult the
+A workspace is a working copy plus its repo. One repo can hold several
+workspaces, each with its own working directory and `@`, all sharing the same
+commits, operations, and bookmarks. It is jj's version of `git worktree`, handy
+for running a long build or test while editing elsewhere. Most tasks don't need
+one; see the
 [official docs](https://docs.jj-vcs.dev/latest/working-copy/#workspaces) for
-anything beyond the basics below.
+anything beyond the basics.
 
 ### Common commands
 
 ```bash
-# Create a new workspace (defaults: name = basename of path, parent = current @'s parent)
 jj workspace add ../my-tests
-jj workspace add --name tests -r <change-id> ../my-tests   # explicit name and base
-
-# Inspect
+jj workspace add --name tests -r <change-id> ../my-tests
 jj --no-pager workspace list
 jj workspace root [--name <ws>]
-
-# Remove (does NOT delete files on disk — rm the directory separately)
-jj workspace forget [<ws>]
-
-# Rename current workspace
 jj workspace rename <new-name>
+jj workspace forget [<ws>]
+jj workspace remove [<ws>]
 ```
 
+`forget` leaves the directory on disk; `remove` deletes it too, after
+snapshotting the working copy into a commit. `add` links by relative path, so a
+workspace survives being moved together with its parent or run inside a
+container. `list` shows each workspace root by default and no longer hides
+unreachable paths.
+
 In `jj log`, each workspace's `@` appears as `<workspace-name>@`.
 
+### Colocation
+
+`jj workspace add` can create a Git worktree alongside the workspace with
+`--colocate`/`--no-colocate`. `jj git colocation status`, `enable`, and
+`disable` report or toggle this, and they work on child workspaces.
+
 ### Key semantics
 
-- **Isolation by default.** `jj workspace add` gives the new workspace its own
-  fresh empty commit; workspaces don't start out sharing `@`, and on-disk files
-  are never live-mirrored between them.
-- **Propagation at command boundaries.** Each jj command snapshots the current
-  workspace's files and reads the op log, so it sees commits/bookmarks made by
-  other workspaces. There is no filesystem watcher.
-- **Stale working copy.** If another workspace rewrites this workspace's `@`
-  (e.g. via `jj squash`, `rebase`, `abandon`), jj refuses commands here until
-  you run `jj workspace update-stale`. Same recovery path if a command was
-  interrupted mid-update.
-- **Shared `@` is sharp-edged.** `jj edit <id>` lets two workspaces point at the
-  same change without warning. When one mutates it, the other goes stale; if the
-  stale one had un-snapshotted edits, `update-stale` preserves them as a
-  **divergent commit** (same change ID, shown as `xyz??` in `jj log`) that you
-  must resolve. Avoid sharing `@` unless both workspaces are read-only.
+- Isolation by default. A new workspace gets its own fresh empty commit.
+  Workspaces don't start out sharing `@`, and files are never live-mirrored
+  between them.
+- Propagation at command boundaries. Each command snapshots its own files and
+  reads the op log, so it sees commits and bookmarks from other workspaces.
+  There is no filesystem watcher.
+- Stale working copy. If another workspace rewrites this workspace's `@` (via
+  `squash`, `rebase`, or `abandon`), jj refuses commands here until you run
+  `jj workspace update-stale`. The same recovery applies after an interrupted
+  command.
+- Shared `@` is sharp-edged. `jj edit <id>` lets two workspaces point at the
+  same change without warning. When one mutates it, the other goes stale; if
+  the stale one had unsnapshotted edits, `update-stale` keeps them as a
+  divergent commit (same change ID, shown as `xyz??` in `jj log`). Resolve the
+  divergence with `jj converge`, or select one version with the `xyz/0`,
+  `xyz/1` syntax. Avoid sharing `@` unless both workspaces are read-only.
 
 ### Agent guidance
 
-- Always pass `--no-pager` to `jj workspace list`.
-- Don't `jj edit` a change another workspace already has as its `@` — main cause
-  of accidental divergence.
+- Pass `--no-pager` to `jj workspace list`.
+- Don't `jj edit` a change that another workspace already has as `@`. That is
+  the usual cause of accidental divergence.
 - Don't `rm -rf` a workspace directory without also running
   `jj workspace forget <name>`.
 
-## Git Integration
+## Git integration
 
-### Working with Existing Git Repos
+### Working with existing Git repos
 
 ```bash
-# Clone a git repository
 jj git clone <url>
-
-# Initialize jj in an existing git repo
 jj git init --colocate
 ```
 
-### Fetching Remote Changes
+`jj git init --colocate` refuses to run inside a Git worktree and explains the
+alternatives.
+
+### Fetching remote changes
 
 ```bash
-# Fetch all branches from the default remote
 jj git fetch
-
-# Fetch from a specific remote
 jj git fetch --remote <remote-name>
-
-# Fetch specific branches
 jj git fetch -b <branch-name>
 ```
 
-After fetching, rebase your work onto the updated trunk: `jj rebase -d main`
-
-### Switching Between jj and git (Colocated Repos Only)
+`jj git fetch` reports abandoned commits and forwards git's stderr, so
+authentication prompts still reach you. It rebases local descendants onto
+rewritten parents when the remote preserves change IDs. Tags arrive as
+`<name>@<remote>` and are tracked by local tags of the same name. After
+fetching, rebase your work: `jj rebase -d main`.
 
-**This section only applies to colocated repos** (where both `.jj/` and `.git/`
-exist). In non-colocated repos, do not use git commands — they will corrupt jj
-state.
+### Switching between jj and git (colocated repos only)
 
-In a colocated repository, you can use both jj and git commands with care:
+This applies only to colocated repos, where `.jj/` and `.git/` both exist. In a
+non-colocated repo, do not run git commands; they corrupt jj state.
 
-**Switching to git mode** (e.g., for merge workflows):
+Switch to git for a merge workflow:
 
 ```bash
-# First, ensure your jj working copy is clean
 jj st
-
-# Then checkout a branch with git
 git checkout <branch-name>
 ```
 
-**Switching back to jj mode**:
+Switch back:
 
 ```bash
-# Use jj edit to resume working with jj
 jj edit <change-id>
 ```
 
-**Important notes:**
-
-- Git may complain about uncommitted changes if jj's working copy differs from
-  the git HEAD
-- ALWAYS ensure your work is committed in jj before switching to git
-- After git operations, jj will detect and incorporate the changes on next
-  command
+Git may complain about uncommitted changes when jj's working copy differs from
+the git HEAD, so commit your jj work first. jj picks up git's changes on the
+next command.
 
-### Pushing Changes
-
-When the user asks you to push changes:
+### Pushing changes
 
 ```bash
-# Push a specific bookmark to the remote
 jj git push -b <bookmark-name>
-
-# Example: push the main bookmark
 jj git push -b main
 ```
 
-**Before pushing, ensure:**
-
-1. Your bookmark points to the correct commit (bookmarks don't auto-advance like
-   git branches)
-2. The commits are refined and atomic
-3. The user has explicitly requested the push
-
-**IMPORTANT**: Unlike git branches, jj bookmarks do not automatically move when
-you create new commits. You must manually update them before pushing:
+Before pushing, confirm the bookmark points at the right commit (bookmarks
+don't auto-advance), the commits are refined and atomic, and the user asked for
+the push.
 
 ```bash
-# Move an existing bookmark to the current commit
 jj bookmark move my-feature --to @
-
-# Then push it
 jj git push -b my-feature
 ```
 
-If no bookmark exists for your changes, create one first:
+If no bookmark exists, create one first:
 
 ```bash
-# Create a bookmark at the current commit
 jj bookmark create my-feature
-
-# Then push it
 jj git push -b my-feature
 ```
 
-## Handling Conflicts
+`jj git push` can push to several remotes at once with repeated `--remote`,
+allow commits that contain conflicts with `--allow-conflicts`, forward push
+options with `-o`, and auto-track a bookmark given to `--bookmark`. The default
+push targets come from `revsets.git-push`.
+
+## Handling conflicts
 
-jj allows committing conflicts — you can resolve them later:
+jj lets you commit conflicts and resolve them later.
 
 ```bash
-# View conflicts
 jj st
 ```
 
-**Agent conflict resolution**: Do not use `jj resolve` (interactive). Instead,
-edit the conflicted files directly to remove conflict markers, then run `jj st`
-to verify resolution.
+Resolve conflicts by editing the files to remove the markers, then run `jj st`.
+Don't use `jj resolve`; it is interactive.
+
+## Running commands over revisions
+
+`jj run` runs a command over a set of revisions, each in an isolated working
+copy, then amends each revision with the result:
+
+```bash
+jj run -- cargo fix
+jj run -j 4 -- cargo test
+jj run --ignore-changes -- cargo clippy
+```
+
+It processes revisions oldest to newest by default. `--passthrough` connects the
+subprocess to the terminal instead of capturing output, `--ignore-changes` runs
+read-only without rewriting commits, and `--ignore-errors` continues after a
+failing command.
+
+## Resolving divergence
+
+`jj converge` combines the divergent revisions of a change into one
+replacement, rebasing descendants and moving bookmarks onto it. It applies
+heuristics and prompts when they don't agree. Pass `--no-interactive` to print a
+warning and exit instead of prompting, which is what an agent should do.
+
+## Inspecting files and other utilities
+
+```bash
+jj file search -p <pattern>          # grep-like; prints each match with its path
+jj file search -p <pattern> -n       # add line numbers; --name-only lists files
+jj file delete -r <rev> <path>       # delete files in any revision
+jj file show -r <rev> <path>         # print a file from a revision
+jj file annotate <path>              # blame
+jj util snapshot                     # snapshot the working copy
+jj util diff <a> <b>                 # compare two files on disk
+jj util backend name                 # show the commit backend
+jj util gc                           # prune unreachable data in the store
+jj config gc                         # drop config for deleted repos
+jj bisect run --range <revs> <cmd>   # find the first bad revision
+```
+
+`jj file search` matches by regex unless the pattern sets another kind, and it
+requires `-p`. `jj file edit` edits a file in a revision but opens your editor,
+so it is not for agent runs. `jj bisect run` checks its endpoints first; pass
+`--trust-endpoints` to skip the checks.
 
-## Preserving Commit Quality
+## Preserving commit quality
 
-**IMPORTANT**: Because commits are mutable, always refine them before
-considering work done:
+Because commits are mutable, refine them before you call the work done.
 
-1. **Review your commit**: `jj --no-pager show @` or `jj --no-pager diff --git`
-2. **Is it atomic?** One logical change per commit
-3. **Is the message clear?** Use imperative verb phrase in sentence case format
-   with no full stop: e.g. "Add login endpoint", "Fix null pointer in payment
-   processor", "Remove deprecated API endpoints"
-4. **Are there unrelated changes?** Use `jj restore` to move changes out, then
-   create separate commits
-5. **Should changes be elsewhere?** Use `jj squash` or `jj absorb`
+1. Review: `jj --no-pager show @` or `jj --no-pager diff --git`.
+2. Keep one logical change per commit.
+3. Write the message as an imperative phrase in sentence case with no full
+   stop: "Add login endpoint", "Fix null pointer in payment processor".
+4. Move unrelated changes out with `jj restore`, then make separate commits.
+5. Put changes in the right commit with `jj squash` or `jj absorb`.
 
-## Quick Reference
+## Quick reference
 
 | Action | Command |
 |--------|---------|
@@ -450,7 +454,7 @@ considering work done:
 | View status | `jj st` |
 | View log | `jj --no-pager log` |
 | View diff | `jj --no-pager diff --git` |
-| New commit | `jj new -m "message"` (use `jj st` first; skip if `@` is empty) |
+| New commit | `jj new -m "message"` |
 | Edit commit | `jj edit <id>` |
 | Squash to parent | `jj squash` |
 | Auto-distribute | `jj absorb` |
@@ -458,18 +462,24 @@ considering work done:
 | Abandon commit | `jj abandon <id>` |
 | Undo last operation | `jj undo` |
 | Restore files | `jj restore [paths]` |
+| Search files | `jj file search -p <pattern>` |
+| Run over revisions | `jj run -- <cmd>` |
+| Resolve divergence | `jj converge --no-interactive` |
 | Create bookmark | `jj bookmark create <name>` |
+| Advance bookmark | `jj bookmark advance <name>` |
+| Track tag | `jj tag track <name>` |
 | Fetch remote | `jj git fetch` |
 | Push bookmark | `jj git push -b <name>` |
 | Add workspace | `jj workspace add <path>` |
 | List workspaces | `jj --no-pager workspace list` |
+| Remove workspace | `jj workspace remove [name]` |
 | Forget workspace | `jj workspace forget [name]` |
 | Fix stale working copy | `jj workspace update-stale` |
 
-## Best Practices Summary
+## Best practices summary
 
-1. **Describe first**: Set the commit message before coding
-2. **One change per commit**: Keep commits atomic and focused
-3. **Use change IDs**: They're stable across rewrites
-4. **Refine commits**: Leverage mutability for clean history
-5. **Embrace the workflow**: No staging area, no stashing - just commit
+1. Describe first: set the message before coding.
+2. One change per commit.
+3. Use change IDs; they survive rewrites.
+4. Refine commits with `squash` and `absorb`.
+5. No staging area, no stashing.