Saltar al contenido

Haz que tu agente de programación use Jujutsu en vez de Git

Estos archivos de configuración listos para usar acompañan a Juju-chu!, una guía práctica para usar Jujutsu con agentes de programación con IA.
También puedes usarlos por separado: no hace falta comprar el libro.

Última actualización: 30 de agosto de 2026

En esta página encontrarás archivos de configuración a nivel de proyecto para que Claude Code y Codex CLI usen Jujutsu en lugar de Git.

Colócalos en los lugares correspondientes de tu proyecto. Así, el agente tendrá a mano el modelo mental de Jujutsu y sus flujos de trabajo básicos cuando se encargue del control de versiones. No tendrás que decirle “haz commit de esto”: a partir de la tarea que le asignes, organizará su trabajo en changes coherentes.

Los mismos archivos de configuración también están disponibles en el repositorio complementario del libro.

Por qué no basta con decírselo al agente

Se lo pregunté directamente a los modelos más recientes disponibles en Claude Code y Codex CLI, y ambos ya conocen los conceptos y comandos básicos de Jujutsu. De hecho, una breve instrucción en CLAUDE.md o AGENTS.md que indique al agente que use Jujutsu para el control de versiones suele bastar para que se comporte razonablemente bien.

Aun así, la mayoría de los flujos de desarrollo presentes en sus datos de entrenamiento siguen basándose en Git, por lo que estos modelos no han interiorizado un flujo de trabajo nativo de Jujutsu. Si esa breve instrucción es su única guía, pueden ocurrir cosas como estas:

  • Sustituir mecánicamente cada comando git por el comando jj más parecido
  • Empezar una tarea sin comprobar el estado del working-copy commit y acabar mezclando en el mismo change trabajo que no tiene relación con ella
  • Tratar un bookmark como una branch de Git que avanza automáticamente con cada commit
  • Detener el trabajo en cuanto aparece un conflicto
  • Quedarse atascado ante un problema específico de Jujutsu

Una cosa es conocer comandos sueltos; otra muy distinta, haberlos usado en tareas reales y haber desarrollado criterio práctico. Pídele a un agente que realice una operación concreta en el repositorio y ejecutará el comando de Jujutsu correspondiente. Pero si quieres que se encargue del control de versiones mientras implementa una funcionalidad o corrige un error, organizando el trabajo en changes coherentes sin que tengas que pedírselo, debes enseñarle un flujo de trabajo basado en el modelo mental de Jujutsu.

Eso es justo lo que cubren las configuraciones de esta página:

  • Qué comandos puede ejecutar el agente y cuáles no
  • Cuándo añadir --git a los comandos que muestran diffs para que el agente pueda interpretar mejor la salida
  • Cuándo usar --ignore-working-copy con comandos de solo lectura para evitar la fragmentación innecesaria de revisiones y los errores de working copy desactualizada (stale)
  • Cómo gestionar el change actual al empezar una tarea
  • Cómo dividir changes y resolver conflictos
  • Cómo gestionar bookmarks al hacer push
  • Qué hacer cuando la working copy queda desactualizada

Configuración de Claude Code

La configuración de Claude Code se basa en reglas que se aplican en todas las sesiones.

CLAUDE.md contiene únicamente la instrucción de máxima prioridad: usar Jujutsu en lugar de Git. Las explicaciones más detalladas sobre el modelo mental de Jujutsu y los procedimientos específicos de cada tarea se guardan por separado en .claude/rules/jujutsu-rules.md.

El paquete también incluye un archivo settings.json que impide al agente ejecutar comandos de Git y permite ejecutar los comandos habituales de Jujutsu sin pedir permiso cada vez.

.
├─ .claude/
│  ├─ rules/
│  │  └─ jujutsu-rules.md
│  └─ settings.json
└─ CLAUDE.md
CLAUDE.md
## Version Control — Required Procedure

