.\n\n### 2. Fetch the issue from Linear\n\nUse Linear MCP `get_issue` with the parsed ID. Pull these fields:\n\n- `id`, `identifier`, `title`, `state.name`, `assignee`, `team.key`, `url`\n- `attachments` / `gitBranches` (if exposed) — to detect existing linked branches\n\nIf the issue can't be found, surface the error verbatim and stop. Don't invent.\n\n### 3. Check for \"already started\" state\n\nSkip-the-work conditions, in priority order:\n\n- **Status is already In Progress AND a branch is linked** → don't create a new branch. Output the existing branch name and the linked PR (if any), then stop. Tell the user: \"Looks like this is already in flight — branch `\u003cname\u003e` exists. Want me to switch to it locally?\" If yes:\n 1. `git fetch origin \u003cbranch\u003e`\n 2. If a local branch with that name exists (`git show-ref --verify --quiet refs/heads/\u003cbranch\u003e`) → `git checkout \u003cbranch\u003e` and then `git merge --ff-only origin/\u003cbranch\u003e` to pick up any remote commits.\n 3. Otherwise → `git checkout --track origin/\u003cbranch\u003e` to create a local tracking branch from the remote.\n\n This works regardless of whether the branch was created remotely (e.g. via Linear's \"Create branch\" button) or already exists locally from a previous session — the plain `git checkout \u003cbranch\u003e` fails in the remote-only case.\n- **Assigned to someone else** → don't silently steal. Ask: \"EXSC-282 is currently assigned to \u003cname\u003e. Take it over, or just create a branch without reassigning?\" Default to the latter.\n- **Status is Done / Cancelled** → ask for confirmation before reopening. \"EXSC-282 is in \u003cstate\u003e. Are you sure you want to start it?\"\n\nIf none of these apply, continue.\n\n### 4. Compute the branch name\n\nFormat: `feature/\u003clowercase-id\u003e-\u003cslugified-title\u003e` — this matches the workspace-configured Linear branch format (`feature/identifier-title`) so the integration auto-links on first push.\n\nSlugification rules (apply in order):\n\n1. Lowercase the title.\n2. Replace any run of non-alphanumeric characters with a single `-`.\n3. Trim leading/trailing `-`.\n4. Truncate to 60 chars total title length (don't break a word — cut at the last `-` within the limit).\n5. Drop the trailing `-` if truncation created one.\n\nExamples:\n\n- `EXSC-282` + \"Earn Monetization v2: Custom Vault Wrapper Design \u0026 Estimate\" → `feature/exsc-282-earn-monetization-v2-custom-vault-wrapper-design`\n- `COM-14` + \"Fix flaky test in route resolver\" → `feature/com-14-fix-flaky-test-in-route-resolver`\n\nShow the computed name to the user before checkout — they may want to override (e.g. `fix/`, `chore/`, scoped prefix). Accept any valid git ref name; if it doesn't contain the ID, warn that Linear won't auto-link.\n\n### 5. Create the branch locally\n\nIn the resolved repo path:\n\n```bash\n# verify clean state — don't clobber uncommitted work\ncd \u003crepo-path\u003e\ngit status --porcelain\n```\n\nIf `git status --porcelain` returns anything, **stop**. Show the user the dirty state and ask what to do:\n\n- \"Stash and proceed\" → `git stash push -m \"auto-stash before \u003cID\u003e\"`, then continue.\n- \"Commit on current branch first\" → exit and let them handle it.\n- \"Proceed anyway\" (rare) → continue but warn the branch will inherit the working changes.\n\nOnce clean:\n\n```bash\ngit fetch origin \u003cdefault-branch\u003e\ngit checkout -b \u003cbranch\u003e origin/\u003cdefault-branch\u003e\n```\n\n**Always base off fresh `origin/\u003cdefault-branch\u003e` — never off the local repo's current HEAD.** The local repo is very often parked on a feature branch from previous work, and silently inheriting whatever commits sit on that branch would mix unrelated changes into the new ticket. Explicitly using `origin/\u003cdefault-branch\u003e` as the base ref sidesteps this completely: the new branch starts from exactly the same commit a fresh `git clone` would land on.\n\nDo NOT use `git checkout main \u0026\u0026 git pull \u0026\u0026 git checkout -b \u003cbranch\u003e` — that mutates the local `main` branch, which the user may have intentionally pinned for some reason, and it requires a temporary checkout of `main` that fails if the working tree is dirty in ways the step-5 clean check missed. The `git fetch` + `checkout -b origin/\u003cdefault\u003e` pattern updates only the remote-tracking ref and never touches local `main`.\n\nUse `origin/main` for all repos in the mapping above. If a repo uses a different default (e.g. `master`, `develop`), detect via `git symbolic-ref refs/remotes/origin/HEAD` (or `git remote show origin | grep \"HEAD branch\"` as a fallback) and use that.\n\n### 6. Move the Linear ticket to In Progress\n\nUse Linear MCP `save_issue` with:\n\n- `id`: the issue ID from step 2\n- `state`: `\"In Progress\"` (the MCP resolves state names server-side against the issue's team)\n\nIf the call fails because the name doesn't resolve (e.g. a team uses a non-standard label), fall back to `list_issue_statuses` for the team, surface the available states, and ask the user which one to use.\n\nSkip if the ticket is already In Progress (idempotent — don't error).\n\n### 7. Assign to the current user\n\nUse Linear MCP `save_issue` with:\n\n- `id`: the issue ID\n- `assignee`: `\"me\"` (the MCP resolves this to the authenticated user — don't hardcode an email or user ID so the skill works for any teammate who installs it)\n\nSkip if the ticket is already assigned to the current user. If assigned to someone else, follow the rule from step 3 — only reassign if the user confirmed takeover.\n\n### 8. Report\n\nOne-line summary:\n\n```\nStarted \u003cID\u003e — \u003ctitle\u003e\n branch: \u003cbranch-name\u003e\n repo: \u003clocal-path\u003e\n linear: \u003clinear-url\u003e\n```\n\nIf anything was skipped (already In Progress, already assigned, etc.), note it in a second line so the user knows what state things are in.\n\n## Failure modes\n\n- **Linear MCP not connected** → tell user to connect it; do not fall back to the Linear web API (no auth available).\n- **Repo not found locally** → see step \"Finding the local clone\". Offer to clone.\n- **Branch name collision** (`git checkout -b` fails because branch exists) → surface the existing branch; offer to switch to it (`git checkout \u003cbranch\u003e`) or pick a suffix like `-2`.\n- **Dirty working tree** → never `git stash` automatically; always ask.\n- **Linear state transition fails** (permissions, missing state) → branch was already created, so don't roll it back. Report partial success and the specific Linear error.\n\n## Design notes (why this skill exists)\n\n- **The Jira \"create branch\" equivalent, plus more.** Linear's native \"Create branch\" button creates the branch on GitHub remote only and doesn't change ticket state. This skill closes both gaps: local checkout + status flip + ownership claim in one shot.\n- **Ownership is claimed at start-of-work, not at PR-open.** PR-auto-assign is intentionally off in workspaces that want unassigned tickets to remain a pool. But the moment someone runs this skill, they're claiming the work — that's the right signal to assign.\n- **Branch naming matches Linear's configured format** (`feature/identifier-title`) so the auto-link works on first push without manual PR-body magic words. Magic words (`Fixes EXSC-282`) are still a fine fallback for ad-hoc branches that don't follow the format.\n- **No GitHub branch creation via the Linear button.** That path creates the branch on GitHub's HEAD of the default branch, which forces a `git fetch \u0026\u0026 git checkout` dance locally. Doing it locally is one step.\n- **Idempotent on re-run.** Running the skill twice on the same ticket should not error, double-assign, or duplicate branches — it should detect existing state and skip cleanly.\n\n## Variations the user may request\n\n- \"Use branch prefix `fix/` instead of `feature/`\" → honor for this run; don't persist.\n- \"Don't assign to me, just create the branch\" → skip step 7.\n- \"Don't change status\" → skip step 6 (useful when starting exploratory work that shouldn't tell the team you've committed).\n- \"Take it over from \u003cname\u003e\" → bypass the step-3 reassignment guard; proceed to assign to current user.\n- \"Use worktree instead of branch\" → run `git worktree add ../\u003crepo\u003e-wt-\u003cshort-id\u003e -b \u003cbranch\u003e origin/\u003cdefault\u003e` instead of `checkout -b`. Useful when the user has uncommitted work on the current branch they don't want to stash.\n","repo_fullName":"lifinance/contracts","repo_stars":204,"repo_language":"Solidity","repo_license":"LGPL-3.0","repo_pushedAt":"2026-06-02T03:26:39Z","owner_login":"lifinance","owner_type":"Organization","owner_name":"LI.FI","owner_avatarUrl":"https://avatars.githubusercontent.com/u/85288935?v=4"}};