# Gt Setup

> Validate Graphite CLI prerequisites and configure settings for AI agent workflows. Use when first installing the plugin, after Graphite auth changes, or when gt commands fail.

- Skill: `kinginyellows/gt-setup` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kinginyellows/gt-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kinginyellows/gt-setup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: kinginyellows (https://skillmd.com/u/kinginyellows)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kinginyellows/gt-setup

---


## What It Does

Validates that Graphite CLI is installed, authenticated, and initialized
for the current repository. Then configures Graphite CLI settings for AI
agent workflows and generates a `.graphite.yml` convention file.

## When to Use

- First installing the plugin.
- After Graphite auth changes.
- When `gt` commands fail.

## Usage

### Phase 1: Validate Prerequisites

#### Step 1: Check Graphite Prerequisites

Run a single Bash call:

```bash
version_gte() {
  local IFS=.
  local i a=($1) b=($2)
  for ((i=0; i<${#b[@]}; i++)); do
    local av="${a[i]:-0}" bv="${b[i]:-0}"
    if ((av > bv)); then return 0; fi
    if ((av < bv)); then return 1; fi
  done
  return 0
}

printf '=== Prerequisites ===\n'
if command -v gt >/dev/null 2>&1; then
  gt_version_full=$(gt --version 2>/dev/null)
  gt_version_exit=$?
  gt_version_raw=$(printf '%s' "$gt_version_full" | head -n1)
  if [ "$gt_version_exit" -ne 0 ]; then
    printf 'gt:            BROKEN (exited with code %s)\n' "$gt_version_exit"
    printf 'mcp_server:    SKIPPED (gt is broken)\n'
  elif [ -n "$gt_version_raw" ]; then
    printf 'gt:            ok (%s)\n' "$gt_version_raw"
    gt_ver=$(printf '%s' "$gt_version_raw" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
    if [ -z "$gt_ver" ]; then
      printf 'mcp_server:    UNKNOWN (could not parse version from: %s)\n' "$gt_version_raw"
    elif version_gte "$gt_ver" "1.6.7"; then
      printf 'mcp_server:    ok (gt >= 1.6.7)\n'
    else
      printf 'mcp_server:    UPGRADE NEEDED (current: %s, need 1.6.7+)\n' "$gt_ver"
    fi
  else
    printf 'gt:            ok (version unknown)\n'
    printf 'mcp_server:    UNKNOWN (gt --version returned no output)\n'
  fi
else
  printf 'gt:            NOT FOUND\n'
  printf 'mcp_server:    SKIPPED (gt not found)\n'
fi
command -v jq >/dev/null 2>&1 && printf 'jq:            ok\n' || printf 'jq:            NOT FOUND\n'
if command -v yq >/dev/null 2>&1; then
  if yq --help 2>&1 | grep -qi 'jq wrapper\|kislyuk'; then
    printf 'yq:            ok\n'
  else
    printf 'yq:            WRONG VARIANT (found non-kislyuk yq; .graphite.yml parsing will be skipped)\n'
  fi
else
  printf 'yq:            NOT FOUND (optional — needed by consumer commands to read .graphite.yml)\n'
fi

printf '\n=== Repository ===\n'
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || true)
[ -n "$repo_top" ] && printf 'git_repo:       ok\n' || printf 'git_repo:       NOT A GIT REPOSITORY\n'
graphite_repo_config=$(git rev-parse --git-path .graphite_repo_config 2>/dev/null || true)
[ -n "$graphite_repo_config" ] && [ -f "$graphite_repo_config" ] && printf 'repo_config:    present (%s)\n' "$graphite_repo_config" || printf 'repo_config:    missing\n'

if command -v gt >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  trunk=$(gt trunk 2>/dev/null || true)
  [ -n "$trunk" ] && printf 'gt_trunk:       %s\n' "$trunk" || printf 'gt_trunk:       UNAVAILABLE\n'
else
  printf 'gt_trunk:       SKIPPED\n'
fi

printf '\n=== Graphite Auth ===\n'
auth_ok=0
for path in \
  "$HOME/.graphite_user_config" \
  "${XDG_CONFIG_HOME:-$HOME/.config}/graphite/user_config" \
  "$HOME/.config/graphite/user_config"; do
  if [ -f "$path" ]; then
    auth_ok=1
    printf 'auth_config:    present (%s)\n' "$path"
    break
  fi
done
[ "$auth_ok" -eq 1 ] || printf 'auth_config:    missing\n'

printf '\n=== Convention Files ===\n'
[ -n "$repo_top" ] && [ -f "$repo_top/.graphite.yml" ] && printf 'graphite_yml:   present\n' || printf 'graphite_yml:   not found\n'
[ -n "$repo_top" ] && [ -f "$repo_top/.github/pull_request_template.md" ] && printf 'pr_template:    present\n' || printf 'pr_template:    not found\n'

printf '\n=== Merge Queue Compatibility ===\n'
# Capture stderr from gh probes so failure diagnostics survive (vs silent 2>/dev/null).
mq_err_log=$(mktemp 2>/dev/null) || mq_err_log=""
# Trap covers interruption (e.g. a Bash-tool timeout); the explicit rm at the
# end of this block still handles normal completion.
[ -n "$mq_err_log" ] && trap 'rm -f "$mq_err_log"' EXIT
# No `gh auth status` precheck: it exits non-zero if ANY known host has stale
# auth, which produces false COULD NOT CHECK results on multi-host setups
# (gh.com + ghe.example.com). Let `gh repo view` be the auth probe — it's
# scoped to the current repo's host and its stderr is captured below.
if command -v gh >/dev/null 2>&1; then
  repo_nwo=$(gh repo view --json nameWithOwner -q .nameWithOwner 2>"${mq_err_log:-/dev/null}")
  repo_view_status=$?
  if [ "$repo_view_status" -ne 0 ]; then
    if [ -n "$mq_err_log" ] && [ -s "$mq_err_log" ]; then
      printf '[gt-workflow] Warning: gh repo view failed (exit %d): %s\n' "$repo_view_status" "$(head -c 200 "$mq_err_log" | tr '\n' ' ')" >&2
    else
      printf '[gt-workflow] Warning: gh repo view failed (exit %d)\n' "$repo_view_status" >&2
    fi
    printf 'gh_native_queue:  COULD NOT CHECK (gh repo view failed)\n'
  elif [ -z "$repo_nwo" ]; then
    printf 'gh_native_queue:  COULD NOT CHECK (gh repo view returned no name)\n'
  else
    repo_owner="${repo_nwo%/*}"
    repo_name="${repo_nwo#*/}"
    [ -n "$mq_err_log" ] && : > "$mq_err_log"  # truncate before next probe
    # shellcheck disable=SC2016  # $owner/$name are GraphQL variable refs, not shell vars — intentionally literal in single quotes
    mq_check=$(gh api graphql -f query='
      query($owner:String!,$name:String!){
        repository(owner:$owner,name:$name){ mergeQueue { url } }
      }' -f owner="$repo_owner" -f name="$repo_name" --jq 'if .data.repository == null then error("repo null") else (.data.repository.mergeQueue | if . != null then "configured" else empty end) end' 2>"${mq_err_log:-/dev/null}")
    mq_status=$?
    if [ "$mq_status" -ne 0 ]; then
      if [ -n "$mq_err_log" ] && [ -s "$mq_err_log" ]; then
        printf '[gt-workflow] Warning: merge queue check failed (gh api graphql): %s\n' "$(head -c 200 "$mq_err_log" | tr '\n' ' ')" >&2
      else
        printf '[gt-workflow] Warning: merge queue check failed (gh api graphql)\n' >&2
      fi
      printf 'gh_native_queue:  COULD NOT CHECK (gh api graphql failed)\n'
    elif [ -n "$mq_check" ]; then
      printf 'gh_native_queue:  WARNING (configured — disable at https://github.com/%s/settings/branches)\n' "$repo_nwo"
    else
      printf 'gh_native_queue:  ok (not configured)\n'
    fi
  fi
else
  printf 'gh_native_queue:  COULD NOT CHECK (gh not installed)\n'
fi
[ -n "$mq_err_log" ] && rm -f "$mq_err_log"
```

#### Step 2: Interpret Results

**Failures (hard stop)** — stop after reporting all that apply:

- `gt` missing: "Graphite CLI is required. Install it from https://graphite.dev/docs/cli and re-run `gt-setup`."
- `jq` missing: "jq is required by gt-workflow (the gt-cleanup skill uses it to parse PR-status JSON). Install it from https://jqlang.github.io/jq/download/."
- `git_repo` not ok: "gt-workflow must be run inside a git repository."
- `auth_config` missing: "Graphite auth was not detected. Run `gt auth` or sign in through the Graphite CLI, then re-run `gt-setup`."
- `repo_config` missing OR `gt_trunk` unavailable: "This repository is not initialized for Graphite. Run `gt init`, confirm `gt trunk` works, then re-run `gt-setup`."

If any hard-stop failures exist, stop here. Do not proceed to Phase 2.

**Warnings (do not block setup — CLI commands still work):**

- `mcp_server` UPGRADE NEEDED: "Graphite MCP server requires gt v1.6.7+. The `gt mcp` stdio server registered in plugin.json will fail to start and Graphite MCP tools will be unavailable until you upgrade. Run `npm i -g @withgraphite/graphite-cli@latest` to upgrade, then re-run `gt-setup`. All CLI-based skills (`smart-submit`, `gt-sync`, etc.) continue to work without MCP."
- `mcp_server` SKIPPED or UNKNOWN: note accordingly.
- `yq` NOT FOUND: "yq (kislyuk variant) is optional but recommended. Without it, consumer skills (`smart-submit`, `gt-stack-plan`, `gt-amend`) will use hardcoded defaults instead of `.graphite.yml` settings. Install with: `pip install yq`"
- `gh_native_queue` WARNING (configured): "GitHub native merge queue is configured for this repo. Graphite and GitHub native merge queue are incompatible — running both causes Graphite to restart CI on queued commits and may produce out-of-order merges. To disable: open https://github.com/<owner>/<repo>/settings/branches, edit the branch protection rule for your trunk branch, and uncheck **Require merge queue**. Setup proceeds, but the warning will repeat each time you run `gt-setup` until resolved."
- `gh_native_queue` COULD NOT CHECK: informational only — but **not necessarily safe to ignore**. The parenthetical reason in the output line indicates which probe failed (gh missing/unauthenticated, `gh repo view`, or `gh api graphql`); the captured stderr is appended to the `[gt-workflow] Warning:` line on failure to aid debugging. Three documented false-negative paths exist for the `repository.mergeQueue { url }` proxy: (1) the GitHub token lacks the admin scope needed to read merge queue config, (2) the repository is not visible to the token, (3) merge queue is configured but `mergeQueue.url` is null. Any of these can produce COULD NOT CHECK or even a misleading `ok (not configured)` while the queue is actually active. If your token is scope-limited (e.g., a CI/automation token), re-run `gt-setup` with an admin-scoped token before relying on the result. Setup itself proceeds normally; the proxy is fail-open by design.

#### Step 3: Validation Report

If all checks pass, show:

```text
gt-workflow Validation
──────────────────────
Graphite CLI:  ready
jq:            ready
yq:            ready (or: not found — optional)
Auth:          detected
Repository:    initialized (trunk: <branch>)
MCP Server:    available (or: unavailable — gt < 1.6.7)
Merge Queue:   ok (or: WARNING — native queue active / COULD NOT CHECK)

Proceeding to AI agent configuration...
```

### Phase 2: Configure Graphite Settings for AI Agents

#### Step 4: Show Planned Changes

Before applying any settings, read current values and show what will change.
Run a single Bash call:

```bash
printf '=== Current Graphite User Settings ===\n'
gt user branch-prefix 2>/dev/null || printf 'branch-prefix: (not set / command unavailable)\n'
gt user branch-date 2>/dev/null || printf 'branch-date: (command unavailable)\n'
gt user restack-date 2>/dev/null || printf 'restack-date: (command unavailable)\n'
gt user submit-body 2>/dev/null || printf 'submit-body: (command unavailable)\n'
gt user pager 2>/dev/null || printf 'pager: (command unavailable)\n'
```

Present a summary table showing current vs recommended AI-agent values for each
setting. Then proceed to the interactive prompts below.

#### Step 5: Branch Prefix Prompt

(`AskUserQuestion` is a Claude Code tool — on Codex, ask each question as a
numbered-option list in your reply and wait for the user's answer before
proceeding; this applies to every AskUserQuestion mention in this skill.)

Use `AskUserQuestion` to ask: "What branch prefix should AI agents use?"

Options:
- `"agent/" (Recommended)` — flat namespace for agent-created branches
- `"Skip"` — keep the current branch-prefix setting unchanged

The "Other" button allows free-text input for a custom prefix.

**If the user provides a custom prefix via "Other", validate it:**
- Must start with a lowercase letter or digit (`[a-z0-9]`)
- Allowed subsequent characters: lowercase letters, digits, `/`, `_`, `-` only
- Reject if it contains `..`, `~`, spaces, or any character outside `[a-z0-9/_-]`
- Normalize: append trailing `/` if missing
- Max length: 20 characters (checked **after** normalization, so the effective
  input limit is 19 characters when a trailing `/` is appended)
- If validation fails, explain the constraint and re-prompt with AskUserQuestion

Store the chosen prefix (or empty string if skipped) for use in Step 7 and
Phase 3.

#### Step 6: Pager Prompt

Use `AskUserQuestion` to ask: "Disable the Graphite CLI pager? AI agents hang when pager is enabled."

Options:
- `"Disable pager (Recommended for AI agents)"` — will run `gt user pager --disable`
- `"Keep current pager setting"` — no change

If user chooses "Keep", note this in the summary. If user chooses "Disable",
include reversal instructions in the final report: "To re-enable: `gt user pager --enable`"

#### Step 7: Apply Settings

Apply settings via `gt user` commands. Run each in a separate Bash call to
isolate failures. Track the result of each command.

**Settings to apply (in this order):**

1. `gt user branch-date --disable` (if not already disabled)
2. `gt user restack-date --use-author-date` (if not already set)
3. `gt user submit-body --include-commit-messages` (if not already set)
4. Branch prefix (if user provided one in Step 5): run
   Substitute the validated prefix as a literal value in single quotes, e.g.,
   `gt user branch-prefix --set 'agent/'` — never use shell variable
   interpolation for user-supplied text
5. `gt user pager --disable` (only if user chose to disable in Step 6)

**Failure handling:** If any command fails:
- Record the error output
- Continue applying remaining settings (do not stop on first failure)
- After all commands, show a summary with status for each:
  - "Applied" — command succeeded
  - "Already set" — current value matches target, no change needed
  - "Failed" — command failed (show error)
  - "Skipped" — user chose not to change this setting

If any commands failed, note the failures in the summary and proceed to
Phase 3. The user can re-run `gt-setup` to retry.

#### Step 8: Settings Summary

Show the final state of all 5 settings:

```text
Graphite Settings Configuration
────────────────────────────────
branch-date:     disabled (Applied)
restack-date:    use-author-date (Applied)
submit-body:     include-commit-messages (Applied)
branch-prefix:   agent/ (Applied)
pager:           disabled (Applied) — to re-enable: gt user pager --enable
```

### Phase 3: Generate Convention File

#### Step 9: Check for Existing .graphite.yml

Determine the repo root and check for an existing convention file:

```bash
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
[ -f "$repo_top/.graphite.yml" ] && printf 'EXISTS\n' || printf 'NOT_FOUND\n'
```

**If the file exists**, read it and show the current contents. Then use
`AskUserQuestion`:
- `"Update with new values"` — overwrite with wizard-generated values
- `"Skip"` — keep the existing file unchanged

**If the file exists but is malformed YAML** (read fails or structure is
unexpected), warn the user and use `AskUserQuestion`:
- `"Overwrite with valid configuration"` — replace entirely
- `"Skip"` — keep the broken file as-is

**If the file does not exist**, proceed to Step 10.

If the user chose "Skip", jump to Step 11.

#### Step 10: Generate .graphite.yml

Build the convention file content using values from Phase 2 (branch prefix from
Step 5) and sensible defaults. Use the Write tool to create the file at
`<repo_root>/.graphite.yml`.

The file content:

```yaml
# gt-workflow convention file — read by smart-submit, gt-stack-plan, gt-amend, gt-setup
# This is NOT a Graphite CLI feature. It is a gt-workflow plugin convention.
# Docs: https://github.com/KingInYellows/yellow-plugins/tree/main/plugins/gt-workflow

submit:
  draft: false
  merge_when_ready: false
  restack_before: true

audit:
  agents: 3
  skip_on_draft: false

branch:
  prefix: "<prefix-from-step-5-or-empty>"

pr_template:
  create: true
```

Substitute the actual branch prefix chosen in Step 5. If the user skipped the
prefix, use an empty string: `prefix: ""`.

After writing, fix CRLF line endings (WSL2 safety):

```bash
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
sed -i 's/\r$//' "$repo_top/.graphite.yml" 2>/dev/null || \
  sed -i '' 's/\r$//' "$repo_top/.graphite.yml" 2>/dev/null || \
  printf '[gt-workflow] Warning: could not strip CRLF from .graphite.yml\n' >&2
```

#### Step 11: PR Template

First, if `.graphite.yml` was loaded in Step 9 and `pr_template.create` is
`false`, skip this step entirely and note "PR template: skipped
(pr_template.create is false in .graphite.yml)" in the final report.

Otherwise, check for an existing PR template:

```bash
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
[ -f "$repo_top/.github/pull_request_template.md" ] && printf 'EXISTS\n' || printf 'NOT_FOUND\n'
```

**If the template exists**, use `AskUserQuestion`:
- `"View current template"` — show contents, then re-prompt with Regenerate/Skip
- `"Regenerate"` — overwrite with the agent-optimized template
- `"Skip"` — keep existing

**If the template does not exist**, create `.github/` directory if needed and
write the template using the Write tool:

```bash
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
mkdir -p "$repo_top/.github"
```

Template content:

```markdown
## Summary

<!-- 2-3 bullet points of what this PR does -->

## Stack context

<!-- What branch is below this one and why (critical for stack reviewers) -->

## Test plan

<!-- What was verified before submit -->

## Notes for reviewers

<!-- Anything the author wants to call attention to -->
```

After writing, fix CRLF:

```bash
repo_top=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
sed -i 's/\r$//' "$repo_top/.github/pull_request_template.md" 2>/dev/null || \
  sed -i '' 's/\r$//' "$repo_top/.github/pull_request_template.md" 2>/dev/null || \
  printf '[gt-workflow] Warning: could not strip CRLF from PR template\n' >&2
```

#### Step 12: Final Report

Show the complete setup summary:

```text
gt-workflow Setup Complete
──────────────────────────
Phase 1: Validation         PASSED
Phase 2: Graphite Settings  5/5 configured
Phase 3: Convention File    .graphite.yml created
         PR Template        .github/pull_request_template.md created

Consumer skills (smart-submit, gt-stack-plan, gt-amend) will read
.graphite.yml for repo-level behavior overrides.

Next steps:
  - Review and commit .graphite.yml and .github/pull_request_template.md
  - Run smart-submit or gt-sync to verify your workflow
```

Adjust the summary to reflect actual outcomes (skipped items, partial
configuration, existing files kept, etc.).

