From 2f111bcb7a78e7f9e03fc0490f36ce49da887263 Mon Sep 17 00:00:00 2001 From: Daniel Wise Date: Mon, 25 May 2026 15:19:25 -0700 Subject: [PATCH 1/3] docs(dub-84): refresh docs + website for post-March feature surface Coverage refresh after the May 23-25 feature burst (DUB-67/69/70 + tree-shaped stacks, MCP, AI providers, JSON output, multi-trunk, SQLite backend). - 14 new command pages: ai, config, mcp, init, install, flow, pr, history, status, watch, migrate, trunk, freeze, prune. - Fix stale mcp.mdx note about `dubstack.back` (shipped) and update guide table. - Replace single-level undo wording with multi-level undo/redo + 20-entry ring buffer across README, QUICKSTART, docs, skills, references. - Update homepage with tree-shaped stacks, Agents & MCP, Shell & IDE Integration, AI-across-the-flow messaging (6-card feature grid). - Refresh README + QUICKSTART for MCP, multi-trunk, SQLite, theming, JSON. - Tree-aware log.mdx with current-path highlighting and frozen markers. Completes DUB-84 --- .agents/skills/dubstack/SKILL.md | 2 +- .../skills/dubstack/references/commands.md | 6 +- .../skills/dubstack/references/workflows.md | 10 +- QUICKSTART.md | 36 ++++- README.md | 93 ++++++++++- apps/docs/content/docs/commands/ai.mdx | 110 +++++++++++++ apps/docs/content/docs/commands/config.mdx | 145 ++++++++++++++++++ apps/docs/content/docs/commands/create.mdx | 2 +- apps/docs/content/docs/commands/flow.mdx | 43 ++++++ apps/docs/content/docs/commands/freeze.mdx | 49 ++++++ apps/docs/content/docs/commands/history.mdx | 33 ++++ apps/docs/content/docs/commands/init.mdx | 32 ++++ apps/docs/content/docs/commands/install.mdx | 40 +++++ apps/docs/content/docs/commands/log.mdx | 27 +++- apps/docs/content/docs/commands/mcp.mdx | 34 ++++ apps/docs/content/docs/commands/meta.json | 14 ++ apps/docs/content/docs/commands/migrate.mdx | 35 +++++ apps/docs/content/docs/commands/pr.mdx | 22 +++ apps/docs/content/docs/commands/prune.mdx | 39 +++++ apps/docs/content/docs/commands/reorder.mdx | 2 +- apps/docs/content/docs/commands/status.mdx | 39 +++++ apps/docs/content/docs/commands/trunk.mdx | 70 +++++++++ apps/docs/content/docs/commands/watch.mdx | 33 ++++ .../docs/getting-started/quickstart.mdx | 2 +- .../docs/guides/conflict-resolution.mdx | 2 +- apps/docs/content/docs/guides/mcp.mdx | 4 +- .../content/docs/guides/stacking-workflow.mdx | 12 +- apps/docs/content/docs/index.mdx | 10 +- apps/docs/src/app/(home)/page.tsx | 40 +++-- skills/dubstack/SKILL.md | 2 +- skills/dubstack/references/commands.md | 6 +- skills/dubstack/references/workflows.md | 10 +- 32 files changed, 961 insertions(+), 43 deletions(-) create mode 100644 apps/docs/content/docs/commands/ai.mdx create mode 100644 apps/docs/content/docs/commands/config.mdx create mode 100644 apps/docs/content/docs/commands/flow.mdx create mode 100644 apps/docs/content/docs/commands/freeze.mdx create mode 100644 apps/docs/content/docs/commands/history.mdx create mode 100644 apps/docs/content/docs/commands/init.mdx create mode 100644 apps/docs/content/docs/commands/install.mdx create mode 100644 apps/docs/content/docs/commands/mcp.mdx create mode 100644 apps/docs/content/docs/commands/migrate.mdx create mode 100644 apps/docs/content/docs/commands/pr.mdx create mode 100644 apps/docs/content/docs/commands/prune.mdx create mode 100644 apps/docs/content/docs/commands/status.mdx create mode 100644 apps/docs/content/docs/commands/trunk.mdx create mode 100644 apps/docs/content/docs/commands/watch.mdx diff --git a/.agents/skills/dubstack/SKILL.md b/.agents/skills/dubstack/SKILL.md index 592506bb..2bfd1a1a 100644 --- a/.agents/skills/dubstack/SKILL.md +++ b/.agents/skills/dubstack/SKILL.md @@ -41,7 +41,7 @@ Use this skill whenever the user is working in a repo that uses `dub` for stacke | Show parent/children/trunk | `dub parent`, `dub children`, `dub trunk` | | Submit PR stack | `dub submit` / `dub ss` | | Open PR in browser | `dub pr [branch|number]` | -| Undo last create/restack | `dub undo` | +| Undo / redo | `dub undo` / `dub redo` (multi-level, 20-entry ring) | ## Command Notes diff --git a/.agents/skills/dubstack/references/commands.md b/.agents/skills/dubstack/references/commands.md index eff75f3d..f2ad359b 100644 --- a/.agents/skills/dubstack/references/commands.md +++ b/.agents/skills/dubstack/references/commands.md @@ -109,7 +109,11 @@ This is a concise command reference for agents using `dub`. | Command | Purpose | |---|---| -| `dub undo` | Undo last `create` or `restack` mutation | +| `dub undo` | Undo the most recent mutating `dub` command (multi-level; 20-entry ring at `.git/dubstack/undo-log.json`) | +| `dub undo --steps N` | Roll back the last `N` operations in sequence | +| `dub undo --list` | Show what's on the ring (newest first) | +| `dub redo` | Replay the most recently undone operation | +| `dub continue` / `dub abort` | Resume/cancel an interrupted restack or rebase | ## Skills Management diff --git a/.agents/skills/dubstack/references/workflows.md b/.agents/skills/dubstack/references/workflows.md index 6895e91a..f11ba038 100644 --- a/.agents/skills/dubstack/references/workflows.md +++ b/.agents/skills/dubstack/references/workflows.md @@ -132,12 +132,16 @@ dub pr 123 ## 8) Recover from Mistakes ```bash -dub undo +dub undo # undo most recent mutation +dub undo --steps 3 # roll back the last 3 +dub undo --list # inspect the ring +dub redo # replay the most recently undone op ``` Notes: -- `undo` supports one level. -- Intended for reverting last `create` or `restack`. +- `undo`/`redo` is multi-level (20-entry ring at `.git/dubstack/undo-log.json`). +- Covers `create`, `restack`, `move`, `reorder`, `absorb`, `unlink`, `rename`, `pop`, `modify`, `freeze`/`unfreeze`, `track`/`untrack`, `delete`, `sync`, `split`, and `submit` (PR body restore only — PR retargets and pushes are not reverted). +- A new mutating command clears the redo log. ## 9) Repair Untracked Branch Metadata diff --git a/QUICKSTART.md b/QUICKSTART.md index 7732f2de..da5c149c 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -368,13 +368,23 @@ dub stash list Useful when you start working on the wrong branch and want to move the changes elsewhere. -## 11) Undo Last Stack Mutation +## 11) Undo and Redo ```bash +# Undo the most recent mutating dub command dub undo + +# Roll back the last N operations +dub undo --steps 3 + +# Show what's on the ring (newest first) +dub undo --list + +# Replay the most recently undone operation +dub redo ``` -`dub undo` supports one level for `create` and `restack` operations. +`dub undo` is backed by a 20-entry ring buffer at `.git/dubstack/undo-log.json`. It reverses `create`, `restack`, `move`, `reorder`, `absorb`, `unlink`, `rename`, `pop`, `modify`, `freeze`/`unfreeze`, `track`/`untrack`, `delete`, `sync`, `split`, and `submit` (PR body restore only — PR retargeting and pushes are not reverted). Any new mutating command clears the redo log; until then `dub undo` ↔ `dub redo` cycle freely. ## Fast Command List @@ -401,7 +411,7 @@ dub undo | `dub delete` | Stack-aware branch deletion | | `dub freeze` / `dub unfreeze` | Set/clear the `frozen` flag; restack/sync/post-merge skip frozen branches | | `dub continue` / `dub abort` | Resume/cancel interrupted operations | -| `dub undo` | Undo last create/restack | +| `dub undo` / `dub redo` | Multi-level undo and redo (20-entry ring) | | `dub stash` / `dub stash pop` / `dub stash list` | Branch-aware stash (refuses pop on wrong branch) | | `dub config ai-assistant on` | Enable repo-local AI assistant | | `dub config ai-provider bedrock` | Pin the repo-local AI provider | @@ -410,6 +420,26 @@ dub undo | `dub flow --ai -a` | Stage, preview, create, and submit with AI | | `dub history` | Show recent Dub command history | +## Programmatic And Agent Use + +Every read-only command supports `--json`. Payloads carry `schemaVersion: 1` and a stable shape; failures emit `{ schemaVersion, error: { message, recovery } }` with non-zero exit. Covered: `log`, `info`, `branch info`, `status`, `doctor`, `history`, `parent`, `children`, `trunk`, `merge-check`, `ready`. + +For MCP-aware agents (Claude Code, Cursor): + +```bash +claude mcp add dubstack dub mcp +dub config mcp-mode interactive # read-only | interactive (default) | trusted +dub history # MCP calls are audited here +``` + +## Optional: Theming and Storage + +```bash +dub config theme dark # or: light, auto (default), none +dub config storage-backend sqlite # opt into SQLite for large stacks +dub migrate storage --to sqlite # copy state.json → SQLite +``` + ## Local AI Evals ```bash diff --git a/README.md b/README.md index 648e707f..9eacb05d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ If you have `gt` muscle memory, use this as a fast map: | `gt parent` | `dub parent` | | `gt children` | `dub children` | | `gt trunk` | `dub trunk` | -| `gt undo` | `dub undo` | +| `gt undo` | `dub undo` (multi-level; pair with `dub redo`) | ## Quick Start @@ -747,14 +747,36 @@ dub unfreeze feat/auth-login `dub log` marks frozen branches with 🔒 and `dub doctor` lists them as an informational notice. Freeze wins over destructive maintenance flags: if a branch is frozen, unfreeze it explicitly before using `dub sync --force` or any other branch-mutating maintenance. -### `dub undo` +### `dub undo` / `dub redo` -Undo the last `dub create`, `dub restack`, `dub rename`, `dub move`, `dub pop`, `dub freeze`, or `dub unfreeze` operation. +Multi-level undo and redo backed by a 20-entry ring buffer at +`.git/dubstack/undo-log.json`. Reversal coverage includes `create`, +`restack`, `move`, `reorder`, `absorb`, `unlink`, `rename`, `pop`, `modify`, +`freeze`/`unfreeze`, `track`/`untrack`, `delete`, `sync`, `split`, and +`submit` (PR body restore only — PR retargets and pushes are not reverted). ```bash +# Undo the most recent mutating dub command dub undo + +# Roll back the last N operations +dub undo --steps 3 + +# Show what's on the ring (newest first) +dub undo --list + +# Wipe both undo and redo logs +dub undo --clear + +# Replay the most recently undone operation +dub redo ``` +A new mutating command **clears** the redo log; until then `dub undo` ↔ +`dub redo` cycle freely. If part of an undo can't fully succeed (a branch +was force-pushed, GitHub rejected a PR body update, etc.) DubStack undoes +what it can and prints `⚠ …` warnings with manual recovery hints. + ### `dub completion ` and `dub man` Generate shell completions and a man page from the live commander definitions. @@ -1073,6 +1095,69 @@ recovery } }` with a non-zero exit code. Covered commands: `log`, `info`, [Programmatic use guide](https://dubstack.dev/docs/guides/json-output) for the full schema reference. +### `dub mcp` (Model Context Protocol) + +Expose DubStack to MCP-aware agents (Claude Code, Cursor, etc.) so they +can drive the stack without shelling out to free-form commands. + +```bash +claude mcp add dubstack dub mcp +``` + +Mutating tools are gated by repo-local mode: + +```bash +dub config mcp-mode read-only # disable mutating tools entirely +dub config mcp-mode interactive # terminal confirmation (default) +dub config mcp-mode trusted # allow mutating tools without prompts +``` + +Every MCP tool invocation — success, refusal, or failure — is appended to +`dub history` with redacted args and a `args_sha256` fingerprint. See the +[MCP server guide](https://dubstack.dev/docs/guides/mcp) for the tool list +and security model. + +### Multi-trunk repositories + +Repositories with multiple long-lived trunks (e.g. `main` plus a release +branch) can register additional trunks. DubStack records which trunk each +stack tracks and the default trunk used by `dub create` at the root. + +```bash +dub trunk list # show configured trunks +dub trunk add release/24.04 # register an additional trunk +dub trunk set-default release/24.04 +dub trunk remove release/24.04 +``` + +`dub doctor` surfaces orphaned trunks (branches that lost their tracked +trunk after a rename or deletion) and walks you through reattachment. + +### Storage backend (SQLite) + +DubStack state defaults to `.git/dubstack/state.json`. Repositories with +very large stacks can opt into a SQLite backend for faster reads. + +```bash +dub config storage-backend # show +dub config storage-backend sqlite # switch backend (does not migrate data) +dub migrate storage --to sqlite # copy state.json → SQLite +dub migrate storage --to json # copy SQLite → state.json +``` + +### Terminal theming + +```bash +dub config theme # show +dub config theme auto # auto-detect light/dark from COLORFGBG (default) +dub config theme dark +dub config theme light +dub config theme none # equivalent to --no-color globally +``` + +`--no-color` on any invocation overrides the configured theme for that +run. Affects `log`, `status`, `sync`, and any other colorized output. + ## Typical Workflows ### Add review feedback to a middle branch @@ -1143,7 +1228,7 @@ dub restack --continue | Need metadata-only removal | Use `dub untrack` (or `--downstack`) | | Need stack-aware branch deletion | Use `dub delete` with `--upstack` / `--downstack` | | Sync skipped branch | Re-run with `--interactive` or `--force` as appropriate | -| Wrong operation during create/restack/move | Use `dub undo` (single-level) | +| Wrong operation during create/restack/move | Use `dub undo` (multi-level; `dub redo` to replay) | | PR merge blocked by order or GitHub conflict | Run `dub merge-check --pr ` to verify stack order and remote mergeability | | Manual merge left stack inconsistent | Run `dub post-merge` | diff --git a/apps/docs/content/docs/commands/ai.mdx b/apps/docs/content/docs/commands/ai.mdx new file mode 100644 index 00000000..8e65e6f0 --- /dev/null +++ b/apps/docs/content/docs/commands/ai.mdx @@ -0,0 +1,110 @@ +--- +title: dub ai +description: AI assistant utilities — provider setup, prompts, env vars, and conflict resolution. +--- + +## Usage + +```bash +# Guided provider + model setup (interactive) +dub ai setup + +# Ask the assistant a question +dub ai ask "what changed in this stack?" + +# Or use the implicit shortcut from the root command +dub "summarize the diff on this branch" + +# Write provider settings into your shell profile +dub ai env --anthropic-key sk-... +dub ai env --gemini-key ... --gemini-model gemini-2.5-pro +dub ai env --ollama-base-url http://localhost:11434 --ollama-model qwen2.5-coder + +# AI-assisted conflict resolution during a rebase/restack +dub ai resolve +dub ai resolve --dry-run +dub ai resolve --adjudicate +``` + +## Subcommands + +### `dub ai setup` + +Interactive provider + model picker. Prompts for the provider, a model +(or a custom model ID), and where to store the model (global shell profile +or repo-local `.git/dubstack/config.json`). Writes the chosen provider env +vars to your shell profile and updates `ai-provider` (and, for repo scope, +`ai-model`) in repo-local config. + +### `dub ai ask ` + +Send a prompt to the configured AI provider. Requires the assistant to be +enabled with `dub config ai-assistant on`. The assistant has read-only bash +access to the repo for context gathering — destructive commands are +sandboxed out. + +### `dub ai env` + +Write provider keys, model overrides, and Bedrock/Ollama settings into your +shell profile (`.zshrc`, `.bashrc`/`.bash_profile`, or `.profile`). + +| Flag | Env var written | +|---|---| +| `--gemini-key ` | `DUBSTACK_GEMINI_API_KEY` | +| `--anthropic-key ` | `DUBSTACK_ANTHROPIC_API_KEY` | +| `--gateway-key ` | `DUBSTACK_AI_GATEWAY_API_KEY` | +| `--openai-key ` | `DUBSTACK_OPENAI_API_KEY` | +| `--ollama-base-url ` | `DUBSTACK_OLLAMA_BASE_URL` | +| `--gemini-model ` | `DUBSTACK_GEMINI_MODEL` | +| `--anthropic-model ` | `DUBSTACK_ANTHROPIC_MODEL` | +| `--gateway-model ` | `DUBSTACK_AI_GATEWAY_MODEL` | +| `--openai-model ` | `DUBSTACK_OPENAI_MODEL` | +| `--ollama-model ` | `DUBSTACK_OLLAMA_MODEL` | +| `--bedrock-profile ` | `DUBSTACK_BEDROCK_AWS_PROFILE` | +| `--bedrock-region ` | `DUBSTACK_BEDROCK_AWS_REGION` | +| `--bedrock-model ` | `DUBSTACK_BEDROCK_MODEL` | +| `--profile ` | Override target profile path | +| `--shell ` | Force shell detection (`zsh` or `bash`) | + +At least one key, model, or Bedrock setting must be passed. + +### `dub ai resolve` + +AI-assisted conflict resolver for in-progress rebase/restack operations. +Reads the conflict markers, asks the configured provider for resolutions, +and previews them before applying. After applying, it tries `dub continue`; +on test failures or new conflicts it retries once with feedback. + +| Flag | Description | +|---|---| +| `--dry-run` | Show proposed resolutions without applying | +| `--abort` | Abort the active rebase/restack operation | +| `--adjudicate` | Resolve with two configured providers and reconcile disagreements | +| `--no-adjudicate` | Force single-provider mode | + +When two providers are configured, adjudication runs by default. With +`--adjudicate`, both providers propose resolutions; matching outputs apply +automatically with `high` confidence, and disagreements prompt for which +side to take (or `skip`/`abort`). Disagreements are also written to +`.git/dubstack/ai-eval-bank/*.json` for later evaluation. + +`--dry-run` shows both providers' answers for disagreement files and the +first provider's pick is recorded as the dry-run choice. + +## Providers + +| Provider | Required env (or other) | +|---|---| +| Gemini | `DUBSTACK_GEMINI_API_KEY` | +| Vercel AI Gateway | `DUBSTACK_AI_GATEWAY_API_KEY` | +| Amazon Bedrock | `DUBSTACK_BEDROCK_AWS_PROFILE`, `DUBSTACK_BEDROCK_AWS_REGION` | +| Anthropic | `DUBSTACK_ANTHROPIC_API_KEY` | +| OpenAI | `DUBSTACK_OPENAI_API_KEY` | +| Ollama (and LM Studio) | `DUBSTACK_OLLAMA_BASE_URL` (default `http://localhost:11434`) | + +Provider selection is repo-local — `dub config ai-provider ` (or +`auto` to pick based on which env vars are set). Per-provider model +overrides live in repo config (`dub config ai-model --provider

`) +or in `DUBSTACK__MODEL` env vars. + +See also: `dub config ai-assistant`, `dub config ai-provider`, `dub config ai-model`, `dub flow`. diff --git a/apps/docs/content/docs/commands/config.mdx b/apps/docs/content/docs/commands/config.mdx new file mode 100644 index 00000000..91a90bff --- /dev/null +++ b/apps/docs/content/docs/commands/config.mdx @@ -0,0 +1,145 @@ +--- +title: dub config +description: Manage repo-local DubStack configuration (AI, reviewers, storage, theme). +--- + +## Usage + +```bash +dub config theme dark +dub config ai-assistant on +dub config reviewers alice,bob +dub config storage-backend sqlite +dub config submit-default draft +``` + +Config lives in `.git/dubstack/config.json` and is repo-local. Most +subcommands accept no argument to print the current value, or a value to +set it. + +## `ai-assistant` + +Enable or disable the repo-local AI assistant. + +```bash +dub config ai-assistant # show +dub config ai-assistant on +dub config ai-assistant off +``` + +## `ai-provider` + +Pick the active AI provider for this repo. + +```bash +dub config ai-provider # show +dub config ai-provider auto # pick based on configured env keys +dub config ai-provider anthropic +dub config ai-provider gemini +dub config ai-provider gateway +dub config ai-provider bedrock +dub config ai-provider openai +dub config ai-provider ollama +``` + +## `ai-model` + +Set or clear a repo-local model override per provider. + +```bash +dub config ai-model --provider anthropic claude-sonnet-4-7 +dub config ai-model --provider gemini gemini-2.5-pro +dub config ai-model --provider openai --clear +``` + +| Flag | Description | +|---|---| +| `--provider ` | Required. One of `gemini`, `anthropic`, `gateway`, `bedrock`, `openai`, `ollama` | +| `--clear` | Clear the repo-local override (falls back to env var or default) | + +## `ai-defaults` + +Toggle AI-on-by-default for `create`, `submit`, and `flow`. When enabled, +running the command without `--ai`/`--no-ai` uses AI; pass `--no-ai` to +opt out for one invocation. + +```bash +dub config ai-defaults create # show +dub config ai-defaults create on +dub config ai-defaults submit on +dub config ai-defaults flow on +``` + +## `ai-prompts` + +Control whether interactive prompts surface AI choices. + +```bash +dub config ai-prompts auto # show AI choices when the assistant is enabled +dub config ai-prompts on # always offer AI choices +dub config ai-prompts off # never offer AI choices +``` + +## `ai-prompts-auto-accept` + +Control how AI recommendations in prompts are accepted. + +```bash +dub config ai-prompts-auto-accept off # always confirm +dub config ai-prompts-auto-accept high # auto-apply high-confidence picks +``` + +## `submit-default` + +Default PR lifecycle for `dub submit`. + +```bash +dub config submit-default # show +dub config submit-default auto # draft when .github/workflows/ has workflows +dub config submit-default draft # open new PRs as drafts +dub config submit-default publish # promote existing draft PRs by default +``` + +## `reviewers` + +Manage repo-default PR reviewers used by `dub submit`. + +```bash +dub config reviewers # show +dub config reviewers alice,@org/backend # set +dub config reviewers --clear # remove +``` + +## `mcp-mode` + +Security model for mutating MCP tool calls (used by `dub mcp`). + +```bash +dub config mcp-mode read-only # disable mutating tools entirely +dub config mcp-mode interactive # terminal confirmation (default) +dub config mcp-mode trusted # allow mutating tools without prompts +``` + +## `storage-backend` + +State storage backend. + +```bash +dub config storage-backend # show +dub config storage-backend json # JSON state.json (default) +dub config storage-backend sqlite # SQLite-backed state +``` + +Use `dub migrate storage --to ` to copy state when switching. + +## `theme` + +Terminal color theme used by `log`, `status`, and `sync` output. + +```bash +dub config theme # show +dub config theme auto # auto-detect light/dark from COLORFGBG (default) +dub config theme dark +dub config theme light +dub config theme none # equivalent to --no-color globally +``` diff --git a/apps/docs/content/docs/commands/create.mdx b/apps/docs/content/docs/commands/create.mdx index 3731bebf..7b8a9d1b 100644 --- a/apps/docs/content/docs/commands/create.mdx +++ b/apps/docs/content/docs/commands/create.mdx @@ -72,4 +72,4 @@ git config commit.template .gitmessage - `dub create` auto-initializes DubStack state if needed. - The new branch is always stacked on the current branch. -- Use `dub undo` to revert the last create operation. +- Use `dub undo` to revert the most recent create (multi-level via the 20-entry ring buffer; `dub redo` replays). diff --git a/apps/docs/content/docs/commands/flow.mdx b/apps/docs/content/docs/commands/flow.mdx new file mode 100644 index 00000000..964c761e --- /dev/null +++ b/apps/docs/content/docs/commands/flow.mdx @@ -0,0 +1,43 @@ +--- +title: dub flow +description: Stage, preview, create, and submit an AI-assisted DubStack change in one shot. +--- + +## Usage + +```bash +# Stage all, preview AI metadata, create branch + commit, submit +dub flow --ai -a + +# Same, but auto-approve generated metadata +dub flow -y -u + +# Preview generated branch, commit, and PR text only +dub flow --dry-run + +# Alias +dub f --ai +``` + +## Flags + +| Flag | Description | +|---|---| +| `-a, --all` | Stage all changes before generating metadata | +| `-u, --update` | Stage tracked file changes before generating metadata | +| `-p, --patch` | Pick hunks to stage before generating metadata | +| `-y, --yes` | Auto-approve generated metadata without prompting | +| `-i, --ai` | Force AI flow for this invocation | +| `--no-ai` | Disable AI flow for this invocation | +| `--dry-run` | Preview generated metadata without creating or submitting | + +**Alias:** `dub f` + +## Notes + +- AI mode requires `dub config ai-assistant on` plus a configured provider + (`dub ai setup` or `dub ai env`). +- The `flow` AI default can be set repo-wide with `dub config ai-defaults flow on`. +- `--ai` and `--no-ai` are mutually exclusive overrides for a single run. + +See also: `dub create`, `dub submit`, `dub ai setup`. diff --git a/apps/docs/content/docs/commands/freeze.mdx b/apps/docs/content/docs/commands/freeze.mdx new file mode 100644 index 00000000..56da4bb3 --- /dev/null +++ b/apps/docs/content/docs/commands/freeze.mdx @@ -0,0 +1,49 @@ +--- +title: dub freeze / dub unfreeze +description: Freeze tracked branches so restack/sync/post-merge skip them. +--- + +## Usage + +```bash +# Freeze the current branch +dub freeze + +# Freeze a specific tracked branch +dub freeze feat/auth-login + +# Freeze a branch and its ancestors toward trunk +dub freeze feat/auth-login --downstack + +# Freeze the current branch and all descendants +dub freeze --upstack + +# Preview the plan without mutating +dub freeze --dry-run + +# Reverse with unfreeze +dub unfreeze +dub unfreeze feat/auth-login --upstack +dub unfreeze --dry-run +``` + +## Flags + +| Flag | Description | +|---|---| +| `--downstack` | Also freeze (or unfreeze) ancestors toward trunk | +| `--upstack` | Also freeze (or unfreeze) descendants | +| `--dry-run` | Print the planned change without mutating state | +| `--json` | Pair with `--dry-run` to emit the plan as JSON | + +## Notes + +- Freezing sets the `frozen` flag on the branch's tracked state. While + set, `dub restack`, `dub sync`, and `dub post-merge` skip the branch + instead of rebasing it. +- `dub doctor` surfaces frozen branches so they don't silently fall behind + the rest of the stack. +- The change is to state only — no git refs are touched by `freeze` or + `unfreeze` themselves. + +See also: `dub restack`, `dub sync`, `dub doctor`. diff --git a/apps/docs/content/docs/commands/history.mdx b/apps/docs/content/docs/commands/history.mdx new file mode 100644 index 00000000..df8a6bc7 --- /dev/null +++ b/apps/docs/content/docs/commands/history.mdx @@ -0,0 +1,33 @@ +--- +title: dub history +description: Show recent DubStack command history. +--- + +## Usage + +```bash +# Show the 20 most recent dub commands +dub history + +# Show the last 50 entries +dub history -n 50 + +# Emit JSON for downstream tooling +dub history --json +``` + +## Flags + +| Flag | Description | +|---|---| +| `-n, --limit ` | Number of history entries to show (default: 20) | +| `--json` | Output history as JSON | + +## Notes + +- Each entry records the command, its status (`success` or failure), and + the timestamp. Sensitive-looking arguments are redacted. +- The same history backs the audit log surfaced by MCP tools, giving AI + agents read-only visibility into recent operations on the stack. + +See also: `dub status`, `dub doctor`. diff --git a/apps/docs/content/docs/commands/init.mdx b/apps/docs/content/docs/commands/init.mdx new file mode 100644 index 00000000..4b592cf1 --- /dev/null +++ b/apps/docs/content/docs/commands/init.mdx @@ -0,0 +1,32 @@ +--- +title: dub init +description: Initialize DubStack in the current git repository. +--- + +## Usage + +```bash +# Create .git/dubstack/ and update .gitignore +dub init + +# Rebuild state.json from refs/dubstack/* (recovery) +dub init --restore-from-refs +``` + +`dub init` is idempotent — safe to run again on a repo that's already initialized. +It creates an empty `state.json` under `.git/dubstack/` and ensures `.git/dubstack` is +listed in the repo `.gitignore`. + +## Flags + +| Flag | Description | +|---|---| +| `--restore-from-refs` | Rebuild `.git/dubstack/state.json` from `refs/dubstack/*` | + +## Notes + +- Fails with a clear DubStack error if the current directory is not inside a git repo. +- The `--restore-from-refs` mode recovers stack state after a `.git/dubstack/` wipe, + using the per-branch refs DubStack writes alongside its state file. + +See also: `dub install`, `dub config`, `dub doctor`. diff --git a/apps/docs/content/docs/commands/install.mdx b/apps/docs/content/docs/commands/install.mdx new file mode 100644 index 00000000..17c9c625 --- /dev/null +++ b/apps/docs/content/docs/commands/install.mdx @@ -0,0 +1,40 @@ +--- +title: dub install +description: Install a DubStack recipe (workflow templates, etc.) into the current repo. +--- + +## Usage + +```bash +# Install the retarget-action GitHub workflow +dub install retarget-action + +# Preview the planned write without touching disk +dub install retarget-action --dry-run + +# Overwrite an existing file with different content without confirming +dub install retarget-action --force +``` + +## Flags + +| Flag | Description | +|---|---| +| `--dry-run` | Print the planned write without touching disk | +| `--force` | Overwrite an existing file with different content without confirming | + +## Recipes + +| Recipe | Writes | +|---|---| +| `retarget-action` | `.github/workflows/dubstack-retarget.yml` — GitHub Action that retargets dependent PRs when a stack PR merges | + +## Notes + +- If the target file already exists with different content, `dub install` prompts + for confirmation in an interactive TTY. In non-interactive shells it refuses to + prompt and prints a hint — re-run with `--force` to overwrite or `--dry-run` to preview. +- If the file already exists with identical content, the command reports + `already installed` and makes no changes. +- After installing `retarget-action`, commit and push the workflow file. The + Action runs on the next merge. diff --git a/apps/docs/content/docs/commands/log.mdx b/apps/docs/content/docs/commands/log.mdx index ee66b3fb..036080e9 100644 --- a/apps/docs/content/docs/commands/log.mdx +++ b/apps/docs/content/docs/commands/log.mdx @@ -1,6 +1,6 @@ --- title: dub log -description: Visualize your stack as an ASCII tree. +description: Visualize your stack as an ASCII tree, tree-aware with current-path highlighting and PR/CI annotations. --- ## Usage @@ -34,9 +34,22 @@ dub log --json **Aliases:** `dub ls`, `dub l` +## Tree-shaped stacks + +`dub log` renders the full tracked tree, not just a linear chain. On +tree-shaped stacks: + +- The current branch's ancestor path is shown in **bold**. +- Sibling sub-trees are dimmed so the focus stays on the current path. +- The current branch is highlighted in bright cyan. +- Frozen branches (see `dub freeze`) are marked so it's clear why + `restack`/`sync`/`post-merge` skipped them. +- PR/CI/commit annotations come from a 30-second cached batch `gh pr list`, + so re-running `dub log` is cheap. + ## Example Output -A typical stack looks like this: +A typical linear stack: ```text (main) @@ -45,6 +58,16 @@ A typical stack looks like this: └─ feat/auth-tests ← you are here ``` +A tree-shaped stack: + +```text +(main) + └─ feat/auth-types + ├─ feat/auth-login ← you are here + │ └─ feat/auth-tests + └─ feat/auth-google +``` + ## Branch Info For detailed metadata about a specific branch: diff --git a/apps/docs/content/docs/commands/mcp.mdx b/apps/docs/content/docs/commands/mcp.mdx new file mode 100644 index 00000000..22b52194 --- /dev/null +++ b/apps/docs/content/docs/commands/mcp.mdx @@ -0,0 +1,34 @@ +--- +title: dub mcp +description: Start the DubStack MCP server over stdio for AI agents. +--- + +## Usage + +```bash +# Speak Model Context Protocol over stdio (run from an AI agent host) +dub mcp +``` + +`dub mcp` exposes DubStack commands as MCP tools so AI coding agents can +inspect and operate on the stack. The full tool list, request/response +shape, and security model are documented in the +[MCP guide](/docs/guides/mcp). + +## Security mode + +Mutating MCP tools are gated by `dub config mcp-mode`: + +```bash +# Disable mutating tools entirely (read-only) +dub config mcp-mode read-only + +# Require terminal confirmation for mutating tools (default) +dub config mcp-mode interactive + +# Allow mutating tools to run without prompts +dub config mcp-mode trusted +``` + +See the [MCP guide](/docs/guides/mcp) for the tool inventory and best +practices for each mode. diff --git a/apps/docs/content/docs/commands/meta.json b/apps/docs/content/docs/commands/meta.json index 52c48ff7..3ab07597 100644 --- a/apps/docs/content/docs/commands/meta.json +++ b/apps/docs/content/docs/commands/meta.json @@ -3,6 +3,12 @@ "pages": [ "docs", "repo", + "init", + "install", + "config", + "ai", + "mcp", + "flow", "create", "modify", "squash", @@ -11,11 +17,16 @@ "back", "log", "navigate", + "status", + "watch", + "history", "submit", + "pr", "sync", "restack", "split", "merge-next", + "prune", "post-merge", "fold", "move", @@ -26,6 +37,9 @@ "doctor", "ready", "track", + "freeze", + "trunk", + "migrate", "rename", "revert", "stash", diff --git a/apps/docs/content/docs/commands/migrate.mdx b/apps/docs/content/docs/commands/migrate.mdx new file mode 100644 index 00000000..7e0016c8 --- /dev/null +++ b/apps/docs/content/docs/commands/migrate.mdx @@ -0,0 +1,35 @@ +--- +title: dub migrate +description: Migrate DubStack repo-local data between storage formats. +--- + +## Usage + +```bash +# Move state.json into state.sqlite (and opt the repo into the SQLite backend) +dub migrate storage --to sqlite + +# Move state.sqlite back to state.json +dub migrate storage --to json +``` + +## `dub migrate storage` + +Copy DubStack state across storage backends and switch +`storage-backend` config to the destination. + +| Flag | Description | +|---|---| +| `--to ` | Required. Destination backend: `json` or `sqlite` | + +## Notes + +- The copy is performed first; the config flip only happens if the copy + succeeds. Running it when the destination already matches the current + backend is a no-op (with a warning). +- The summary line reports how many stacks and branches were migrated. +- Storage backend can also be toggled directly with + `dub config storage-backend `, but `dub migrate storage` is the + safe path because it preserves existing state. + +See also: `dub config storage-backend`, `dub init`. diff --git a/apps/docs/content/docs/commands/pr.mdx b/apps/docs/content/docs/commands/pr.mdx new file mode 100644 index 00000000..c3f24e91 --- /dev/null +++ b/apps/docs/content/docs/commands/pr.mdx @@ -0,0 +1,22 @@ +--- +title: dub pr +description: Open a branch PR in your browser. +--- + +## Usage + +```bash +# Open the PR for the current branch +dub pr + +# Open the PR for a specific branch +dub pr feat/auth-login + +# Open a PR by number +dub pr 123 +``` + +The argument can be either a branch name or a PR number; both are resolved +through `gh` and opened in your default browser. + +See also: `dub submit`, `dub repo`, `dub status`. diff --git a/apps/docs/content/docs/commands/prune.mdx b/apps/docs/content/docs/commands/prune.mdx new file mode 100644 index 00000000..4bc0ffa5 --- /dev/null +++ b/apps/docs/content/docs/commands/prune.mdx @@ -0,0 +1,39 @@ +--- +title: dub prune +description: Preview or remove stale tracked branches from DubStack metadata. +--- + +## Usage + +```bash +# Preview stale tracked branches (no changes) +dub prune + +# Apply the prune and remove stale metadata +dub prune --apply + +# Scan every tracked stack across trunks +dub prune --all + +# Skip the remote fetch (offline / fast path) +dub prune --no-fetch +``` + +## Flags + +| Flag | Description | +|---|---| +| `--apply` | Apply pruning changes (default is preview only) | +| `-a, --all` | Prune stale tracked branches across all stacks | +| `--no-fetch` | Skip remote fetch before pruning checks | + +## Notes + +- Stale branches are those whose local and/or remote ref is gone but whose + tracked metadata still lives in `.git/dubstack/state.json`. The output + reports the reason and whether the branch still has a local or remote + ref. +- Preview mode (the default) prints each stale entry and a hint to re-run + with `--apply`. + +See also: `dub doctor`, `dub untrack`, `dub delete`. diff --git a/apps/docs/content/docs/commands/reorder.mdx b/apps/docs/content/docs/commands/reorder.mdx index 13649188..eb2b86c1 100644 --- a/apps/docs/content/docs/commands/reorder.mdx +++ b/apps/docs/content/docs/commands/reorder.mdx @@ -104,4 +104,4 @@ dub undo - `dub modify` — edit, amend, or pop the latest commit. - `dub restack` — rebase descendants after a parent moves. - `dub move` — relocate a branch within its stack (not commits). -- `dub undo` — roll back the last create/restack/move/rename/reorder. +- `dub undo` / `dub redo` — multi-level undo and redo of mutating commands (20-entry ring). diff --git a/apps/docs/content/docs/commands/status.mdx b/apps/docs/content/docs/commands/status.mdx new file mode 100644 index 00000000..b608452a --- /dev/null +++ b/apps/docs/content/docs/commands/status.mdx @@ -0,0 +1,39 @@ +--- +title: dub status +description: One-line status snapshot for the current branch — designed for shell prompts and IDE integrations. +--- + +## Usage + +```bash +# One-line status (cache-only, fast) +dub status + +# Structured JSON for IDE/prompt integrations +dub status --json + +# Refresh PR/CI data via gh (bypass cache) +dub status --live + +# Skip the PR fetch for fast prompts without gh +dub status --no-pr +``` + +## Flags + +| Flag | Description | +|---|---| +| `--json` | Output the status snapshot as JSON | +| `--live` | Bypass the overview cache and hit `gh` fresh | +| `--no-pr` | Skip PR fetch (for fast prompts without `gh`) | + +## Notes + +- The plain-text form is one short line — safe to embed in a shell prompt. +- The JSON form is versioned (`schemaVersion: 1`) so editor extensions and + prompt tools can depend on the shape. +- The default path uses a 30-second cached overview of PR/CI state. Use + `--live` only when you specifically need fresh data; the cached path is + what makes the command prompt-fast. + +See also: `dub log`, `dub doctor`, `dub watch`. diff --git a/apps/docs/content/docs/commands/trunk.mdx b/apps/docs/content/docs/commands/trunk.mdx new file mode 100644 index 00000000..115b803f --- /dev/null +++ b/apps/docs/content/docs/commands/trunk.mdx @@ -0,0 +1,70 @@ +--- +title: dub trunk +description: Show or manage configured trunk branches for multi-trunk repos. +--- + +## Usage + +```bash +# Show the trunk for the current stack +dub trunk + +# Show the trunk for a specific branch +dub trunk feat/auth-login + +# Emit trunk info as JSON +dub trunk --json +``` + +## Flags + +| Flag | Description | +|---|---| +| `--json` | Output trunk info as JSON | + +## Subcommands + +### `dub trunk list` + +List every configured trunk, with the default marked. + +```bash +dub trunk list +``` + +### `dub trunk add ` + +Register an additional trunk branch (e.g. a release line). + +```bash +dub trunk add main +dub trunk add release/24.x +``` + +### `dub trunk remove ` + +Unregister a configured trunk. + +```bash +dub trunk remove release/24.x +``` + +### `dub trunk set-default ` + +Set the trunk used for new untracked stacks. + +```bash +dub trunk set-default main +dub trunk set-default release/24.x +``` + +## Notes + +- Multi-trunk repos let DubStack track stacks against multiple long-lived + branches (e.g. `main` plus release lines). Each stack records its trunk + in `.git/dubstack/state.json`. +- `dub trunk` with no subcommand prints the trunk for the inspected + branch — defaulting to the current branch — which makes it useful in + shell prompts and scripts. + +See also: `dub sync --all`, `dub status`, `dub log`. diff --git a/apps/docs/content/docs/commands/watch.mdx b/apps/docs/content/docs/commands/watch.mdx new file mode 100644 index 00000000..12adacb5 --- /dev/null +++ b/apps/docs/content/docs/commands/watch.mdx @@ -0,0 +1,33 @@ +--- +title: dub watch +description: Long-lived monitor that polls GitHub and watches .git for stack-state changes. +--- + +## Usage + +```bash +# Default 60s poll interval +dub watch + +# Custom interval (e.g. 30s, 2m) +dub watch --interval 30s + +# Render the live TUI status pane +dub watch --ui +``` + +## Flags + +| Flag | Description | +|---|---| +| `--interval ` | Poll interval — duration like `30s`, `2m` (default `60s`) | +| `--ui` | Render the live TUI status pane | + +## Notes + +- `dub watch` polls GitHub for PR and CI status changes and watches the + `.git` directory for stack-state changes (checkouts, restacks, submits). +- It is intended to run as a long-lived process in a terminal pane or + editor sidecar; exit with Ctrl-C. + +See also: `dub status`, `dub log`, `dub sync`. diff --git a/apps/docs/content/docs/getting-started/quickstart.mdx b/apps/docs/content/docs/getting-started/quickstart.mdx index 72b3b5ae..ee21df81 100644 --- a/apps/docs/content/docs/getting-started/quickstart.mdx +++ b/apps/docs/content/docs/getting-started/quickstart.mdx @@ -195,6 +195,6 @@ the direct merge path. | `dub restack` | Rebase stack onto updated parents | | `dub merge-next` | Merge next safe PR + maintenance | | `dub continue` / `dub abort` | Resume/cancel operations | -| `dub undo` | Undo last create/restack | +| `dub undo` / `dub redo` | Multi-level undo and redo (20-entry ring) | | `dub ai ask "..."` | Ask AI assistant | | `dub flow --ai -a` | Run the AI-assisted authoring flow | diff --git a/apps/docs/content/docs/guides/conflict-resolution.mdx b/apps/docs/content/docs/guides/conflict-resolution.mdx index fe8ed640..88074ea4 100644 --- a/apps/docs/content/docs/guides/conflict-resolution.mdx +++ b/apps/docs/content/docs/guides/conflict-resolution.mdx @@ -18,7 +18,7 @@ Common issues and how to resolve them. | Need metadata-only removal | Use `dub untrack` (or `--downstack`) | | Need stack-aware branch deletion | Use `dub delete` with `--upstack` / `--downstack` | | Sync skipped branch | Re-run with `--interactive` or `--force` as appropriate | -| Wrong operation during create/restack | Use `dub undo` (single-level) | +| Wrong operation during create/restack | Use `dub undo` (multi-level; pair with `dub redo` to replay) | | PR merge blocked by order | Run `dub merge-check --pr ` and merge previous PR first | | Manual merge left stack inconsistent | Run `dub post-merge` | diff --git a/apps/docs/content/docs/guides/mcp.mdx b/apps/docs/content/docs/guides/mcp.mdx index 7f67c7ef..b5b1372c 100644 --- a/apps/docs/content/docs/guides/mcp.mdx +++ b/apps/docs/content/docs/guides/mcp.mdx @@ -58,6 +58,7 @@ state, or GitHub. They are available in every MCP mode when the repo has | `dubstack.submit` | Push the current path or stack and create/update GitHub PRs | | `dubstack.sync` | Sync tracked branches with the remote and reconcile divergence | | `dubstack.checkout` | Switch to a tracked branch (stack-aware) | +| `dubstack.back` | Return to a previously checked-out branch (`steps` optional) | | `dubstack.delete` | Delete a local branch and update DubStack metadata | | `dubstack.reorder` | Reorder or drop commits on the current tracked branch from a supplied todo | | `dubstack.freeze` | Mark a branch or stack scope as frozen | @@ -76,9 +77,6 @@ state, or GitHub. They are available in every MCP mode when the repo has Mutating tools are gated by the configured **MCP mode** (see below). -The Tier 3 command family is still landing incrementally. `dubstack.back` will -be added to the MCP surface when its underlying CLI command lands. - ## Return shapes Read-only and AI-cooperative tools return JSON as both MCP text content and diff --git a/apps/docs/content/docs/guides/stacking-workflow.mdx b/apps/docs/content/docs/guides/stacking-workflow.mdx index fd1cf536..79d5a5a1 100644 --- a/apps/docs/content/docs/guides/stacking-workflow.mdx +++ b/apps/docs/content/docs/guides/stacking-workflow.mdx @@ -87,11 +87,19 @@ dub pr 123 ## 6. Recover from Mistakes ```bash +# Undo the most recent mutating dub command dub undo + +# Undo multiple steps in sequence +dub undo --steps 3 + +# Replay the most recently undone op +dub redo ``` -- `undo` supports one level. -- Intended for reverting last `create` or `restack`. +- `undo`/`redo` is multi-level, backed by a 20-entry ring buffer at `.git/dubstack/undo-log.json`. +- Covers `create`, `restack`, `move`, `reorder`, `absorb`, `unlink`, `rename`, `pop`, `modify`, `freeze`/`unfreeze`, `track`/`untrack`, `delete`, `sync`, `split`, and `submit` (PR body restore only). +- See [Recovery](/docs/commands/undo) for the full operation table and limitations. ## 7. Repair Untracked Branch Metadata diff --git a/apps/docs/content/docs/index.mdx b/apps/docs/content/docs/index.mdx index 89adad5b..2f116bb6 100644 --- a/apps/docs/content/docs/index.mdx +++ b/apps/docs/content/docs/index.mdx @@ -3,7 +3,13 @@ title: Introduction description: DubStack is a CLI for stacked diffs — dependent git branches that make code review faster and more focused. --- -DubStack is a CLI tool for managing stacked diffs — dependent git branches that make code review faster and more focused. It stores all state locally in `.git/dubstack/`, uses GitHub PRs directly via the `gh` CLI, and includes built-in AI assistance for stack-aware guidance, branch naming, commit messages, PR descriptions, and end-to-end flow previews. +DubStack is a CLI tool for managing **tree-shaped stacks** of dependent git branches that make code review faster and more focused. It stores all state locally in `.git/dubstack/` (with an optional SQLite backend for large stacks), uses GitHub PRs directly via the `gh` CLI, and includes: + +- **AI across the flow** — pluggable providers (Anthropic, Gemini, OpenAI, Bedrock, Ollama, Vercel AI Gateway) for branch names, commit messages, PR descriptions, conflict resolution, and stack-aware Q&A. +- **Agent integration** — every read command emits `--json` with `schemaVersion: 1`, and a built-in `dub mcp` server exposes stack tools to MCP-aware agents under a per-repo security model. +- **Safe merges and retargeting** — `dub merge-next` picks the next safe PR, `dub post-merge` repairs metadata after manual merges, and the [`wiseiodev/dubstack-retarget`](https://github.com/wiseiodev/dubstack-retarget) GitHub Action retargets dependent PR bases automatically. +- **Multi-level undo & redo** — every mutating command is recorded in a 20-entry ring buffer; `dub undo`/`dub redo` step freely until the next new mutation. +- **Shell and IDE integration** — `dub status` for prompts, `dub completion ` for shell completions, `dub man` for a generated man page, themable terminal output. ## Prerequisites @@ -162,6 +168,6 @@ dub flow --ai -a | `dub restack` | Rebase stack onto updated parents | | `dub merge-next` | Merge next safe PR + maintenance | | `dub continue` / `dub abort` | Resume/cancel operations | -| `dub undo` | Undo last create/restack | +| `dub undo` / `dub redo` | Multi-level undo and redo (20-entry ring) | | `dub ai ask "..."` | Ask AI assistant | | `dub flow --ai -a` | Stage, preview, create, and submit with AI | diff --git a/apps/docs/src/app/(home)/page.tsx b/apps/docs/src/app/(home)/page.tsx index dea2081b..e2428521 100644 --- a/apps/docs/src/app/(home)/page.tsx +++ b/apps/docs/src/app/(home)/page.tsx @@ -1,7 +1,9 @@ import { ArrowRight, + Bot, GitBranch, Layers, + Network, RefreshCw, Sparkles, Terminal, @@ -11,27 +13,39 @@ import Link from 'next/link'; const features = [ { icon: Layers, - title: 'Stacked Branches', + title: 'Tree-Shaped Stacks', description: - 'Split work into focused, dependent layers. Each branch builds on the one below, keeping PRs small and reviewable.', + 'Split work into focused layers — linear or branching. DubStack tracks the full stack tree and renders the current path in your terminal.', }, { icon: RefreshCw, - title: 'Auto Restack', + title: 'Safe Restack & Merge', description: - 'When a lower branch changes, dub restack propagates it upstack. Conflict recovery is built in with dub continue and dub abort.', + 'Restack propagates parent changes upstack. merge-next picks the next safe PR, post-merge cleans up retargets, and undo/redo is multi-level.', + }, + { + icon: Sparkles, + title: 'AI Across The Flow', + description: + 'Pluggable providers (Anthropic, Gemini, OpenAI, Bedrock, Ollama, AI Gateway) generate branch names, commit bodies, PR descriptions, and resolve restack conflicts.', + }, + { + icon: Bot, + title: 'Agents & MCP', + description: + 'Every read command emits JSON with schemaVersion: 1. The built-in MCP server exposes stack tools to Claude Code, Cursor, and any MCP-aware agent with a per-repo security model.', }, { icon: Terminal, - title: 'Graphite Compatible', + title: 'Shell & IDE Integration', description: - 'If you have gt muscle memory, DubStack maps 1:1. Same mental model, same workflow patterns, fully local-first.', + 'dub status drives prompts. dub completion + dub man emit shell completions and a man page from live commander metadata. Theming follows your terminal.', }, { - icon: Sparkles, - title: 'AI Powered', + icon: Network, + title: 'Graphite-Compatible', description: - 'AI-generate branch names and commit messages from staged changes. Ask the built-in assistant for stack-aware guidance.', + 'If you have gt muscle memory, DubStack maps 1:1. Local-first state under .git/dubstack, optional SQLite backend for large stacks, and a GitHub Action that retargets stacks after merges.', }, ]; @@ -51,9 +65,9 @@ export default function HomePage() { without the friction

