-
Notifications
You must be signed in to change notification settings - Fork 0
feat(cli): theming + per-command help expansion + migration guides + lazy AI imports #109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
dubscode
merged 3 commits into
main
from
feature/dub-69-theming-per-command-help-expansion-migration-guides
May 25, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
apps/docs/content/docs/guides/migration-from-charcoal.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| --- | ||
| title: Migrating from Charcoal | ||
| description: Map Charcoal (`gt`) commands to DubStack equivalents and migrate an active stack in under 30 minutes. | ||
| --- | ||
|
|
||
| [Charcoal](https://github.com/danerwilliams/charcoal) is the community-maintained fork of Graphite's CLI that ships under the same `gt` binary. If you have `gt` muscle memory, this guide is the fast path to DubStack — the mental model is identical, and most command names map one-to-one. | ||
|
|
||
| If you are migrating from Graphite proper (the SaaS-backed `gt`), the [Graphite migration guide](/docs/guides/migration-from-graphite) covers the same surface plus the cloud-features wind-down. | ||
|
|
||
| ## Command Mapping | ||
|
|
||
| | Charcoal | DubStack | Notes | | ||
| |---|---|---| | ||
| | `gt create` / `gt c` | `dub create` | Same flags: `-a`, `-m`, `--ai` | | ||
| | `gt modify` / `gt m` | `dub modify` / `dub m` | Amend HEAD and restack descendants | | ||
| | `gt submit` / `gt s` | `dub submit` / `dub ss` | Defaults to downstack; pass `--stack` for the full tree | | ||
| | `gt sync` | `dub sync` | `--all` covers every tracked stack | | ||
| | `gt checkout` / `gt co` | `dub checkout` / `dub co` | Interactive picker with no argument | | ||
| | `gt log` / `gt ls` | `dub log` / `dub ls` | `--stack`, `--all`, `--json` | | ||
| | `gt up` / `gt down` | `dub up` / `dub down` | Identical | | ||
| | `gt top` / `gt bottom` | `dub top` / `dub bottom` | Identical | | ||
| | `gt info` | `dub info` | `--json` available | | ||
| | `gt pr` | `dub pr` | Opens GitHub PR for the current branch | | ||
| | `gt restack` | `dub restack` | Run after `git rebase` to fix up children | | ||
| | `gt continue` | `dub continue` | `--ai` to resolve conflicts via LLM | | ||
| | `gt abort` | `dub abort` | Restack/rebase rollback | | ||
| | `gt track` / `gt trunk` | `dub track` / `dub trunk` | Multi-trunk supported | | ||
| | `gt untrack` | `dub untrack` | Keep the branch, drop metadata | | ||
| | `gt delete` | `dub delete` | `--upstack`/`--downstack`/`--force` | | ||
| | `gt absorb` | `dub absorb` | `--ai` for ambiguous fixups | | ||
| | `gt fold` | `dub fold` | `--squash` for single-commit collapse | | ||
| | `gt undo` | `dub undo` | 20-entry ring buffer + `dub redo` | | ||
|
|
||
| Charcoal inherits Graphite's CLI surface, so anything in the [Graphite mapping](/docs/guides/migration-from-graphite#command-mapping) that is not listed above maps the same way to DubStack. | ||
|
|
||
| ## Conceptual Differences | ||
|
|
||
| - **Local-first by design.** DubStack stores everything in `.git/dubstack/`. No external service, no telemetry, no shared cache file. | ||
| - **State mirrored into git refs.** `refs/dubstack/*` lets you rebuild state on a fresh clone with `dub init --restore-from-refs`. Charcoal relies on its own cache files and is sensitive to manual file deletion. | ||
| - **Optional AI throughout.** `dub create --ai`, `dub submit --ai`, `dub flow`, `dub absorb --ai`. Configured per-repo with `dub config ai-provider` and friends; none of it is required to use the stacked-diff workflow. | ||
| - **Safe merge order.** `dub merge-next` (alias `dub land`) refuses to merge a PR whose ancestors are open and retargets every child PR atomically. | ||
| - **Multi-trunk support.** Register additional trunks with `dub trunk add` and `dub trunk set-default`. | ||
| - **GitHub Action for retargeting.** `dub install retarget-action` drops a workflow that retargets dependents when a stack PR merges through the GitHub UI. | ||
|
|
||
| ## Common Pitfalls | ||
|
|
||
| - **`gt submit` defaulted to the full stack; `dub submit` defaults to downstack.** Pass `--stack` explicitly in CI scripts. | ||
| - **Charcoal's local config is not migrated.** Re-run `dub config ai-provider`, `dub config reviewers`, and `dub config submit-default`. | ||
| - **`gt downstack edit` has no direct equivalent.** Use `dub reorder` for interactive reordering or `dub move --before/--after` for one-shot moves. | ||
| - **`gt sync --pull` is implicit.** `dub sync` fetches the trunk by default; pass `--fresh` to force a full refetch. | ||
|
|
||
| ## 30-Minute Migration Script | ||
|
|
||
| ```bash | ||
| # 1. Install DubStack | ||
| npm install -g dubstack | ||
|
|
||
| # 2. Initialize alongside Charcoal — non-destructive | ||
| cd path/to/repo | ||
| dub init | ||
|
|
||
| # 3. Adopt every Charcoal branch. DubStack walks ancestry to infer parents. | ||
| for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do | ||
| if [ "$branch" != "main" ]; then | ||
| git switch "$branch" | ||
| dub track --no-interactive || true | ||
| fi | ||
| done | ||
|
|
||
| # 4. Verify the tree matches what Charcoal showed | ||
| dub log --all | ||
|
|
||
| # 5. (Optional) restore AI configuration | ||
| dub config ai-assistant on | ||
| dub config ai-provider anthropic | ||
| dub config ai-model --provider anthropic claude-sonnet-4-7 | ||
|
|
||
| # 6. (Optional) reviewers | ||
| dub config reviewers alice,@org/backend | ||
|
|
||
| # 7. Restack to confirm the chain is intact | ||
| dub restack | ||
|
|
||
| # 8. Refresh PR descriptions with DubStack metadata | ||
| dub submit --downstack --no-ai | ||
|
|
||
| # 9. Once stable, remove Charcoal. (The exact uninstall depends on how you | ||
| # installed it — Homebrew tap, source build, or volta-managed npm bin.) | ||
| # Then remove the per-repo cache. Charcoal inherits Graphite's file names: | ||
| rm -rf .graphite_cache_persist .graphite_repo_config 2>/dev/null || true | ||
| # (If your Charcoal fork renamed these, check the fork's docs for its actual | ||
| # cache path before deleting.) | ||
| ``` | ||
|
|
||
| If `dub log --all` differs from `gt log`, run `dub doctor` to diagnose. State is recoverable via `dub init --restore-from-refs`. | ||
|
|
||
| ## See Also | ||
|
|
||
| - [Stacking Workflow](/docs/guides/stacking-workflow) | ||
| - [Conflict Resolution](/docs/guides/conflict-resolution) | ||
| - [GitHub Action: retarget](/docs/guides/github-action-retarget) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| --- | ||
| title: Migrating from ghstack | ||
| description: Move from Meta's ghstack workflow (`ghstack`) to DubStack without re-creating any branches. | ||
| --- | ||
|
|
||
| [ghstack](https://github.com/ezyang/ghstack) implements stacked diffs on top of GitHub by treating one local commit per PR and synthesising orphan `gh/<user>/<n>/{base,head,orig}` branches on push. DubStack takes the opposite approach: every PR has its own branch in your local checkout, mirroring how you work in `git switch`. | ||
|
|
||
| This guide explains the model shift and walks through migrating an in-flight ghstack series in roughly 30 minutes. | ||
|
|
||
| ## Command Mapping | ||
|
|
||
| | ghstack | DubStack | Notes | | ||
| |---|---|---| | ||
| | `ghstack` | `dub submit --stack` | Push everything in the stack and open/refresh PRs | | ||
| | `ghstack land $URL` | `dub merge-next` / `dub land` | Land the next safe PR; retargets dependents | | ||
| | `ghstack unlink` | `dub unlink <branch>` | Detach a branch from its parent | | ||
| | `ghstack checkout $URL` | `dub co <branch>` | ghstack materialises a local branch from the PR's synthesised remote refs; with DubStack the PR's branch already exists locally, so just `dub co` it | | ||
| | (no equivalent) | `dub info` | Stack-aware branch metadata is implicit in ghstack's commit-per-PR model | | ||
| | Implicit rebase on push | `dub restack` | Explicit, undo-able restack | | ||
| | Implicit PR description prefix | `dub submit --ai` or templated body | DubStack does not auto-prefix; configure via templates | | ||
|
|
||
| (ghstack has a narrower surface than Graphite/Charcoal; many DubStack commands have no ghstack analog because ghstack does not model stacked branches locally.) | ||
|
|
||
| ## Conceptual Differences | ||
|
|
||
| - **One commit per PR vs. one branch per PR.** ghstack rewrites your local history so each commit is mapped to its own pseudo-branch on the remote. DubStack keeps a real branch per PR in your working copy. The DubStack model is friendlier to bisect, blame, and IDE workflows because each PR is an ordinary git branch you can check out. | ||
| - **No commit re-authoring.** DubStack does not amend or rewrite commits when you submit. ghstack rewrites the `gh-metadata` trailer on every push. | ||
| - **PR base is a real branch.** DubStack PRs target the previous branch in your stack directly. ghstack PRs target a synthesised `gh/$user/$n/base` orphan branch, which can confuse code review tooling. | ||
| - **Land semantics.** `ghstack land` squash-merges the bottom commit into `main`. `dub merge-next` (alias `dub land`) merges the next mergeable PR and retargets every dependent before deleting the branch — including in the GitHub merge queue when configured. | ||
| - **Multi-author safe.** Because each PR is a real branch, collaborators can push to your stack without your local `gh-metadata` getting in the way. | ||
| - **No remote write on read.** DubStack never pushes anything during `dub log`, `dub status`, or `dub info`. ghstack's `checkout` walks the remote to assemble the working copy. | ||
|
|
||
| ## Common Pitfalls | ||
|
|
||
| - **Squash vs. merge.** `ghstack land` always squash-merges. DubStack's default is configurable per repo with `dub config submit-default` and per merge with `dub merge-next --method squash|merge|rebase`. | ||
| - **PR commit messages.** ghstack uses the commit subject as the PR title and the body as the PR description. DubStack uses the same convention for new PRs but does **not** rewrite the PR title on subsequent submits. Edit titles in GitHub or pass `--ai` for an LLM-suggested rewrite. | ||
| - **The `gh-metadata: Pull-Request resolved:` trailer.** DubStack does not add or rely on this trailer. You can leave it on existing commits or strip it during the migration with `git rebase -i`. | ||
| - **Submodules and worktrees.** DubStack supports git worktrees and stores per-worktree state under `.git/worktrees/<id>/dubstack/`. ghstack does not. | ||
|
|
||
| ## 30-Minute Migration Script | ||
|
|
||
| The cleanest path: convert each in-flight ghstack PR into a real local branch, then track it. | ||
|
|
||
| ```bash | ||
| # 1. Install DubStack | ||
| npm install -g dubstack | ||
|
|
||
| # 2. Initialize. Safe alongside ghstack — DubStack writes only under .git/dubstack/ | ||
| cd path/to/repo | ||
| dub init | ||
|
|
||
| # 3. For each open ghstack PR you own, materialise a local branch. | ||
| # ghstack PR titles include "[ghstack-poisoned]" markers — these refer to | ||
| # your `orig` commits. Use the GitHub UI or `gh pr list --author @me` to | ||
| # enumerate; for each one, create a local branch off the PR's head SHA: | ||
| # | ||
| # gh pr checkout <pr-number> | ||
| # git switch -c feat/<your-name> # rename to something human | ||
| # | ||
| # Or, for the entire stack at once, walk from oldest to newest and chain: | ||
| git switch main | ||
| git switch -c feat/auth-base # bottom of the old ghstack | ||
| git cherry-pick <bottom-orig-sha> # the orig commit ghstack tracked | ||
| git switch -c feat/auth-login # next one up | ||
| git cherry-pick <next-orig-sha> | ||
| # ... and so on. | ||
|
|
||
| # 4. Track every new branch in DubStack | ||
| git switch feat/auth-base | ||
| dub track --parent main | ||
| git switch feat/auth-login | ||
| dub track --parent feat/auth-base | ||
| # etc. | ||
|
|
||
| # 5. Sanity-check the chain | ||
| dub log --stack | ||
|
|
||
| # 6. Open new DubStack PRs and close the old ghstack PRs by hand. New PRs use | ||
| # real branch bases instead of the synthesised gh/<user>/<n>/base branches. | ||
| dub submit --stack | ||
|
|
||
| # 7. Once the team has approved + merged the new PRs, prune ghstack: | ||
| pip uninstall ghstack | ||
| git for-each-ref --format='%(refname)' refs/heads/gh/ \ | ||
| | xargs -I {} git update-ref -d {} | ||
| git push origin --delete $(git for-each-ref \ | ||
| --format='%(refname:lstrip=3)' refs/heads/gh/) | ||
| ``` | ||
|
|
||
| If your team uses ghstack as a merge tool only (and not for daily local stacking), the simpler answer is: keep ghstack for landing, use DubStack for local stack manipulation, and switch fully once the last ghstack PR lands. | ||
|
|
||
| ## See Also | ||
|
|
||
| - [Stacking Workflow](/docs/guides/stacking-workflow) | ||
| - [Conflict Resolution](/docs/guides/conflict-resolution) | ||
| - [JSON Output](/docs/guides/json-output) |
131 changes: 99 additions & 32 deletions
131
apps/docs/content/docs/guides/migration-from-graphite.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,38 +1,105 @@ | ||
| --- | ||
| title: Graphite Migration | ||
| description: Map Graphite commands to DubStack equivalents. | ||
| title: Migrating from Graphite | ||
| description: Map Graphite (`gt`) commands to DubStack equivalents and migrate an in-flight stack in under 30 minutes. | ||
| --- | ||
|
|
||
| If you have `gt` muscle memory, use this as a fast map. DubStack follows the same mental model. | ||
| If you have `gt` muscle memory, this guide is the fast path to DubStack. The mental model is the same: branches stacked on branches, one PR per branch, automatic restack on rebase. | ||
|
|
||
| ## Command Mapping | ||
|
|
||
| | Graphite | DubStack | | ||
| |---|---| | ||
| | `gt create` | `dub create` | | ||
| | `gt modify` | `dub modify` / `dub m` | | ||
| | `gt submit` / `gt ss` | `dub submit` / `dub ss` | | ||
| | `gt sync` | `dub sync` | | ||
| | `gt checkout` / `gt co` | `dub checkout` / `dub co` | | ||
| | `gt log` / `gt ls` | `dub log` / `dub ls` | | ||
| | `gt up` / `gt down` | `dub up` / `dub down` | | ||
| | `gt top` / `gt bottom` | `dub top` / `dub bottom` | | ||
| | `gt info` | `dub info` | | ||
| | `gt pr` | `dub pr` | | ||
| | `gt restack` | `dub restack` | | ||
| | `gt continue` | `dub continue` | | ||
| | `gt abort` | `dub abort` | | ||
| | `gt track --parent` | `dub track --parent` | | ||
| | `gt untrack` | `dub untrack` | | ||
| | `gt delete` | `dub delete` | | ||
| | `gt parent` | `dub parent` | | ||
| | `gt children` | `dub children` | | ||
| | `gt trunk` | `dub trunk` | | ||
| | `gt undo` | `dub undo` | | ||
|
|
||
| ## Key Differences | ||
|
|
||
| - **Local-first** — DubStack stores all state locally in `.git/dubstack/`. Nothing is pushed to your remote from these files. | ||
| - **AI features** — DubStack includes built-in AI for branch naming, commit messages, PR descriptions, `dub flow`, and stack-aware guidance via `dub ai ask`. | ||
| - **Agent skills** — DubStack ships packaged skills for coding assistants via `dub skills add`. | ||
| - **Safe merging** — `dub merge-next` handles retargeting child PRs before deleting merged branches. | ||
| | Graphite | DubStack | Notes | | ||
| |---|---|---| | ||
| | `gt create` | `dub create` | Same flags: `-a`, `-m`, `--ai` | | ||
| | `gt modify` / `gt m` | `dub modify` / `dub m` | Amend current branch and restack descendants | | ||
| | `gt submit` / `gt ss` | `dub submit` / `dub ss` | `--stack`, `--upstack`, `--downstack`, `--branch` | | ||
| | `gt sync` | `dub sync` | `--all` syncs every tracked stack | | ||
| | `gt checkout` / `gt co` | `dub checkout` / `dub co` | Interactive picker with no argument | | ||
| | `gt log` / `gt ls` | `dub log` / `dub ls` | `--stack`, `--all`, `--json` | | ||
| | `gt up` / `gt down` | `dub up` / `dub down` | Identical | | ||
| | `gt top` / `gt bottom` | `dub top` / `dub bottom` | Identical | | ||
| | `gt info` | `dub info` | `--json` machine-readable | | ||
| | `gt pr` | `dub pr` | Opens the PR for the current branch | | ||
| | `gt restack` | `dub restack` | Automatic when a parent changes | | ||
| | `gt continue` | `dub continue` | Add `--ai` to resolve conflicts via LLM | | ||
| | `gt abort` | `dub abort` | Rolls back restack/rebase | | ||
| | `gt track --parent` | `dub track --parent` | Adopt an untracked branch | | ||
| | `gt untrack` | `dub untrack` | Keep the branch, drop DubStack metadata | | ||
| | `gt delete` | `dub delete` | `--upstack`, `--downstack`, `--force` | | ||
| | `gt parent` / `gt children` | `dub parent` / `dub children` | `--json` outputs the relation | | ||
| | `gt trunk` | `dub trunk` / `dub trunk add` / `dub trunk set-default` | Multi-trunk supported | | ||
| | `gt undo` | `dub undo` | 20-entry ring buffer, supports `dub redo` | | ||
| | `gt absorb` | `dub absorb` | `--ai` for ambiguous fixups | | ||
| | `gt fold` | `dub fold` | Defaults to keeping commits; `--squash` to collapse | | ||
| | `gt move --before/--after` | `dub move --before/--after` | Identical semantics | | ||
| | `gt split` | `dub split` | Interactive or AI-assisted commit split | | ||
|
|
||
| ## Conceptual Differences | ||
|
|
||
| - **Local-first.** All state lives in `.git/dubstack/` and never leaves your machine. There is no DubStack account, no remote server, and no synchronization daemon. The downside is that team coordination happens through GitHub PRs alone. | ||
| - **Stack metadata in git refs.** DubStack mirrors stack state into `refs/dubstack/*` so a wiped checkout can rebuild from `dub init --restore-from-refs`. Graphite stores the equivalent in `.graphite_cache_persist`. | ||
| - **First-class AI.** `dub create --ai`, `dub submit --ai`, `dub flow`, and `dub absorb --ai` all use a provider you configure with `dub config ai-provider`. Set keys with `dub config ai-model --provider anthropic <model>`. | ||
| - **Safer merges.** `dub merge-next` (alias `dub land`) refuses to merge a PR whose ancestors are not yet merged, and retargets every dependent PR atomically before deleting the local branch. | ||
| - **Multi-trunk.** A single repository can have several trunks (e.g. `main` plus `release/24.x`). Configure with `dub trunk add` and `dub trunk set-default`. | ||
| - **MCP server.** `dub mcp` exposes the local stack to AI coding agents via the Model Context Protocol, gated by `dub config mcp-mode`. | ||
|
|
||
| ## Common Pitfalls | ||
|
|
||
| - **`gt submit --stack` defaulted to the whole tree; `dub submit` defaults to downstack.** Pass `--stack` explicitly when migrating CI scripts that assumed Graphite's old default. | ||
| - **`gt sync --no-restack` does not exist in DubStack.** Use `dub sync` and then `dub restack --continue` if you wanted to defer restack. | ||
| - **`.graphite_user_config` is not read.** Re-configure with `dub config ai-provider`, `dub config reviewers`, and friends. | ||
| - **`gt downstack edit` has no direct equivalent.** Use `dub reorder` for interactive reordering, or `dub move --before/--after` for single-branch moves. | ||
|
|
||
| ## 30-Minute Migration Script | ||
|
|
||
| The following walkthrough migrates an active Graphite stack in place without re-creating any branches or losing in-flight PRs. | ||
|
|
||
| ```bash | ||
| # 1. Install DubStack (assumes pnpm/npm available) | ||
| npm install -g dubstack | ||
|
|
||
| # 2. From the repo root, initialize DubStack alongside Graphite | ||
| cd path/to/repo | ||
| dub init | ||
|
|
||
| # 3. Adopt every Graphite-tracked branch into DubStack. DubStack walks the | ||
| # git ancestry to infer parent links — this is non-destructive. | ||
| git switch main | ||
| for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do | ||
| if [ "$branch" != "main" ]; then | ||
| git switch "$branch" | ||
| dub track --no-interactive || true | ||
| fi | ||
| done | ||
|
|
||
| # 4. Verify the stack matches what Graphite showed | ||
| dub log --all | ||
|
|
||
| # 5. Optional: enable AI features. Pick one provider. | ||
| dub config ai-assistant on | ||
| dub config ai-provider anthropic | ||
| dub config ai-model --provider anthropic claude-sonnet-4-7 | ||
|
|
||
| # 6. Optional: pre-fetch your default reviewers so `dub submit` requests them | ||
| dub config reviewers alice,@org/backend | ||
|
|
||
| # 7. Confirm restack works on the active stack | ||
| dub restack | ||
|
|
||
| # 8. Resync PR descriptions with the new metadata layout | ||
| dub submit --downstack --no-ai | ||
|
|
||
| # 9. (When you are confident) remove Graphite | ||
| npm uninstall -g @withgraphite/graphite-cli | ||
| rm -rf .graphite_cache_persist .graphite_repo_config .graphite_user_config | ||
|
|
||
| # 10. Add an alias so muscle memory survives: | ||
| # alias gt=dub # zsh/bash | ||
| ``` | ||
|
|
||
| If anything looks off after step 4, run `dub doctor` for a diagnostic report. The state is recoverable via `dub init --restore-from-refs`. | ||
|
|
||
| ## See Also | ||
|
|
||
| - [Stacking Workflow](/docs/guides/stacking-workflow) | ||
| - [Conflict Resolution](/docs/guides/conflict-resolution) | ||
| - [Multi-trunk stacks](/docs/guides/multi-trunk) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.