An open API service indexing awesome lists of open source software.

https://github.com/chardigio/pappardelle

A TUI for multi-clauding without losing your marbles
https://github.com/chardigio/pappardelle

agent-orchestration claude claude-code multi-claude multi-clauding tui

Last synced: 21 days ago
JSON representation

A TUI for multi-clauding without losing your marbles

Awesome Lists containing this project

README

          

# ๐Ÿฆ€๐Ÿ๐Ÿฆ€ Pappardelle ๐Ÿฆ€๐Ÿ๐Ÿฆ€

[![Test](https://github.com/chardigio/pappardelle/actions/workflows/test.yml/badge.svg)](https://github.com/chardigio/pappardelle/actions/workflows/test.yml)
[![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

A TUI for multi-clauding without losing your marbles.

You type a description, it reads or creates an issue in Linear/Jira, spawns a configured git worktree, builds a PR/MR, and starts a Claude Code session alongside a lazygit session โ€” all wired together in a 3-pane tmux layout you can navigate with simple, customizable keystrokes.

**Video:**

https://github.com/user-attachments/assets/abeaf413-5a1e-448a-ac53-2956a8ada5bf

---

## Table of Contents

1. [Installation and Getting Started](#1-installation-and-getting-started)
2. [Understanding tmux in Pappardelle](#2-understanding-tmux-in-pappardelle)
3. [Spawning New Sessions](#3-spawning-new-sessions)
4. [Spec-Driven Development Mindset](#4-spec-driven-development-mindset)
5. [Customizing Your Configuration](#5-customizing-your-configuration)
6. [Advanced: Doom-coding with Pappardelle](#6-advanced-doom-coding-with-pappardelle)
7. [Advanced: Wrangling Multi-Repo Changes](#7-advanced-wrangling-multi-repo-changes)
8. [Reference](#8-reference)

---

## 1. Installation and Getting Started

The fastest way to get set up is with `/init-pappardelle`.

Add the marketplace:

```bash
claude plugin marketplace add chardigio/pappardelle
```

Install the plugin. This installs four skills โ€” `/init-pappardelle` (setup wizard), `/update-pappardelle` (update to latest), `/configure-pappardelle` (interactive config editor), and `/sous-chef` (optional workspace coordinator):

```bash
claude plugin install pappardelle@pappardelle-marketplace
```

Run the setup wizard from any repo where you want to use Pappardelle. This installs pappardelle configures your .pappardelle.yml:

```bash
claude /init-pappardelle
```

For manual installation, see [Section 8: Reference](#8-reference). For the full config format, see the [configuration reference](pappardelle-config.md).

### Launch Pappardelle:

```bash
pappardelle
```

![Screenshot 2026-03-02 at 4.18.44โ€ฏPM](assets/Screenshot%202026-03-02%20at%204.18.44%E2%80%AFPM.png)

---

## 2. Understanding tmux in Pappardelle

### The 3-pane layout

When you launch `pappardelle`, it creates a tmux session with three panes:

- **Left pane** shows the ticket rail. This is where you navigate workspaces, create new ones, and trigger actions.
- **Center pane** shows the Claude Code session for whichever workspace is highlighted.
- **Right pane** shows [lazygit](https://github.com/jesseduffield/lazygit) for the highlighted workspace's worktree.

### How nested sessions work

Each workspace creates two independent tmux sessions:

- `claude-{repo}-{issue-key}` โ€” runs Claude Code
- `lazygit-{repo}-{issue-key}` โ€” runs lazygit

The center and right panes in the Pappardelle session are "viewers" โ€” they run nested tmux clients that attach to these independent sessions. When you highlight a different workspace in the list, Pappardelle uses `tmux switch-client` to instantly swap which session the viewer pane displays.

This means:

- **Workspaces are independent.** Each Claude session runs in its own tmux session. If Pappardelle crashes, your Claude sessions keep running.
- **Attach from anywhere.** You can attach to any workspace's Claude session from a separate terminal: `tmux attach -t claude-stardust-labs-STA-631`.
- **Switching is instant.** After the first attachment, switching between workspaces uses tmux's fast `switch-client` path โ€” no process restart, no visible flash.

### Recommended tmux config

Pappardelle works with any tmux configuration, but these settings improve the experience โ€” mouse support, Ctrl+Shift+arrow pane navigation, and a clean status bar. See [`examples/tmux.conf`](examples/tmux.conf) and append to your `~/.tmux.conf`. If you don't have one yet:

```bash
curl -fsSL https://raw.githubusercontent.com/chardigio/pappardelle/main/examples/tmux.conf -o ~/.tmux.conf
```

### Exiting Pappardelle

Press `q` in the workspace list pane to quit. This kills the Pappardelle tmux session and all its viewer panes, returning you to your original terminal. Your Claude and lazygit workspace sessions are **not** affected โ€” they run in independent tmux sessions and will keep going after Pappardelle exits. To reattach, just run `pappardelle` again.

To also kill all workspace sessions, use `Delete` on each workspace from the TUI before quitting, or nuke everything with:

```bash
tmux kill-server
```

---

## 3. Spawning New Sessions

### From the TUI

Press `n` in the workspace list to open the prompt dialog.

![New session dialog](assets/new-session-dialog.png)

### What gets provisioned

When you create a workspace, Pappardelle runs through these steps:

1. **Profile selection** โ€” Your input is keyword-matched against a profile in `.pappardelle.yml`.

2. **Issue creation/fetch** โ€” For new descriptions, a Linear (or Jira) issue is created with a WIP title. For existing issue keys, the issue is fetched.

3. **Git worktree** โ€” An isolated worktree is created at `~/.worktrees/{repo-name}/{issue-key}/`. This is a full working copy of your repo on a new branch, completely isolated from your main checkout.

4. **PR/MR creation** โ€” A placeholder PR (GitHub) or MR (GitLab) is created from the new branch.

5. **Project setup** โ€” Profile `commands` are executed (e.g., `xcodegen generate`, dependency installs). Top-level `post_workspace_init` commands also run after the worktree is created (e.g., copying `.env` files).

6. **Claude & lazygit sessions spawned** โ€” A named tmux session is created and Claude Code is launched inside it. If `claude.initialization_command` is set in `.pappardelle.yml` (e.g., `/do`), that command is passed to Claude along with the issue key. A lazygit session rooted at the worktree dir is also spawned.

---

## 4. Spec-Driven Development Mindset

![Spec-driven development in Linear](assets/spec-driven-development-linear.png)

Pappardelle's recommended `/do` skill (set via `claude.initialization_command` in `.pappardelle.yml`) starts every Claude session with a **planning-first workflow**. Before writing any code, the agent researches and uses Claude Code's `AskUserQuestion` tool to clarify requirements โ€” asking about ambiguous scope, confirming design decisions, and validating edge cases. The goal is to turn a rough prompt into a detailed, unambiguous spec โ€” **written back to the issue description** โ€” before the first line of code is written.

### Why this matters

A one-line prompt like "add dark mode to settings" leaves a lot of questions open: which settings screen? System preference or manual toggle? What colors? The `/do` skill instructs the agent to surface these questions upfront rather than guessing. This front-loaded clarification produces better code on the first pass and fewer revision cycles.

### Automatic Q&A documentation

Every `AskUserQuestion` exchange is automatically posted as a comment on the Linear or Jira issue by the [`comment-question-answered.py`](hooks/comment-question-answered.py) hook. This means:

- **The issue becomes the single source of truth.** The original prompt, every clarifying question, and every answer are all captured in one place โ€” not scattered across chat windows or terminal scrollback.
- **Anyone reviewing the PR can see the full context.** The issue thread shows exactly what the agent asked, what the developer decided, and why.
- **Record-keeping is automatic.** You don't need to manually document decisions or copy-paste from the terminal. The hook handles it silently in the background.

---

## 5. Customizing Your Configuration

Use `/configure-pappardelle` to interactively edit your config โ€” it walks you through adding profiles, keybindings, hooks, and more using `AskUserQuestion`. Available via the [plugin marketplace](#plugin-marketplace) or by asking Claude directly (it's model-invocable).

Pappardelle is configured via a `.pappardelle.yml` file at your repo root. The key concepts:

- **Issue watchlist** โ€” Auto-discover issues assigned to you and spawn workspaces for them. Pappardelle polls your issue tracker and creates workspaces for new matching issues. Filter by status, labels, or `key_prefixes` (e.g. watch `STA-*` but not `WAB-*` when one account spans multiple workspaces).
- **Auto-remove when done** โ€” Opt-in flag (`auto_remove_when_done: true`) that drops a space from the rail as soon as the tracker reports its issue as completed or canceled. Same teardown as pressing `d`; the on-disk worktree is left untouched.
- **Profiles** โ€” Per-project-type config (keywords, setup commands, VCS labels, optional `emoji:` shown in the ticket rail). Pappardelle keyword-matches your input to auto-select the right profile. Each profile's `tracker_projects` list both routes existing issues to the right profile and (Linear only) lands brand-new issues in `tracker_projects[0]`.
- **Template variables** โ€” All string values support `${VAR_NAME}` expansion (`${ISSUE_KEY}`, `${WORKTREE_PATH}`, `${PR_URL}`, profile `vars`, env vars, etc.).
- **Custom keybindings** โ€” Bind single keys to bash commands (`run`) or Claude directives (`send_to_claude`).
- **Providers** โ€” Pluggable issue trackers (Linear, Jira) and VCS hosts (GitHub, GitLab). Defaults to Linear + GitHub.
- **Built-in file copies** โ€” `.pappardelle.local.yml` and `.claude/settings.local.json` are automatically copied from the main repo to new worktrees (if they exist).
- **Workspace lifecycle hooks** โ€” `post_workspace_init` commands run after worktree creation (e.g., copying `.env` files, installing dependencies). `pre_workspace_deinit` commands run before workspace deletion (e.g., closing issues, removing worktrees).

For the full schema, all fields, and examples, see the [configuration reference](pappardelle-config.md).

For a production `.pappardelle.yml` used across a polyglot monorepo (Python backends + Swift iOS apps), see [`examples/monorepo-pappardelle.yml`](examples/monorepo-pappardelle.yml).

---

## 6. Advanced: Doom-coding with Pappardelle

**Video:**

https://github.com/user-attachments/assets/824307b7-73a6-48d2-918f-4a2d75fcb39b

Because Pappardelle runs entirely inside tmux, you can access your full workspace setup from anywhere โ€” all you need is an SSH connection to the machine running it.

### What you need

- **A machine that stays on** โ€” I'm not a Mac Mini guy (yet), I just keep my MacBook plugged in. macOS won't sleep with the lid closed as long as it has power and an active SSH session.
- **[Tailscale](https://tailscale.com/)** โ€” A mesh VPN that makes your dev machine accessible from any network without port forwarding or firewall configuration. Install on both your dev machine and your mobile device.
- **[Termius](https://termius.com/)** (iOS) โ€” A full-featured SSH client for iPhone and iPad with good tmux support, copy/paste, and keyboard shortcuts.

### Nice-to-haves

- **[ntfy](https://ntfy.sh/)** โ€” Push notifications to your phone when Claude needs input. Pappardelle ships with a [`zap-notification.py`](hooks/zap-notification.py) hook that sends a push via ntfy whenever Claude asks a question or hits a permission prompt. To get it working, set the `PAPPARDELLE_NTFY_TOPIC` environment variable and subscribe to the same topic in the ntfy app on your phone โ€” the hook only fires when an Tailscale SSH session is active. This way you don't have to babysit the terminal โ€” just wait for the buzz.
- **[Wispr Flow](https://apps.apple.com/us/app/wispr-flow-ai-voice-keyboard/id6497229487)** โ€” Voice-to-text dictation that works system-wide, including inside Termius. Lets you talk to Claude instead of thumb-typing on a phone keyboard.

### Recommended Termius keyboard shortcuts

Termius lets you customize the shortcut bar above the on-screen keyboard โ€” these are my favorite groups for Pappardelle:

![Termius keyboard shortcuts](assets/termius-keyboard-shortcuts.jpg)

- **Arrow keys** โ€” scroll through Claude output and navigate the workspace list
- **pgUp / pgDn** โ€” cycle between tmux panes (requires the `PageUp`/`PageDown` bindings from [`examples/tmux.conf`](examples/tmux.conf))
- **esc / ^C** โ€” cancel prompts, exit modes
- **paste / tab / ctrl / alt** โ€” general terminal essentials

Also recommended: toggle on **Settings > Hide the AI widget** in Termius for extra screen real estate.

### Useful keybindings

When you're doom-coding from your phone, you want one-tap access to open the PR on the device in your hand. Bind a key that sends an ntfy notification with a clickable link:

```yaml
keybindings:
- key: 'z'
name: 'Zap PR'
# Use `--search "head:${ISSUE_KEY}"` (tokenized prefix match) rather than
# `--head ${ISSUE_KEY}` (exact match) so follow-up branches like
# ${ISSUE_KEY}-FOLLOW-1 are also discoverable from the parent issue key.
# Sort by updatedAt desc โ€” when a branch name has been reused (e.g. an
# old merged PR + a freshly opened one), surface the PR you're actually
# working on, not the oldest stale match.
run: >
PR_JSON=$(gh pr list --search "head:${ISSUE_KEY}" --state all --json number,url,updatedAt
-q 'sort_by(.updatedAt) | reverse | .[0]' 2>/dev/null);
PR_NUM=$(echo "$PR_JSON" | jq -r '.number // empty');
PR_URL=$(echo "$PR_JSON" | jq -r '.url // empty');
if [ -n "$PR_NUM" ]; then
curl -d "${ISSUE_KEY} GitHub PR #$PR_NUM"
-H "Click: $PR_URL"
ntfy.sh/${PAPPARDELLE_NTFY_TOPIC};
fi
```

Press `z` on a workspace and your phone buzzes with a notification โ€” tap it and the PR opens in the GitHub app.

---

## 7. Advanced: Wrangling Multi-Repo Changes

Pappardelle is designed for single-repo workflows, but (experimentally) you can extend it to orchestrate changes across multiple repositories using a parent (pappa) repo.

### The setup

Create a parent repository that serves as the orchestration hub:

```
my-workspace/
โ”œโ”€โ”€ .pappardelle.yml
โ”œโ”€โ”€ .claude/
โ”‚ โ”œโ”€โ”€ settings.json # shared settings + plugins
โ”‚ โ””โ”€โ”€ skills/
โ”‚ โ”œโ”€โ”€ do/
โ”‚ โ”‚ โ””โ”€โ”€ SKILL.md # initialization skill
โ”‚ โ””โ”€โ”€ address-mr-feedbacks/
โ”‚ โ””โ”€โ”€ SKILL.md # orchestration skill
โ””โ”€โ”€ CLAUDE.md
```

The parent repo's primary purpose is to share settings, context, and orchestration skills to coordinate work across child repos. Child repos are **not** committed to the parent โ€” they're shallow-cloned on demand during workspace setup.

### Spawning agents in child repos

Multi-repo work has been an achilles heel for Claude Code in the past, but I'm hoping **[Agent Teams](https://code.claude.com/docs/en/agent-teams)** can help solve this. One key unlock with agent teams is that teammates can be spawned in _separate directories_, meaning we can have a parent repo, but then spawn an agent per relevant child repo, which is nice because it automatically loads that repo's CLAUDE.md, skills, settings, etc.

### On-demand shallow cloning

Repos are pulled down as needed, not upfront. During the planning phase, use a search tool like SourceBot's `codesearch` MCP to identify which repos are relevant, then shallow-clone only what you need:

```bash
git clone --depth 1 https://github.com/org/repo-a.git
```

This keeps initialization fast and reduces noise for the agent while it greps and globs. Because we use `--depth 1`, only the latest commit is fetched โ€” no full history.

### Plugin skills vs. parent repo skills

One key distinction for multi-repo work is between plugin skills and parent repo skills:

- **Plugin skills** (added in the parent repo's `settings.json` but defined elsewhere) are skills that can be used by any repo / agent teammate receives automatically. These handle single-repo concerns.

Example: An `/address-mr-feedback` plugin that lets any agent look at its own repo's MR and address reviewer comments.

- **Parent repo skills** (in the parent repo's `.claude/skills/`) are orchestration skills that spawn agent teams across child repos.

Example: An `/address-mr-feedbacks` (plural) skill that spins up an agent team, spawning one agent per relevant child repo โ€” each agent calls the plugin's singular skill for its own MR.

### Example `/do` skill for multi-repo

A starter `/do` skill tailored for multi-repo workflows is available at [`examples/skills/do-multi-repo/SKILL.md`](examples/skills/do-multi-repo/SKILL.md). It covers shallow cloning, agent team spin-up, per-repo QA, and coordinated PR creation. Install it into your parent repo with:

```bash
mkdir -p .claude/skills/do && curl -fsSL https://raw.githubusercontent.com/chardigio/pappardelle/main/examples/skills/do-multi-repo/SKILL.md -o .claude/skills/do/SKILL.md
```

### Useful keybindings

Bind keys to open specific child repos in your editor for quick navigation:

```yaml
keybindings:
- key: 's'
name: 'Open repo-a in Cursor'
run: 'open -a "Cursor" "${WORKTREE_PATH}/repo-a" 2>/dev/null || open -a "Cursor" "${REPO_ROOT}/repo-a"'
```

Note the fallback to `${REPO_ROOT}/repo-a` here ensures this shortcut works in the `master`/`main` space.

---

## 8. Reference

### Prerequisites

| Tool | Required | Install |
| ---------------------------------------------------------------------- | -------- | ------------------------------------------------------------------ |
| Node.js >= 18 | Yes | `brew install node` |
| npm | Yes | Comes with Node.js |
| git | Yes | `brew install git` |
| tmux | Yes | `brew install tmux` |
| jq | Yes | `brew install jq` |
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) | Yes | `curl -fsSL https://claude.ai/install.sh \| bash` |
| [linctl](https://github.com/raegislabs/linctl) | Optional | `brew tap raegislabs/linctl && brew install linctl` (for Linear) |
| [gh](https://cli.github.com/) | Optional | `brew install gh` (for GitHub) |
| [glab](https://gitlab.com/gitlab-org/cli) | Optional | `brew install glab` (for GitLab) |
| [acli](https://developer.atlassian.com/) | Optional | `brew tap atlassian/homebrew-acli && brew install acli` (for Jira) |

### Manual installation

If you prefer to install without the `/init-pappardelle` skill:

**One-line install:**

```bash
curl -fsSL https://raw.githubusercontent.com/chardigio/pappardelle/main/install.sh | bash
```

**From a local clone:**

```bash
git clone https://github.com/chardigio/pappardelle.git
cd pappardelle
./install.sh
```

**Manual install:**

```bash
git clone https://github.com/chardigio/pappardelle.git
cd pappardelle
npm install
npm run build
npm link # makes `pappardelle` available globally
./hooks/install.sh # installs Claude Code hooks for status tracking
```

**Directories created by the installer:**

| Directory / File | Purpose |
| -------------------------------------------------- | --------------------------------------------------------- |
| `~/.pappardelle/` | Config, hooks, logs, and Claude status files |
| `~/.pappardelle/repos/{repoName}/open-spaces.json` | Persisted workspace registry (per-repo, survives reboots) |
| `~/.pappardelle/repos/{repoName}/issue-meta/` | Issue metadata for hook tracking (per-repo) |
| `~/.pappardelle/claude-status/` | Real-time status JSON files from Claude hooks |
| `~/.pappardelle/logs/` | Daily log files (7-day retention) |
| `~/.worktrees/` | Git worktrees for all your workspaces |

> **Multi-repo support:** State is namespaced per repository under `~/.pappardelle/repos/{repoName}/`.
> Running pappardelle in two different repos keeps their workspace registries completely separate.
> On first run, existing state is automatically migrated from the legacy global location.

### Claude Code hooks

Pappardelle installs three Claude Code hooks that provide integration between Claude sessions and the TUI:

| Hook | Trigger | What it does |
| ------------------------------ | ----------------------------------- | ----------------------------------------------------------------------------- |
| `update-status.py` | `PreToolUse`, `PostToolUse`, `Stop` | Writes session status to `~/.pappardelle/claude-status/` for live TUI updates |
| `comment-question-answered.py` | `PostToolUse` (AskUserQuestion) | Posts Q&A exchanges as comments on the issue (Linear or Jira) |
| `zap-notification.py` | `PreToolUse`, `PermissionRequest` | Sends push notifications via ntfy when Claude needs user input |

### Versioning and updates

Pappardelle is versioned via git tags on `chardigio/pappardelle` (`vX.Y.Z`) โ€” `package.json` is not bumped on release. Every push to `main` cuts a new tag + GitHub Release via the `release` workflow. Bump type is driven by PR labels:

| Label | Effect |
| --------------- | -------------------- |
| `release:major` | `X.0.0` bump |
| `release:minor` | `x.Y.0` bump |
| `release:patch` | `x.y.Z` bump |
| _(no label)_ | patch bump (default) |

Two paths feed the release workflow:

- **Direct merge on `chardigio/pappardelle`** โ€” an external contributor opens a PR here and you merge it. The release workflow reads the `release:*` label on the chardigio-side PR directly.
- **Forward sync from `stardust-labs-io/stardust-labs`** โ€” rsync pushes straight to `main` with no PR on this side. The monorepo's sync workflow reads the merged _monorepo_ PR's `release:*` label and propagates it to the synced commit as a `Release-bump: ` trailer, which the release workflow here consumes.

On startup, the TUI checks the GitHub Releases API (cached for 24h at `~/.pappardelle/update-check.json`) and, if a newer tag is available, renders a magenta banner above the workspace list:

```
Update available: v0.1.0 โ†’ v0.2.0 ยท U to update ยท X to dismiss
```

The installed version is read from `git describe --tags --abbrev=0 --match 'v*.*.*'` on the install clone, with `package.json` as a fallback for the pre-release window. Press `U` to exit the TUI and re-run the install script in-place. Press `X` to dismiss the banner for the current session โ€” the next launch re-reads the cache.

When running out of the stardust-labs monorepo (LOCAL_MODE), the check is skipped entirely; the monorepo is the source of truth and must not be clobbered by `curl | bash`.

### Logging

Logs are written to `~/.pappardelle/logs/` with daily rotation (7-day retention):

```bash
# View today's log
cat ~/.pappardelle/logs/pappardelle-$(date +%Y-%m-%d).log

# Tail logs in real-time
tail -f ~/.pappardelle/logs/pappardelle-*.log

# View errors only
grep '\[ERROR\]' ~/.pappardelle/logs/*.log
```

Warnings and errors also appear in a red box at the bottom of the TUI. Press `e` to view them.

### Development

```bash
npm run dev # Watch mode (auto-rebuild on changes)
npm run build # Build once
npm start # Run without building
npm test # Lint + format check + tests
```

### Integration tests

Standalone scripts in `integration-tests/` verify providers against real instances. They are **not** ava tests and are never run in CI โ€” use them for local verification after making provider changes.

```bash
npx tsx integration-tests/verify-linear.ts # Linear provider (linctl)
npx tsx integration-tests/verify-jira.ts # Jira provider (acli)
npx tsx integration-tests/verify-github.ts # GitHub PR detection (gh)
npx tsx integration-tests/verify-gitlab.ts # GitLab MR detection (glab)
npx tsx integration-tests/verify-config.ts # Config loading + validation
npx tsx integration-tests/verify-watchlist.ts # Full watchlist pipeline end-to-end
npx tsx integration-tests/verify-comments.ts # Comment posting (creates real comments)
```

See [`integration-tests/README.md`](integration-tests/README.md) for env vars and prerequisites.

### Plugin Marketplace

Pappardelle ships a [Claude Code plugin marketplace](plugins/) with a single `pappardelle` plugin containing four skills:

| Skill | Description | Model-invocable |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- |
| `/init-pappardelle` | Interactive setup wizard โ€” installs Pappardelle, checks prerequisites, generates `.pappardelle.yml` | No |
| `/update-pappardelle` | Re-runs the install script to update Pappardelle to the latest version | No |
| `/configure-pappardelle` | Interactive config editor for `.pappardelle.yml` and `.pappardelle.local.yml` โ€” profiles, keybindings, hooks, watchlists, and more | Yes |
| `/sous-chef` | Kitchen-style coordinator โ€” quick overview of active spaces, drill into any space for a sitrep, relay instructions to running Claude sessions via tmux | No |

**Install the plugin:**

```bash
claude /plugin marketplace add chardigio/pappardelle
```

```bash
claude /plugin install pappardelle@pappardelle-marketplace
```

Because `/configure-pappardelle` is model-invocable, Claude will automatically offer to use it when you ask about configuring Pappardelle โ€” no need to invoke it explicitly.

### Dependencies

- [Ink](https://github.com/vadimdemedes/ink) โ€” React for CLIs
- [tmux](https://github.com/tmux/tmux) โ€” Terminal multiplexer
- [lazygit](https://github.com/jesseduffield/lazygit) โ€” Terminal git UI
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) โ€” AI coding assistant