Best for
- Use when the user expresses work intent ("let's build/fix/add X", "work on Y"), pastes a list of todos/notes to triage, asks about existing issues, OR you (or the user) are about to open a PR, queue auto-merge, or merge…
gobifrost/bifrost/.codex/skills/bifrost-issues/SKILL.md
Track work on Bifrost via GitHub Issues + isolated worktrees, AND own the PR/merge lifecycle (opening, queuing auto-merge, watching CI + reviews). Use when the user expresses work intent ("let's build/fix/add X", "work on Y"), pastes a list of todos/notes to triage, asks about existing issues, OR you (or the user) are about to open a PR, queue auto-merge, or merge a PR on this repo. `main` uses GitHub's native merge queue — `gh pr merge <N>` (no strategy flag) enqueues the PR; the queue rebases,
Decision brief
All trackable work on gobifrost/bifrost lives in GitHub Issues, and all non-trivial work happens in isolated git worktrees under .worktrees/. This skill owns both halves: issue creation/triage and worktree setup/teardown. One skill because the triggers are identical — the moment…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/gobifrost/bifrost --skill ".codex/skills/bifrost-issues"Inspect the Agent Skill "bifrost-issues" from https://github.com/gobifrost/bifrost/blob/3e53e2c53db6b1db1712cb62a013ffe8885dedbe/.codex/skills/bifrost-issues/SKILL.md at commit 3e53e2c53db6b1db1712cb62a013ffe8885dedbe. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
CRITICAL: Use absolute paths in every Bash call. The Bash tool's CWD leaks between calls — once you cd somewhere (e.g. for npm ci), subsequent calls silently inherit that CWD. Always write the full worktree path explicitly. Don't trust cd to stick.
1. Light-touch, never block. Nudge once, respect the answer. If the user skips, proceed without guilt. 2. Show drafts before filing. Never call gh issue create without showing the drafted body first. 3. GitHub conventions only. Use assignee, help wanted, good first issue — not c…
Activate on any of these:
A change is trivial and does not need an issue or worktree if it meets any of these:
Before any code, before any worktree, get an issue number.
Permission review
The documentation asks the agent to create, modify, or delete local files.
≤3-line edit to a single file with no behavior changeThe documentation asks the agent to run terminal commands or scripts.
git fetch origin mainThe documentation asks the agent to run terminal commands or scripts.
git log --oneline main..origin/main # if non-empty, warn and offer to pullEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 92/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 59 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
All trackable work on gobifrost/bifrost lives in GitHub Issues, and all non-trivial work happens in isolated git worktrees under .worktrees/. This skill owns both halves: issue creation/triage and worktree setup/teardown. One skill because the triggers are identical — the moment the user expresses work intent on a non-trivial change, both pipelines fire.
gh issue create without showing the drafted body first.assignee, help wanted, good first issue — not custom status/priority/milestone labels.main is a smell — the user keeps main clean to pull updates without conflicting with in-progress work../debug.sh stack (Compose project derived from the worktree path). See the bifrost-debug skill for boot/teardown.Activate on any of these:
help wanted or good first issueDo not activate for:
A change is trivial and does not need an issue or worktree if it meets any of these:
Anything else — multi-file, multi-line, new behavior, test changes, migrations, dependency bumps — is non-trivial and triggers the full flow.
Before any code, before any worktree, get an issue number.
Search for existing issues:
gh issue list --search "<2-3 key terms>" --state all --limit 5
If a plausible match exists, surface it: "This looks related to #N — is that the same thing, or a new one?"
If none, ask once: "Is there an issue for this? I can create one, or skip if it's trivial."
When drafting an issue body:
bug, feature, chore) from the work description.gh issue create --title "..." --body "..." --label "..." --assignee "@me" (self-assign only if the user is doing the work).Once the issue exists:
CRITICAL: Use absolute paths in every Bash call. The Bash tool's CWD leaks between calls — once you
cdsomewhere (e.g. fornpm ci), subsequent calls silently inherit that CWD. Always write the full worktree path explicitly. Don't trustcd <worktree>to stick.
# Preflight: make sure main isn't stale
git fetch origin main
git log --oneline main..origin/main # if non-empty, warn and offer to pull
# Create the worktree (absolute path)
git worktree add -b <issue-num>-<short-slug> \
/home/jack/GitHub/bifrost/.worktrees/<issue-num>-<short-slug> origin/main
# Node deps in the worktree (needed for vitest/tsc/lint).
# This `cd` will leak into later Bash calls — keep using absolute paths after.
cd /home/jack/GitHub/bifrost/.worktrees/<slug>/client && npm ci
Conventions:
<issue-num>-<short-slug>. Slug is hyphenated, ≤40 chars..worktrees/ is already gitignored in this repo — verify once, warn if not.origin/main, not local main (local can be stale; origin is the shared truth)..env / .env.test files — ./test.sh and ./debug.sh find them on their own. Copying creates drift between worktrees and is a footgun.Migrations are run by the bifrost-init container against a single Postgres shared across worktrees. Before starting work in the new worktree:
# Any new migrations on main that this branch doesn't have?
git diff --stat origin/main -- api/alembic/versions/
Do NOT compare migration folders with ls | tail — a __pycache__ directory in one but not the other silently skews the result. Use git diff --stat or ls api/alembic/versions/*.py.
If main has migrations the branch lacks, warn: "main has migrations ahead of this branch — merge or rebase before running the stack, otherwise the DB schema won't match your code." Don't auto-rebase.
Debug stacks are per-worktree — ./debug.sh derives its Compose project name from the worktree path, so two worktrees running their own stacks don't conflict. See the bifrost-debug skill for the lifecycle (boot, status, teardown, two-mode behavior).
Most worktrees don't need a debug stack. The test stack (./test.sh stack up) is already per-worktree and is enough for unit/E2E coverage. Type generation can extract OpenAPI from the test-stack's API container. Only invoke the bifrost-debug skill when you actually need to click around the UI in this worktree.
./test.sh stack up once per worktree, then ./test.sh many times../test.sh quality api for Dockerized pyright and ruff parity; do not depend on a host .venv.Run cheap, targeted tripwires for the surfaces you touched before opening the PR. These catch the common "CI found the stale generated thing" loop locally.
| If you touched... | Run before PR |
|---|---|
| CLI help, entity commands, DTO flags, or SDK-facing command surface | ./test.sh tests/unit/test_cli_surface_smoke.py tests/unit/test_skill_appendix_fresh.py |
| DTO models or CLI/MCP mutation flags | ./test.sh tests/unit/test_dto_flags.py tests/unit/test_contract_version.py |
Bifrost skills under .claude/skills/ | bash scripts/sync-codex-skills.sh, then ./test.sh tests/unit/test_skill_appendix_fresh.py tests/unit/test_codex_mirror_sync.py |
Public plugin skills under plugins/bifrost/skills/ | Confirm canonical .claude/skills/ and plugin mirror match (diff -qr ...) and that public skill names do not repeat the plugin namespace |
If test_skill_appendix_fresh.py fails, run the generator before pushing:
python api/scripts/skill-truth/generate.py
If host Python is missing API dependencies, run the generator in the API test image with writable .claude/skills and read-only source mounts. Do not hand-edit generated appendices.
After targeted verification, commit the exact candidate and run:
./test.sh pre-pr
Do not open a PR or queue it for merge unless this passes for the current HEAD. The command rejects dirty worktrees and branches that do not contain current origin/main; rerun it after every commit, amend, rebase, or merge. It exercises every locally reproducible PR and merge-queue gate. GitHub-only boundaries such as the synthetic merge ref, registry publication, signing, and attestation remain remote checks.
When opening the PR:
<issue-num>-<slug> should yield one automatically.Fixes #N (use Closes #N for non-bug issues; GitHub auto-closes the issue on merge either way).Fixes #N line per issue.The PR isn't done at "opened." Carry it through to merged. The path depends on whether main has branch protection with required status checks — --auto is only safe when GitHub will refuse to merge until checks pass.
Capability check (do this once, immediately after opening the PR):
# Detect required-checks gating. ≥1 → protection exists; 0 / 404 → no protection.
gh api repos/gobifrost/bifrost/branches/main/protection \
--jq '.required_status_checks.contexts // [] | length' 2>/dev/null
If the count is ≥1, --auto is safe. Otherwise it isn't (a --auto merge would fire the moment GitHub considers the PR mergeable, which without required checks is immediately).
Watch reviews and CI together — gh pr checks alone will miss code review comments.
Once a PR is open, three independent signals can come in: CI check transitions, code-review comments (CodeQL bot, human reviewers, copilot/Anthropic), and merge-state changes. The watcher must cover all three. Don't just tail -f gh pr checks — that silently misses CodeQL findings until they're already old, and an auto-merge queued PR can sit forever blocked on an "actionable" review you never noticed.
Combined watcher pattern (use this, not a checks-only loop):
# Hash reviews + check states + comments together; emit only on change.
# Terminal condition is INTENTIONALLY narrow: only state==MERGED|CLOSED.
# Don't try to be clever with "BLOCKED + all checks done" — mergeStateStatus
# is BLOCKED from the moment a PR opens against a protected branch, and
# `statusCheckRollup` may briefly contain entries with empty conclusion+state
# while checks are being scheduled, which makes the "all done" predicate
# fire prematurely. Watch until merge or close; the user can interrupt.
prev=""
prev_c=""
while true; do
s=$(gh pr view <N> --repo gobifrost/bifrost \
--json reviews,statusCheckRollup,reviewDecision,mergeStateStatus,state 2>/dev/null) || { sleep 60; continue; }
c=$(gh api repos/gobifrost/bifrost/pulls/<N>/comments --jq '.[] | "\(.user.login):\(.id):\(.path):\(.line):\(.body|gsub("\n";" ")|.[0:100])"' 2>/dev/null | sort)
cur=$(printf '%s\n%s' "$s" "$c" | sha256sum | cut -d' ' -f1)
if [ "$cur" != "$prev" ]; then
echo "=== $(date -u +%H:%M:%S) PR <N> update ==="
jq -r '" reviewDecision: \(.reviewDecision // "(none)")\n mergeStateStatus: \(.mergeStateStatus)\n state: \(.state)\nchecks:", (.statusCheckRollup[] | " \(.name // .context // "?"): \(.conclusion // .state // "queued")"), "reviews:", (.reviews[] | " \(.author.login) \(.state)")' <<<"$s"
if [ -n "$prev_c" ] && [ "$c" != "$prev_c" ]; then
echo "NEW review comments:"
diff <(echo "$prev_c") <(echo "$c") | grep '^>' | head -10
fi
prev_c=$c
prev=$cur
fi
st=$(jq -r '.state' <<<"$s")
case "$st" in MERGED|CLOSED) echo "PR is $st"; break ;; esac
sleep 60
done
When a review comment lands (CodeQL, copilot, human): pull the body and address it before merging. CodeQL findings on this repo's pre-push hook are usually real — see feedback_codeql_friendly_idioms.md in memory. Never queue --auto and walk away from a fresh review.
When a CI job fails: fetch the failing job log immediately instead of waiting for the whole workflow run to finish. gh run view --log-failed may refuse while sibling jobs are still running; the job logs endpoint often works sooner:
gh pr checks <N> --repo gobifrost/bifrost
gh pr view <N> --repo gobifrost/bifrost \
--json statusCheckRollup \
--jq '.statusCheckRollup[] | select((.conclusion // "") == "FAILURE") | {name,workflowName,detailsUrl}'
gh api repos/gobifrost/bifrost/actions/jobs/<job_id>/logs
If the failure is locally reproducible and ./test.sh pre-pr passed for the same SHA, the local gate is incomplete or non-equivalent. Fix that harness/guidance defect and preserve the exposing condition in pre-pr before rerunning or requeueing; do not accept CI as the routine first broad test run.
Fix CI failures in the same worktree and branch. Prefer a normal follow-up commit once reviewers or other agents may have seen the PR; amending with --force-with-lease is acceptable for a fresh, unreviewed PR where you are the only actor. After any force-push, re-check whether auto-merge/queue state survived.
Path A — protection exists (preferred for ship-when-green):
gh pr merge <N> --repo gobifrost/bifrost (NO strategy flag — the queue dictates squash; passing --squash is rejected with "The merge strategy for main is set by the merge queue"). Enqueuing IS the auto-merge-when-green: the queue owns the rebase, runs checks once on a combined ref, and merges when green. (--auto is accepted if you want gh to wait for the PR to be mergeable before enqueuing, but NOTE the queue is the actual gating mechanism — you don't need it.)BLOCKED/DIRTY mergeStateStatus.required_pull_request_reviews is set) and the user isn't admin, surface that the merge is gated on approval and offer to request reviewers via gh pr edit <N> --add-reviewer <login>. Don't pick reviewers unprompted.Path B — no protection (fallback):
<issue-num>-<slug>, not a fresh worktree. The PR auto-updates on push. New worktree only if the branch is being abandoned entirely.gh pr view <N> --json viewerCanAdminister,reviewDecision,mergeStateStatus to decide.
viewerCanAdminister: true → self-merge: confirm once ("CI's green and reviews are clean — merge?"), then gh pr merge <N> --squash --delete-branch=false.--auto on Path B. Without required checks, it would fire before CI completes.Both paths:
gh pr checks watcher that doesn't also poll reviews/comments will leave the user thinking nothing is happening while CodeQL has been waiting on you for 20 minutes.autoMergeRequest may be null even if the issue event log says added_to_merge_queue. Check both gh pr view ... --json autoMergeRequest,mergeStateStatus,statusCheckRollup and recent issue events before repeatedly re-running gh pr merge.mergeStateStatus is CLEAN, a queued PR can still take several minutes to flip to MERGED. Confirm added_to_merge_queue via gh api repos/gobifrost/bifrost/issues/<N>/events; then keep the watcher attached rather than thrashing the queue.After the PR is merged, offer (do not run unprompted):
git worktree remove .worktrees/<issue-num>-<slug>
git branch -d <issue-num>-<slug>
git push origin --delete <issue-num>-<slug> # if --delete-branch=false was used at merge time
Then cd back to the main checkout (/home/jack/GitHub/bifrost) so subsequent commands target main and not a stale worktree path.
When the user pastes a list of todos, notes, or ideas:
bug, feature (→ enhancement label), chore, or idea.idea items too vague to fit feature.yml, use a blank issue with the idea label.## Bugs (3)
1. [title] — [one-line summary]
2. ...
## Features (2)
...
gh issue create. Print the resulting issue numbers.Do not auto-create worktrees for batch-triaged issues — the user is cataloging, not starting work.
On user request:
gh issue edit N --add-label "help wanted"gh issue edit N --add-label "good first issue"gh issue edit N --add-assignee "@me"gh issue edit N --add-assignee <login>Do not add priority labels, milestones, or status labels.
main conflict risk.gh not authenticated → surface the error and offer to proceed without an issue. Don't block the real work.gh issue create Patterngh issue create \
--title "[bug]: <summary>" \
--body "$(cat <<'EOF'
## Summary
...
## Steps to reproduce
...
## Expected behavior
...
## Actual behavior
...
## Environment
...
## Notes
- File paths and line numbers where relevant
- Proposed approach if known
EOF
)" \
--label "bug" \
--assignee "@me" # only if user is doing the work
Mirror the relevant template in .github/ISSUE_TEMPLATE/. Use [bug]:, [feature]:, or [chore]: title prefixes.
./debug.sh in another worktree — user controls that manually.gobifrost/bifrost.Frequently asked questions
All trackable work on gobifrost/bifrost lives in GitHub Issues, and all non-trivial work happens in isolated git worktrees under .worktrees/. This skill owns both halves: issue creation/triage and worktree setup/teardown. One skill because the triggers are identical — the moment…
The source record exposes this install command: npx skills add https://github.com/gobifrost/bifrost --skill ".codex/skills/bifrost-issues". Inspect the command and pinned source before running it.
Static rules flagged write-files, exec-script in the source; the page lists the matching lines and excerpts.