- DubStack makes stacked branch workflows fast and safe. Create - dependent branches, restack automatically, and submit entire PR - stacks in one command. + A local-first CLI for tree-shaped stacked branches. Create dependent + layers, restack safely, submit entire stacks, and drive it all from + your shell, IDE, or an MCP-aware agent.

@@ -92,7 +106,7 @@ export default function HomePage() {
           Everything you need to manage dependent branches, from creation to
           merge.
         

-
+
{features.map((feature) => (
Date: Mon, 25 May 2026 15:30:17 -0700 Subject: [PATCH 2/3] docs(dub-84): apply second-pass review fixes - sqlite-backend.mdx: fix inspect example to drop the value (read form is `dub config storage-backend` without an argument). - state-management.mdx, conflict-resolution.mdx, README.md: rename `undo.json` to `undo-log.json` (the actual file name; source: lib/undo-log.ts:89). - unlink.mdx, move.mdx: add `text` language tag to ASCII tree code fences. - history.mdx: use `--limit 50` long form in primary example to match README and the flag table. - .claude/agents/code-reviewer.md, .agents/patterns/command-changes.md: refresh stale "undo is single-level" rule to describe the shipped multi-level ring buffer + redo contract. Refs DUB-84 --- .agents/patterns/command-changes.md | 2 +- .claude/agents/code-reviewer.md | 2 +- README.md | 2 +- apps/docs/content/docs/commands/history.mdx | 2 +- apps/docs/content/docs/commands/move.mdx | 4 ++-- apps/docs/content/docs/commands/unlink.mdx | 4 ++-- apps/docs/content/docs/concepts/state-management.mdx | 2 +- apps/docs/content/docs/guides/conflict-resolution.mdx | 2 +- apps/docs/content/docs/guides/sqlite-backend.mdx | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.agents/patterns/command-changes.md b/.agents/patterns/command-changes.md index bdfe4f0c..8cc71597 100644 --- a/.agents/patterns/command-changes.md +++ b/.agents/patterns/command-changes.md @@ -16,7 +16,7 @@ Use this pattern when modifying files under `src/commands/*`. - Ensure stack context is validated before mutating state. - Preserve submit linearity constraints during submit workflows. -- Keep undo behavior single-level unless a scoped change explicitly expands it. +- Preserve the multi-level `undo`/`redo` ring buffer contract (20 entries, mutating commands save before mutation, new mutations clear the redo log); don't shrink coverage without a scoped change. ## 4) Test Nearby diff --git a/.claude/agents/code-reviewer.md b/.claude/agents/code-reviewer.md index 8c2cd6dd..d78f8fde 100644 --- a/.claude/agents/code-reviewer.md +++ b/.claude/agents/code-reviewer.md @@ -47,7 +47,7 @@ Apply these principles from the code-principles skill. Read the reference files - `create` must auto-initialize state via `ensureState(...)` — never assume state exists - `restack` and `submit` must fail clearly when stack context is invalid - `submit` scope flags (`--upstack`/`--downstack`/`--stack`/`--branch`) are mutually exclusive; tree stacks are supported. Legacy `--path` emits a deprecation warning. -- `undo` is single-level only — don't silently extend it +- `undo`/`redo` is multi-level (20-entry ring at `.git/dubstack/undo-log.json`); mutating commands save an entry before mutation, and a new mutation clears the redo log - Error messages are UX and tested — change them deliberately, update tests - Keep command files thin, push logic to `src/lib/*` - ESM imports, 2-space indent, single quotes, kebab-case files diff --git a/README.md b/README.md index 9eacb05d..b56fec32 100644 --- a/README.md +++ b/README.md @@ -1260,7 +1260,7 @@ DubStack stores local state in your repo: ```text .git/dubstack/ ├── state.json -├── undo.json +├── undo-log.json └── restack-progress.json ``` diff --git a/apps/docs/content/docs/commands/history.mdx b/apps/docs/content/docs/commands/history.mdx index df8a6bc7..5dfbd0d1 100644 --- a/apps/docs/content/docs/commands/history.mdx +++ b/apps/docs/content/docs/commands/history.mdx @@ -10,7 +10,7 @@ description: Show recent DubStack command history. dub history # Show the last 50 entries -dub history -n 50 +dub history --limit 50 # Emit JSON for downstream tooling dub history --json diff --git a/apps/docs/content/docs/commands/move.mdx b/apps/docs/content/docs/commands/move.mdx index 6cad2db3..e36812ab 100644 --- a/apps/docs/content/docs/commands/move.mdx +++ b/apps/docs/content/docs/commands/move.mdx @@ -25,7 +25,7 @@ dub move --after ### `--before` -``` +```text Before: After (dub move feat/inserted --before feat/auth-login): main main └─ feat/auth-base └─ feat/auth-base @@ -39,7 +39,7 @@ main main target with multiple children turns into a true insert-between rather than a sibling split. -``` +```text Before: After (dub move feat/inserted --after feat/base): main main └─ feat/base └─ feat/base diff --git a/apps/docs/content/docs/commands/unlink.mdx b/apps/docs/content/docs/commands/unlink.mdx index 0a2de0c5..1401121c 100644 --- a/apps/docs/content/docs/commands/unlink.mdx +++ b/apps/docs/content/docs/commands/unlink.mdx @@ -28,7 +28,7 @@ dub unlink --no-retarget ### Default (`--keep-children`) -``` +```text Before: After (dub unlink feat/auth-login): main main └─ feat/auth-base └─ feat/auth-base @@ -42,7 +42,7 @@ retargeted from `feat/auth-base` to `main` via `gh pr edit`. ### `--orphan-children` -``` +```text Before: After (dub unlink feat/auth-login --orphan-children): main main └─ feat/auth-base └─ feat/auth-base diff --git a/apps/docs/content/docs/concepts/state-management.mdx b/apps/docs/content/docs/concepts/state-management.mdx index fb118af4..b3bbf717 100644 --- a/apps/docs/content/docs/concepts/state-management.mdx +++ b/apps/docs/content/docs/concepts/state-management.mdx @@ -9,7 +9,7 @@ DubStack stores all state locally in your repository under `.git/dubstack/`. - **`state.json`** — Branch tracking relationships (parent/child graph) - **`state.sqlite`** — Optional SQLite-backed branch tracking state for large repositories -- **`undo.json`** — State snapshot for undo operations +- **`undo-log.json`** — Multi-level undo/redo ring buffer (20 entries) - **`restack-progress.json`** — In-progress rebase/restack state for recovery `state.json` is the default. See [SQLite Backend](/docs/guides/sqlite-backend) to opt in to SQLite storage. diff --git a/apps/docs/content/docs/guides/conflict-resolution.mdx b/apps/docs/content/docs/guides/conflict-resolution.mdx index 88074ea4..8276e418 100644 --- a/apps/docs/content/docs/guides/conflict-resolution.mdx +++ b/apps/docs/content/docs/guides/conflict-resolution.mdx @@ -50,6 +50,6 @@ DubStack stores local state in your repo. Nothing is pushed to your remote from ```text .git/dubstack/ ├── state.json -├── undo.json +├── undo-log.json └── restack-progress.json ``` diff --git a/apps/docs/content/docs/guides/sqlite-backend.mdx b/apps/docs/content/docs/guides/sqlite-backend.mdx index cd170481..8936a36d 100644 --- a/apps/docs/content/docs/guides/sqlite-backend.mdx +++ b/apps/docs/content/docs/guides/sqlite-backend.mdx @@ -15,7 +15,7 @@ The migration copies the current JSON state into `.git/dubstack/state.sqlite` an You can inspect the selected backend afterward with: ```bash -dub config storage-backend sqlite +dub config storage-backend ``` ## When To Use It From d586ad22127f5e42cd9b44bb5a6e0670ccd7c347 Mon Sep 17 00:00:00 2001 From: Daniel Wise Date: Mon, 25 May 2026 15:34:17 -0700 Subject: [PATCH 3/3] docs(dub-84): add redo-log.json to state file listings Copilot review on PR #110 flagged that README and conflict-resolution still listed the legacy `undo.json`. The earlier review-fix commit renamed it to `undo-log.json`; this commit also adds the `redo-log.json` companion file (see `packages/cli/src/lib/undo-log.ts:94`) so readers don't go looking for the redo ring under a different name. Refs DUB-84 --- README.md | 1 + apps/docs/content/docs/concepts/state-management.mdx | 3 ++- apps/docs/content/docs/guides/conflict-resolution.mdx | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b56fec32..671922dc 100644 --- a/README.md +++ b/README.md @@ -1261,6 +1261,7 @@ DubStack stores local state in your repo: .git/dubstack/ ├── state.json ├── undo-log.json +├── redo-log.json └── restack-progress.json ``` diff --git a/apps/docs/content/docs/concepts/state-management.mdx b/apps/docs/content/docs/concepts/state-management.mdx index b3bbf717..1a0445bd 100644 --- a/apps/docs/content/docs/concepts/state-management.mdx +++ b/apps/docs/content/docs/concepts/state-management.mdx @@ -9,7 +9,8 @@ DubStack stores all state locally in your repository under `.git/dubstack/`. - **`state.json`** — Branch tracking relationships (parent/child graph) - **`state.sqlite`** — Optional SQLite-backed branch tracking state for large repositories -- **`undo-log.json`** — Multi-level undo/redo ring buffer (20 entries) +- **`undo-log.json`** — Multi-level undo ring buffer (20 entries) +- **`redo-log.json`** — Redo ring populated when `dub undo` runs; cleared on the next new mutation - **`restack-progress.json`** — In-progress rebase/restack state for recovery `state.json` is the default. See [SQLite Backend](/docs/guides/sqlite-backend) to opt in to SQLite storage. diff --git a/apps/docs/content/docs/guides/conflict-resolution.mdx b/apps/docs/content/docs/guides/conflict-resolution.mdx index 8276e418..4110059e 100644 --- a/apps/docs/content/docs/guides/conflict-resolution.mdx +++ b/apps/docs/content/docs/guides/conflict-resolution.mdx @@ -51,5 +51,6 @@ DubStack stores local state in your repo. Nothing is pushed to your remote from .git/dubstack/ ├── state.json ├── undo-log.json +├── redo-log.json └── restack-progress.json ```