This project uses **Jujutsu (jj)** for version control. For the detailed rules, see `.claude/rules/jujutsu-rules.md`.

**Before you begin editing code**, always settle which change the work belongs to: inspect working-copy commit (`@`), reuse it if it is empty, otherwise open a new one. The decision procedure is in the rules file under "1. Starting Work" of "Basic Workflow" — do not start editing and sort the changes out afterwards.

**Prohibited:** Direct use of `git` commands (the `jj git` subcommands and the `gh` CLI are allowed).
.claude/rules/jujutsu-rules.md
# Jujutsu (jj) Rules for AI Agents

Standard jj semantics are assumed knowledge. What follows is only what an agent cannot infer from the tool itself: this repository's permissions, its aliases, and the conventions the team has settled on.

---

## Important Notes for AI Agents

### Command Constraints

`.claude/settings.json` denies these outright. Never plan a workflow around them; if one is genuinely needed, describe the command and let the user run it.

| Denied        | Why                                                                                 |
| ------------- | ----------------------------------------------------------------------------------- |
| `git` (all)   | Risks corrupting jj state. `jj git ...` and `gh` remain allowed.                    |
| `jj resolve`  | Opens the interactive merge editor. Resolve conflicts by editing the files instead. |
| `jj diffedit` | Opens the interactive diff editor.                                                  |
| `jj arrange`  | Interactive TUI.                                                                    |

`jj split` is allowed, but **always pass filesets and `-m`. Never run it bare, and never pass `-i` or `--tool`** because these actions trigger an interactive diff editor.

These prompt for confirmation every time, so save them for the end of a task rather than firing them mid-flow: `jj git push`, `jj bookmark delete`, `jj bookmark forget`, `jj bookmark track`, `jj bookmark untrack`.

### What jj Changes About the Workflow

- **No staging, no stash, no "unsaved change".** Saving a file puts it in the working-copy commit (`@`) that instant. Never ask the user whether a change should be included — it already is.
- **Bookmarks are not branches and do not follow `@`** — and they do not need to. Leave them where they are while you work; there is nothing to keep in sync. Position one only when it is about to be used (see "Positioning a Bookmark").
- **Automatic formatting (`jj fix`)**: This project has `jj fix` set up. Because it is registered as a Stop hook, it runs when a task finishes and retroactively reformats the code across the mutable changes. Even if `jj diff` shows unintended formatting changes, accept them as long as they conform to the project's rules.

### Rules for diff Output

Always pass `--git` to `jj diff`, `jj show`, and `jj log -p`. Without it the output cannot express file additions, deletions, renames, and permission changes accurately, and an agent's reading of the diff degrades accordingly.

### Suppressing Snapshots in Read-Only Operations

Every jj command snapshots the working copy, which risks an operation-log conflict when another process is working in the same repo. Add `--ignore-working-copy` to purely read-only inspection — `jj log`, `jj diff`, `jj bookmark list`, `jj evolog`, `jj op log`.

**Never add it right after creating, editing, or deleting a file**: that is exactly when the snapshot has to be recorded. Use `jj util snapshot` if you want one without running anything else.

### Choosing the Right Log Output

Read `jj log`'s graph as-is for ordinary state checks. To extract values programmatically, add `--no-graph` and `-T`:

```bash
jj log --ignore-working-copy --no-graph -T 'change_id.short() ++ " " ++ description.first_line() ++ "\n"'
```

---

## Basic Workflow

### 1. Starting Work

Adjust your actions according to the state of the working-copy commit (`@`):

1. Run `jj status` — **without** `--ignore-working-copy`, the one exception to the rule above. The user may have edited files since the last jj command, and skipping the snapshot would report those edits as absent.
2. **If `@` is empty** (NO description AND NO diff) → **reuse it.** Set its description with `jj describe -m "<description>"` and work there. **Do not create a new change.** A change created by `jj new` is itself empty, so it falls under this rule too.
3. Otherwise (`@` already has a description or a diff) → `jj new -m "<description>"`.
4. Write the description in English, in Conventional Commits format.

### 2. Splitting a Change

```bash
jj split -m "<description for the extracted change>" <path>...
```

Filesets are what keep it out of the diff editor, `-m` out of the description editor. Hunk-level splits need that editor, so hand those to the user.

### 3. Resolving Conflicts

Edit the marked-up files directly, then confirm with `jj status` that the conflict is gone. Saving the file _is_ the resolution; there is no `git add` equivalent to run afterwards.

jj's conflict markers differ from Git's: the `%%%%%%%` block is a diff against the base, expressed with `-`/`+` lines, while the `+++++++` block is the other side's content verbatim.

### 4. Positioning a Bookmark

Move a bookmark only when asked to push, or asked to open a PR with the push step left implicit. Otherwise leave bookmarks alone — a change does not need one to exist.

Never point one at `@` unexamined: after `jj new` it is empty and undescribed, and `jj git push` refuses a commit whose description is empty. Target the newest ancestor of `@` that has both a diff and a description, and read it back before moving:

```bash
jj log --ignore-working-copy --no-graph \
  -r 'heads(::@ & ~empty() & ~description(exact:""))' \
  -T 'change_id.short() ++ " " ++ description.first_line() ++ "\n"'

jj bookmark create <name> -r 'heads(::@ & ~empty() & ~description(exact:""))'  # the first time
jj bookmark move <name> --to 'heads(::@ & ~empty() & ~description(exact:""))'  # afterwards
```

**Do not use `jj bookmark advance`.** It takes its target from `revsets.bookmark-advance-to`, so the landing point is decided by repository configuration rather than by the command you wrote. Spell the target out at the call site.

### 5. Syncing with the Remote

```bash
jj git fetch                  # fetch the latest state
jj git push -b <bookmark-name>  # publish the bookmark
```

---

## PR Creation Workflow

- The base is always `main` unless instructed otherwise. No confirmation needed.
- **Never squash.** Keep each change as-is so the history stays traceable.
- Pass the title explicitly with `--title` in Conventional Commits format, derived from the description of the bookmark's lead change. Do not rely on the title `gh` derives.

```bash
jj git fetch
jj log --ignore-working-copy
jj bookmark list --all --ignore-working-copy   # then position it — see above
jj bookmark track <bookmark-name>@origin       # only if untracked
jj git push -b <bookmark-name>                 # skip if local and remote already match
gh pr create --base main --head <bookmark-name> --title "<type>: <summary>" --body "<body>"
```

---

## Troubleshooting

**"The working copy is stale"** — a human and an agent worked in the repo in parallel, or an external tool changed files. Run `jj workspace update-stale`, then confirm with `jj status`.
.claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(jj status:*)",
      "Bash(jj log:*)",
      "Bash(jj diff:*)",
      "Bash(jj show:*)",
      "Bash(jj file list:*)",
      "Bash(jj root:*)",
      "Bash(jj describe:*)",
      "Bash(jj new:*)",
      "Bash(jj edit:*)",
      "Bash(jj restore:*)",
      "Bash(jj squash:*)",
      "Bash(jj rebase:*)",
      "Bash(jj abandon:*)",
      "Bash(jj evolog:*)",
      "Bash(jj op log:*)",
      "Bash(jj operation log:*)",
      "Bash(jj undo:*)",
      "Bash(jj bookmark list:*)",
      "Bash(jj bookmark create:*)",
      "Bash(jj bookmark move:*)",
      "Bash(jj bookmark advance:*)",
      "Bash(jj bookmark set:*)",
      "Bash(jj bookmark rename:*)",
      "Bash(jj git fetch:*)",
      "Bash(jj config get:*)",
      "Bash(jj config list:*)"
    ],
    "deny": [
      "Bash(git:*)",
      "Bash(jj resolve:*)",
      "Bash(jj diffedit:*)",
      "Bash(jj arrange:*)"
    ],
    "ask": [
      "Bash(jj bookmark delete:*)",
      "Bash(jj bookmark forget:*)",
      "Bash(jj bookmark track:*)",
      "Bash(jj bookmark untrack:*)",
      "Bash(jj git push:*)"
    ]
  }
}

