Skip to content

Instantly share code, notes, and snippets.

@khoi
Created March 30, 2026 11:02
Show Gist options
  • Select an option

  • Save khoi/da504ebf072dbcf7474c3943fa0a435e to your computer and use it in GitHub Desktop.

Select an option

Save khoi/da504ebf072dbcf7474c3943fa0a435e to your computer and use it in GitHub Desktop.
start-linear-task-on-a-new-tab skill
interface:
display_name: "Start Linear Task Tab"
short_description: "Open a Linear task in a new Supaterm tab"
default_prompt: "Use $start-linear-task-on-a-new-tab to start SUP-34 in a new Supaterm tab."
name start-linear-task-on-a-new-tab
description Start work on a Linear issue in a new Supaterm tab backed by a dedicated git worktree and a fresh Codex session. Use when the user asks to start, pick up, spin up, or plan a Linear ticket in a new tab or dedicated worktree.

Start Linear Task On A New Tab

Use scripts/start-linear-task-on-a-new-tab.sh to validate the Linear issue, create or reuse a dedicated worktree under .worktrees/, and open a focused Supaterm tab that starts Codex with the planning prompt.

Workflow

  1. Resolve the Linear issue identifier from the user request. If the identifier is ambiguous, stop and ask for it.
  2. Run the launcher:
scripts/start-linear-task-on-a-new-tab.sh SUP-34
  1. Outside Supaterm, pass --space and optionally --window:
scripts/start-linear-task-on-a-new-tab.sh SUP-34 --space 1
scripts/start-linear-task-on-a-new-tab.sh SUP-34 --space 1 --window 1
  1. Let the script fetch linear issue view --json, prefer the issue branchName, and create or reuse the matching worktree.
  2. Let the script open a focused tab in that worktree and start Codex with this prompt:
You are working on a Linear ticket {{ issue.identifier }} under a dedicated worktree

- Fetch the ticket information and evaluate it and cross check with the code
- Come up with a plan to address it
  1. Report the resulting worktree path, branch name, and sp new-tab --json payload back to the user.

Requirements

  • Require git, jq, linear, sp, and codex on PATH.
  • Reuse an existing worktree for the issue branch instead of creating a second one.
  • Keep the worktree inside <repo>/.worktrees/.
#!/usr/bin/env bash
set -euo pipefail
issue_identifier=""
space=""
window=""
focus="--focus"
while [[ $# -gt 0 ]]; do
case "$1" in
--space)
[[ $# -ge 2 ]] || {
echo "missing value for --space" >&2
exit 1
}
space="$2"
shift 2
;;
--window)
[[ $# -ge 2 ]] || {
echo "missing value for --window" >&2
exit 1
}
window="$2"
shift 2
;;
--focus)
focus="--focus"
shift
;;
--no-focus)
focus="--no-focus"
shift
;;
-h|--help)
echo "usage: $(basename "$0") <ISSUE-ID> [--space N] [--window N] [--focus|--no-focus]"
exit 0
;;
-*)
echo "unknown option: $1" >&2
exit 1
;;
*)
[[ -z "$issue_identifier" ]] || {
echo "unexpected argument: $1" >&2
exit 1
}
issue_identifier="$1"
shift
;;
esac
done
[[ -n "$issue_identifier" ]] || {
echo "issue identifier is required" >&2
exit 1
}
[[ -z "$window" || -n "$space" ]] || {
echo "--window requires --space" >&2
exit 1
}
for tool in git jq linear sp codex; do
command -v "$tool" >/dev/null || {
echo "missing required tool: $tool" >&2
exit 1
}
done
sp ping >/dev/null
if [[ -z "${SUPATERM_SURFACE_ID:-}" && -z "${SUPATERM_TAB_ID:-}" && -z "$space" ]]; then
echo "outside Supaterm, pass --space <n>" >&2
exit 1
fi
repo_root=$(git rev-parse --show-toplevel)
issue_json=$(linear issue view "$issue_identifier" --json)
issue_identifier=$(jq -r '.identifier' <<<"$issue_json")
issue_title=$(jq -r '.title' <<<"$issue_json")
branch_name=$(jq -r '.branchName // empty' <<<"$issue_json")
if [[ -z "$branch_name" || "$branch_name" == "null" ]]; then
issue_slug=$(printf '%s' "$issue_title" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')
branch_name="${issue_identifier,,}"
[[ -z "$issue_slug" ]] || branch_name="$branch_name-$issue_slug"
fi
existing_worktree=$(
git worktree list --porcelain | awk -v branch="refs/heads/$branch_name" '
$1 == "worktree" { worktree = $2 }
$1 == "branch" && $2 == branch { print worktree; exit }
'
)
created_worktree=false
if [[ -n "$existing_worktree" ]]; then
worktree_path="$existing_worktree"
else
worktree_root="$repo_root/.worktrees"
worktree_name=$(printf '%s' "$branch_name" | tr '/' '-')
worktree_path="$worktree_root/$worktree_name"
mkdir -p "$worktree_root"
[[ ! -e "$worktree_path" ]] || {
echo "worktree path already exists but is not registered: $worktree_path" >&2
exit 1
}
if git show-ref --verify --quiet "refs/heads/$branch_name"; then
git worktree add "$worktree_path" "$branch_name"
else
if git show-ref --verify --quiet refs/remotes/origin/HEAD; then
base_ref=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD)
elif git show-ref --verify --quiet refs/heads/main; then
base_ref="main"
else
base_ref="HEAD"
fi
git worktree add -b "$branch_name" "$worktree_path" "$base_ref"
fi
created_worktree=true
fi
prompt=$(cat <<EOF
You are working on a Linear ticket $issue_identifier under a dedicated worktree
- Fetch the ticket information and evaluate it and cross check with the code
- Come up with a plan to address it
EOF
)
escaped_prompt=${prompt//\\/\\\\}
escaped_prompt=${escaped_prompt//\"/\\\"}
escaped_prompt=${escaped_prompt//\$/\\$}
printf -v tab_script 'codex "%s"\n' "$escaped_prompt"
sp_args=(new-tab --json "$focus" --cwd "$worktree_path")
if [[ -n "$space" ]]; then
sp_args+=(--space "$space")
fi
if [[ -n "$window" ]]; then
sp_args+=(--window "$window")
fi
sp_args+=(--script "$tab_script")
tab_json=$(sp "${sp_args[@]}")
jq -n \
--arg issue "$issue_identifier" \
--arg title "$issue_title" \
--arg branch "$branch_name" \
--arg worktree "$worktree_path" \
--argjson createdWorktree "$created_worktree" \
--argjson tab "$tab_json" \
'{
issue: $issue,
title: $title,
branch: $branch,
worktree: $worktree,
createdWorktree: $createdWorktree,
tab: $tab
}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment