---
name: renri
description: Manage parallel work across git worktrees and jujutsu workspaces with the `renri` CLI. Use this when the user wants to create / list / switch / remove worktrees, fan out parallel agent sessions, or clean up stale workspace entries.
---

# renri

`renri` (連理) is a single CLI for managing both **git worktrees** and
**jj workspaces**. It auto-detects the backend, dispatches to the right
one, and exposes one verb set.

## Verbs

- `renri add <name>` — create a new worktree (git) or workspace (jj).
  For git, `<name>` becomes a new branch off HEAD; for jj, a bookmark
  attached to the new workspace's working-copy commit. If `<name>`
  matches an existing branch / bookmark, attaches to it instead.
  **If `<name>` is omitted**, prompts interactively unless
  `--non-interactive` is set.

- `renri list` (alias `ls`) — show all worktrees with name, path,
  branch, and flags (main, bare, locked, stale).

- `renri cd <name>` — print the absolute path of a worktree on stdout.
  Designed to be wrapped: `cd "$(renri cd foo)"`. The shell wrapper
  generated by `renri shell-init <bash|zsh|fish|powershell>` does this
  automatically. **If `<name>` is omitted**, opens a fuzzy picker.

- `renri remove <name>` (alias `rm`) — remove a worktree (git) or
  forget a workspace (jj) and delete its directory. Refuses to
  remove the main worktree. Runs configured `pre_remove` hooks first.
  **If `<name>` is omitted**, opens a fuzzy picker.

- `renri exec <name> -- <command...>` — run a command inside the
  named worktree, streaming stdio. **If `<name>` is omitted**, opens
  a fuzzy picker.

- `renri prune` — clean up stale entries: for git, removes worktree
  metadata for deleted directories; for jj, forgets workspaces whose
  root path is gone (the missing `jj workspace prune` analog).

- `renri config show` — print the resolved configuration, the
  computed worktree path for the current branch, and the list of
  config sources.

- `renri shell-init <bash|zsh|fish|powershell>` — emit a shell snippet
  that makes `renri cd` actually change the parent shell's directory.

## Global flags

- `--vcs git|jj` — force a backend instead of auto-detecting.
  Auto-detection picks jj for colocated repos.
- `--non-interactive` — disable the interactive picker fallback. Use
  in scripts and CI; missing required arguments become errors.

## Configuration

Config lives at `<repo>/renri.toml` and (optionally)
`<config_dir>/renri/config.toml`, both loaded via the
[teravars](https://github.com/yukimemi/teravars) library so they
support:

- `include = ["base.toml"]` — pull in another config file.
- `{% if system.os == "windows" %}` / `{% if system.host == "..." %}` —
  per-OS / per-host overrides via Tera control flow.
- `{{ env(name='HOME') }}`, `{{ system.cwd }}`, etc. — standard
  helpers from teravars.

Layout templates have access to `vcs.{owner, repo, branch, host}`
which renri populates from the origin remote and the working-copy
state at use time.

Hooks are typed: `type = "copy" | "symlink" | "command"`. See
README.md for the full schema.

## Common workflows

**Spinning up a worktree for a Claude session:**
```sh
renri add feature/auth
renri cd feature/auth        # with shell-init wrapper, this cds
claude                       # work in the new worktree
```

**Per-host worktree root** (laptop vs desktop):
```toml
# renri.toml
[layout]
{% if system.host == "thinkpad" %}
worktree_root = "/home/yuki/wt"
{% elif system.os == "windows" %}
worktree_root = "C:/wt"
{% else %}
worktree_root = "{{ env(name='HOME') }}/wt"
{% endif %}
```

**Cleaning up after `rm -rf`-ing worktree directories:**
```sh
renri prune
```