Descargar la configuración de Claude Code (.zip)

Configuración de Codex CLI

Codex CLI no tiene un equivalente directo de las reglas de comportamiento de Claude Code.

Por eso, el archivo AGENTS.md contiene las instrucciones que Codex debe seguir siempre y le indica que consulte una skill para obtener indicaciones detalladas sobre el uso de Jujutsu.

Codex también cuenta con una funcionalidad llamada rules, pero estas reglas cumplen otra función: controlan si un comando puede ejecutarse fuera del sandbox. El paquete incluye un archivo de rules adaptado a partir de los permisos definidos en el settings.json de Claude Code.

.
├─ .agents/
│  └─ skills/
│     └─ jujutsu/
│        └─ SKILL.md
├─ .codex/
│  └─ rules/
│     └─ jujutsu.rules
└─ AGENTS.md
AGENTS.md
## Version Control —   Required Procedure

This repository uses Jujutsu (`jj`). Use `jj` terminology and commands; do not run raw `git` commands. `jj git ...` and `gh` are allowed.

Before editing, run `jj status` to snapshot and inspect working-copy commit (`@`). Reuse `@` only when it has neither a description nor a diff; otherwise create a new change. Write change descriptions in English using Conventional Commits.
Always use `--git` with `jj diff`, `jj show`, and `jj log -p`. Use `--ignore-working-copy` for purely read-only inspection only after the working copy is known to be snapshotted.

Do not run `jj resolve`, `jj diffedit`, or `jj arrange`. Run `jj split` only with filesets and `-m` (never bare, never with `-i` or `--tool`), which is what keeps it out of the diff editor. After history-changing operations, run `jj status` and resolve any conflicts before continuing.
Do not move bookmarks unless publishing changes. PRs target `main` unless instructed otherwise, and stacked changes must not be squashed.

For non-trivial revsets, conflicts, bookmark operations, history rewriting or recovery, fetch, push, and PR creation, consult the `jujutsu` Skill at `.agents/skills/jujutsu/SKILL.md`.
.agents/skills/jujutsu/SKILL.md
---
name: jujutsu
description: Repository-specific procedures for non-trivial Jujutsu operations, including revsets, conflicts, bookmarks, history rewriting or recovery, remote synchronization, and PR creation.
---

# Jujutsu Operations

The standing policy lives in `AGENTS.md`. This skill covers only repository-specific decisions and procedures that are not implied by standard Jujutsu behavior.

## When to Use This Skill

- Writing or evaluating a non-trivial revset
- Resolving conflicts
- Creating, moving, tracking, forgetting, or deleting bookmarks
- Rebasing, squashing, restoring, abandoning, undoing, or restoring an operation
- Splitting a change without a diff editor
- Handling stale or immutable working-copy errors
- Fetching, pushing, or creating a PR

Routine state inspection and starting ordinary work do not require this skill; follow `AGENTS.md` directly.

## Repository Constraints

- Do not run raw `git` commands. `jj git ...` and `gh` are allowed.
- Do not run `jj resolve`, `jj diffedit`, or `jj arrange`; they require interactive interfaces. `jj split` is allowed only with filesets and `-m` — never bare, never `-i`/`--tool`. If a task cannot be completed safely with non-interactive commands, ask the user to perform that part.
- Always add `--git` to `jj diff`, `jj show`, and `jj log -p`.
- After a history-changing operation such as `jj new`, `jj rebase`, `jj squash`, `jj restore`, or `jj abandon`, run `jj status` before continuing.
- Do not squash stacked changes when preparing a PR.

## Snapshot Discipline

Add `--ignore-working-copy` to read-only inspection — `jj log`, `jj diff`, `jj bookmark list`, `jj evolog`, `jj op log` — only when the working copy is already known to be snapshotted, since it suppresses a new snapshot and can report stale state.

Omit it at the start of work and after creating, editing, or deleting a file: those are exactly the moments the latest filesystem state has to be captured.

## Splitting a Change by File

```bash
jj split -m "<description for the extracted change>" <path>...
```

Filesets are what keep it out of the diff editor, `-m` out of the text editor. Hunk-level splits need that editor, so hand those to the user.

## Resolving Conflicts

Edit the conflict markers directly into the intended final content, then confirm with `jj status` that no conflict remains. Saving the file is the resolution: do not run `jj resolve`, and do not look for a `git add` equivalent afterwards.

## Positioning a Bookmark for Publication

Do not move bookmarks during ordinary implementation. Position one only when the user asks to push or create a PR, including when the push is implicit in the PR request.

Never assume `@` is the revision to publish — after `jj new` it may be empty. Target the newest ancestor of `@` that has both content and a description, and read the result back before moving the bookmark:

```bash
jj log --ignore-working-copy --no-graph \
  -r 'heads(::@ & ~empty() & ~description(exact:""))' \
  -T 'change_id.short() ++ " " ++ description.first_line() ++ "\n"'

jj bookmark create <name> -r 'heads(::@ & ~empty() & ~description(exact:""))'  # new bookmark
jj bookmark move <name> --to 'heads(::@ & ~empty() & ~description(exact:""))'  # existing one
jj status
```

Do not use `jj bookmark advance`; spell out the target revision at the call site.

## Remote and PR Workflow

Unless instructed otherwise, use `main` as the PR base and preserve each change in a stack. Track an untracked remote bookmark with `jj bookmark track <name>@origin`, and skip the push when local and remote already match. The PR title is Conventional Commits, passed explicitly; the body is Japanese.

```bash
jj git fetch
jj log --ignore-working-copy
jj bookmark list --all --ignore-working-copy   # then position it — see above
jj git push -b <name>
gh pr create --base main --head <name> --title "<type>: <summary>" --body "<body>"
```

## Recovery and Troubleshooting

Before `jj undo`, `jj op restore`, `jj restore`, or `jj abandon`, inspect the affected operation or revision and confirm that it is exactly the intended target. Do not discard or rewrite user work based on an assumed target.

**Stale working copy** — run `jj workspace update-stale`, then `jj status`.

**Immutable revision** — do not bypass immutability. Check the target, choose the intended mutable change, and retry there.
.codex/rules/jujutsu.rules
# .codex/rules/jujutsu.rules

# --- allow ---
prefix_rule(pattern = ["jj", "status"], decision = "allow")
prefix_rule(pattern = ["jj", "log"], decision = "allow")
prefix_rule(pattern = ["jj", "diff"], decision = "allow")
prefix_rule(pattern = ["jj", "show"], decision = "allow")
prefix_rule(pattern = ["jj", "file", "list"], decision = "allow")
prefix_rule(pattern = ["jj", "root"], decision = "allow")
prefix_rule(pattern = ["jj", "describe"], decision = "allow")
prefix_rule(pattern = ["jj", "new"], decision = "allow")
prefix_rule(pattern = ["jj", "edit"], decision = "allow")
prefix_rule(pattern = ["jj", "restore"], decision = "allow")
prefix_rule(pattern = ["jj", "squash"], decision = "allow")
prefix_rule(pattern = ["jj", "rebase"], decision = "allow")
prefix_rule(pattern = ["jj", "abandon"], decision = "allow")
prefix_rule(pattern = ["jj", "evolog"], decision = "allow")
prefix_rule(pattern = ["jj", "op", "log"], decision = "allow")
prefix_rule(pattern = ["jj", "operation", "log"], decision = "allow")
prefix_rule(pattern = ["jj", "undo"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "list"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "create"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "move"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "advance"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "set"], decision = "allow")
prefix_rule(pattern = ["jj", "bookmark", "rename"], decision = "allow")
prefix_rule(pattern = ["jj", "config", "get"], decision = "allow")
prefix_rule(pattern = ["jj", "config", "list"], decision = "allow")
prefix_rule(
    pattern = ["jj", "git", "fetch"],
    decision = "allow",
    justification = "Jujutsu's fetch is allowed"
)

# --- deny / forbidden ---
prefix_rule(
    pattern = ["git"],
    decision = "forbidden",
    justification = "Do not use raw git; use jj commands instead"
)
prefix_rule(
    pattern = ["jj", "resolve"],
    decision = "forbidden",
    justification = "Conflicts should be resolved manually"
)
prefix_rule(
    pattern = ["jj", "diffedit"],
    decision = "forbidden",
    justification = "jj diffedit should be done manually"
)
prefix_rule(
    pattern = ["jj", "arrange"],
    decision = "forbidden",
    justification = "jj arrange should be done manually"
)

# --- ask / prompt ---
prefix_rule(
    pattern = ["jj", "bookmark", "delete"],
    decision = "prompt",
    justification = "Deleting a bookmark requires confirmation"
)
prefix_rule(
    pattern = ["jj", "bookmark", "forget"],
    decision = "prompt",
    justification = "bookmark forget requires confirmation"
)
prefix_rule(
    pattern = ["jj", "bookmark", "track"],
    decision = "prompt",
    justification = "Starting to track a remote bookmark requires confirmation"
)
prefix_rule(
    pattern = ["jj", "bookmark", "untrack"],
    decision = "prompt",
    justification = "Untracking a remote bookmark requires confirmation"
)
prefix_rule(
    pattern = ["jj", "git", "push"],
    decision = "prompt",
    justification = "Pushing to the remote requires confirmation",
    match = ["jj git push -b feature-x"],
)

Descargar la configuración de Codex (.zip)

Cómo usar estos archivos

Instalación

  1. Descomprime el archivo ZIP descargado.
  2. Copia todo el contenido de la carpeta resultante en la raíz de tu proyecto, incluidos los directorios cuyos nombres empiezan por un punto. Conserva la estructura de directorios.
  3. Inicia una sesión nueva en Claude Code o Codex CLI.

Si tu proyecto ya contiene archivos con los mismos nombres, se sobrescribirán al copiar esta configuración. Haz primero una copia de seguridad de los archivos existentes o combina el contenido manualmente.

Requisitos

  • Jujutsu debe estar instalado y el comando jj debe estar disponible.
  • El proyecto de destino debe estar inicializado como repositorio de Jujutsu.
  • Claude Code o Codex CLI deben estar instalados.

Versiones probadas

  • Jujutsu: 0.44.0
  • Claude Code: 2.1.226
  • Codex CLI: 0.147.0

Licencia

Estos archivos de configuración se ofrecen bajo la Apache License 2.0. Se permiten el uso comercial, la modificación y la redistribución.

Consulta el archivo LICENSE incluido en cada descarga para conocer las condiciones completas.

El libro va más allá de esta configuración inicial

Estos archivos de configuración bastan para que Claude Code y Codex usen Jujutsu en el control de versiones del día a día. Sin embargo, a medida que tu flujo de trabajo crezca, quizá necesites también comprobaciones automáticas, limpieza de changes y coordinación entre varios agentes.

Juju-chu! explica paso a paso cómo construir esos flujos de trabajo. Entre otras cosas, aprenderás a:

  • Ejecutar formateadores y linters con jj fix cada vez que un agente termine una tarea
  • Ejecutar pruebas, builds y comprobaciones de seguridad antes de hacer push
  • Limpiar y consolidar grandes conjuntos de changes generados por agentes
  • Ejecutar varios agentes en paralelo e integrar sus changes manteniendo limpio el historial
Conoce más sobre Juju-chu!