Slash Commands/Acceptpr
---
summary: 'Land one PR end-to-end (changelog + thanks, lint, merge, back to main).'
read_when:
- You need to accept a PR: fix, lint, merge, sync main.
---
/acceptpr
Input: PR number or URL (required). Default merge mode: rebase.
0) Guardrails
- Must end on main (or repo default branch if no main).
- git status -sb clean before/after. No uncommitted changes.
- If PR is draft, has conflicts, or base branch != main: stop + ask.
- If PR is from a fork and you canβt push: stop + ask.
1) Capture context
- START_BRANCH="$(git branch --show-current)"
- gh pr view <PR> --json number,title,author,baseRefName,headRefName,isDraft,mergeable,maintainerCanModify
- Skim: gh pr view <PR> --comments and gh pr diff <PR>
2) Checkout + suggested fixes
- gh pr checkout <PR>
- Apply fixes (and tests if needed). Keep edits minimal; follow repo conventions.
- Ensure change/feature/regression is well-tested (add/extend tests, and run the smallest relevant test target until green).
- Commit with explicit paths (no git add .), then push: git push origin HEAD
3) Changelog (and thank contributor)
- Edit CHANGELOG.md (or project changelog file).
- Add entry under the top βUnreleasedβ section (match existing style).
- Include PR + thanks, e.g.: - <short change> (#<num>) β thanks @<author>
- Commit + push changelog if it changed.
4) Lint
- Run repo linter/gate (prefer existing scripts; fix until green).
- If thereβs no obvious lint target, search: rg -n "lint|biome|eslint|swiftlint|ruff" package.json Makefile scripts -S
5) Merge (then delete PR branch)
- Prefer rebase merge: gh pr merge <PR> --rebase --delete-branch
- If rebase is disallowed, fallback to repo preference (--merge or --squash).
6) Sync main + exit clean
- git checkout main || git checkout "$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')"
- git pull --ff-only
- Verify merged: gh pr view <PR> --json mergedAt,mergeCommit
- git status -sb (clean) + ensure youβre on main.
---
Slash Commands/Fixissue
---
summary: 'Fix an issue end-to-end (tests, changelog, commit, push, comment, close).'
read_when:
- You need a full issue fix workflow.
---
/fixissue
Purpose: fix an issue end-to-end, with tests and proper follow-through.
Do (in order):
1) Take your time, fix it properly, refactor if necessary.
2) Add regression tests and run them.
3) Add a changelog entry.
4) Commit, pull, and push.
5) Comment on the issue with what changed and close it.
If the issue URL/number isnβt provided, ask for it before the changelog/comment steps.
Location: global prompt lives in ~/.codex/prompts/fixissue.md; this file mirrors it for easy edits.
---
Slash Commands/Handoff
---
summary: 'Codex handoff checklist for agents.'
read_when:
- Creating a /handoff prompt or refining handoff format.
---
/handoff
Purpose: package the current state so the next agent (or future you) can resume quickly.
Include (in order):
1) Scope/status: what you were doing, whatβs done, whatβs pending, and any blockers.
2) Working tree: git status -sb summary and whether there are local commits not pushed.
3) Branch/PR: current branch, relevant PR number/URL, CI status if known.
4) Running processes: list tmux sessions/panes and how to attach:
- Example: tmux attach -t codex-shell or tmux capture-pane -p -J -t codex-shell:0.0 -S -200
- Note dev servers, tests, debuggers, background scripts.
5) Tests/checks: which commands were run, results, and what still needs to run.
6) Next steps: ordered bullets the next agent should do first.
7) Risks/gotchas: any flaky tests, credentials, feature flags, or brittle areas.
Output format: concise bullet list; include copy/paste tmux commands for any live sessions.
Location: global prompt lives in ~/.codex/prompts/handoff.md; this file mirrors it for easy edits.
---
Slash Commands/Landpr
---
summary: 'Land PR end-to-end (temp rebase, full gate, merge, thanks).'
description: Land PR end-to-end (temp rebase, full gate, merge, thanks).
argument-hint: <pr-number|pr-url?>
read_when:
- Landing a PR end-to-end (temp rebase, full gate, merge, thanks).
---
/landpr
Input
- PR: $1 (number or URL). If missing: use most recent PR in convo; if ambiguous: ask.
Goal
- End state: GitHub PR state = MERGED (never CLOSED).
0) Guardrails
- git status -sb clean (no local changes).
- If PR is draft, has conflicts, or you canβt push to head branch: stop + ask.
- Prefer repo default branch as base (often main).
1) Capture PR context
PR="$1"
gh pr view "$PR" --json number,title,state,isDraft,mergeable,author,baseRefName,headRefName,headRepository,maintainerCanModify --jq '{number,title,state,isDraft,mergeable,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,maintainerCanModify}'
prnum=$(gh pr view "$PR" --json number --jq .number)
contrib=$(gh pr view "$PR" --json author --jq .author.login)
base=$(gh pr view "$PR" --json baseRefName --jq .baseRefName)
head=$(gh pr view "$PR" --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view "$PR" --json headRepository --jq .headRepository.url)2) Update base + create temp branch
git checkout "$base"
git pull --ff-only
git checkout -b "temp/landpr-$prnum"3) Checkout PR + rebase onto temp
gh pr checkout "$PR"
git rebase "temp/landpr-$prnum"4) Fix + tests + changelog
- Implement fixes (keep scope tight).
- Add/adjust tests (regression when it fits).
- Update CHANGELOG.md: include #$prnum + thanks @$contrib.
5) Gate (before commit)
- Run full repo gate (lint/typecheck/tests/docs). Example: pnpm lint && pnpm build && pnpm test.
6) Commit
git add CHANGELOG.md <changed files>
git commit -m "fix: <summary> (#$prnum) (thanks @$contrib)"
land_sha=$(git rev-parse HEAD)7) Push rebased PR branch (fork-safe)
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git"
git push --force-with-lease prhead "HEAD:$head"8) Merge PR
- Rebase: gh pr merge "$PR" --rebase
- Squash: gh pr merge "$PR" --squash
- Never gh pr close.
9) Sync base locally
git checkout "$base"
git pull --ff-only9b) Return to main (final local state)
git checkout main
git pull --ff-only
git branch --show-current10) Comment with SHAs + thanks
merge_sha=$(gh pr view "$PR" --json mergeCommit --jq '.mergeCommit.oid')
gh pr comment "$PR" --body "Landed via temp rebase onto $base.- Gate: <cmds>
- Land commit: $land_sha
- Merge commit: $merge_sha
Thanks @$contrib!"
11) Verify state == MERGED
gh pr view "$PR" --json state,mergedAt --jq '.state + \" @ \" + .mergedAt'12) Cleanup
git branch -D "temp/landpr-$prnum"---
Slash Commands/Pickup
---
summary: 'Codex pickup checklist when starting on a task.'
read_when:
- Creating a /pickup prompt or onboarding a new task.
---
/pickup
Purpose: rehydrate context quickly when you start work.
Steps:
1) Read AGENTS.MD pointer + relevant docs (run pnpm run docs:list if present).
2) Repo state: git status -sb; check for local commits; confirm current branch/PR.
3) CI/PR: gh pr view <num> --comments --files (or derive PR from branch) and note failing checks.
4) tmux/processes: list sessions and attach if needed:
- tmux list-sessions
- If sessions exist: tmux attach -t codex-shell or tmux capture-pane -p -J -t codex-shell:0.0 -S -200
5) Tests/checks: note what last ran (from handoff notes/CI) and what you will run first.
6) Plan next 2β3 actions as bullets and execute.
Output format: concise bullet summary; include copy/paste tmux attach/capture commands when live sessions are present.
Location: global prompt lives in ~/.codex/prompts/pickup.md; this file mirrors it for easy edits.
---
Slash Commands/Raise
---
summary: 'Raise next patch Unreleased section in CHANGELOG.md (commit + push).'
read_when:
- You just cut a release and want to open the next patch cycle.
---
/raise
Goal: If CHANGELOG.md top release is dated (not Unreleased), create a new top section for the next patch version as Unreleased, then commit + push only CHANGELOG.md.
0) Guardrails
- Must be on main (or repo default) and git status -sb clean.
- If CHANGELOG.md already starts with ## <version> β Unreleased: stop (nothing to do).
- If the top ## version canβt be parsed as X.Y.Z: stop + ask.
1) Compute next patch
- In CHANGELOG.md, find the first header like: ## X.Y.Z β <date|Unreleased>.
- If suffix is a date (released), bump patch: X.Y.(Z+1).
2) Edit changelog
- Insert at the top (above the last released section):
- ## X.Y.(Z+1) β Unreleased
- blank line
- Do not touch any other release sections.
3) Commit + push
- git add CHANGELOG.md && git commit -m "docs(changelog): start X.Y.(Z+1) cycle"
- git push
4) Verify CI
- GH_PAGER=cat gh run list -L 5 --branch main --json status,conclusion,workflowName,displayTitle,updatedAt
- If any run fails: gh run view <id> --log, fix, commit, push, repeat.
---
Slash Commands/README
---
summary: 'Index of slash commands (prompts) and where they live.'
read_when:
- Auditing or updating slash command docs.
---
Slash Commands
Slash commands are reusable prompt templates that live in ~/.codex/prompts/ (global) and, when present, in repo-local folders (e.g., .claude/commands/, .cursor/commands/). This folder mirrors the global set so agents can discover and edit them in-repo.
Available commands
-
/acceptpr β Land one PR end-to-end (changelog + thanks, lint, merge, back to main).-
/fixissue β Fix an issue end-to-end (tests, changelog, commit, push, comment, close).-
/handoff β Capture current state for the next agent (running sessions, tmux targets, blockers, next steps).-
/landpr β Land PR via temp-branch rebase + full gate (pnpm lint && pnpm build && pnpm test) before commit; merge via gh pr merge (rebase/squash) and verify GitHub state = MERGED (never CLOSED).-
/pickup β Rehydrate context when starting work (status, tmux sessions, CI/PR state).-
/raise β If changelog is released, open next patch Unreleased section (commit + push CHANGELOG.md).-
/sectriage β Finish GHSA triage end-to-end (land fix, run gates, patch advisory via gh api, ready to publish later).See the individual files in this directory for details.
---
Slash Commands/Sectriage
---
summary: "Finish security advisory triage (land fix, gates, GHSA patch, ready-to-publish)."
read_when:
- After discussion, when asked to finish GHSA triage end-to-end.
argument-hint: "<ghsa-or-url?>"
---
/sectriage
Use after discussion. When you say βupdate this on GitHub via ghβ (or you type /sectriage), that is consent for remote writes: I will patch the GHSA via gh api and verify.
Intent
Default intent: land the fix on main directly (commit + push; no PR), update CHANGELOG.md, and keep the GHSA in a βready to publish laterβ state. No separate/private PR workflow unless you explicitly ask.
Invocation Format (you paste, optional)
Prefer minimal. If you only give ghsa (or URL), I will derive the rest from the repo + tags and only ask if something is ambiguous.
- repo: owner/name (optional; default from git remote)
- ghsa: GHSA-.... (or advisory URL)
- severity: low|medium|high|critical
- cvss: full vector string (optional; but include if we want it set/restored)
- affected: human range line for text (example: <= 2026.2.13)
- vuln_range: GitHub structured vulnerable_version_range (example: <=2026.2.13)
- patched_versions: planned fixed version (normally the version youβre about to ship next; from changelog/release prep)
- package: usually openclaw (npm)
- credits: reporter handle (example: @akhmittra)
- fix_commits: one or more full SHAs for internal evidence only (do not place SHAs, PRs, or fix mechanism in public text)
- summary: 1-liner summary (no GHSA id)
- description_md: full Markdown for advisory description (must include an βAffected Packages / Versionsβ section)
What I Do (execute, not suggest)
1. Parse inputs. Derive repo from git remote -v if omitted. Extract GHSA id from URL if needed.
2. Preflight:
- git status --porcelain (must be clean or only expected files)
- fetch advisory via gh api β¦security-advisories/<GHSA> and show current structured fields
- existing fix PR scan (prefer re-use; avoid duplicate fixes):
- if advisory has private_fork.full_name: gh pr list -R <privateFork> --state open
- also search upstream: gh pr list -R <repo> --search "<GHSA>" --state all
- if thereβs a credible fix PR already:
- review via gh pr view / gh pr diff
- fetch PR head branch and cherry-pick commits (avoid local branch switching): git fetch <remote> <headRef> then git cherry-pick <sha>β¦
- fetch latest published versions:
- npm view <pkg> version --userconfig "$(mktemp)"
- update vulnerable_version_range to include that latest version if the issue still exists on main
- fixed-version rule (optimize for βpress publish onlyβ):
- use the planned next release version from CHANGELOG.md (if present) or package.json
- set patched_versions to that planned version even if npm publish hasnβt happened yet
- this keeps the advisory ready so the only follow-up action is βPublishβ after npm is out
3. Local verify (required):
- pnpm check
- pnpm exec vitest run --config vitest.gateway.config.ts
- pnpm test:fast
4. Changelog:
- ensure CHANGELOG.md has ## Unreleased + ### Fixes entry
- no GHSA id mention
- includes thanks to reporter
- ensure wording implies it ships in the next npm release (thatβs the whole point: no more ticket edits)
- commit only if changelog needed changes
5. Git:
- if there are local commits ahead of origin: git pull --rebase then git push
6. Similar-issue scan (read-only):
- list other pathToFileURL( + dynamic import( callsites
- list obvious path-join/resolve callsites
- if I find a credible escape bug: stop and report (do not βsurprise-fixβ during /sectriage)
7. GHSA patch (remote write; invocation is consent):
- write /tmp/ghsa.desc.md from description_md
- required in description_md:
- explicit versions (latest published + affected ranges)
- fix provenance using only release version or patched-version field; no raw SHAs, PR titles/numbers, or fix-mechanism summary in public text
- βRelease Process Noteβ: patched version is pre-set to the planned next release; once npm release is out, just publish the advisory
- write /tmp/ghsa.patch.json with summary, severity, description, and vulnerabilities[]:
- vulnerable_version_range uses latest published npm version (usually <=<npmVersion>)
- patched_versions uses the planned next release version (from changelog/package.json)
- gh api -X PATCH β¦ --input /tmp/ghsa.patch.json
- if cvss provided: patch cvss_vector_string
8. Verify:
- re-fetch advisory, print html_url, state, vulnerabilities, cvss, updated_at
- print GHSA link
Implementation Notes (hard rules)
- Avoid JSON quoting footguns:
- description_md goes to /tmp/ghsa.desc.md
- build JSON via jq -n --rawfile desc /tmp/ghsa.desc.md β¦
- Advisory comments endpoint may not exist via REST; update via description + structured fields.
- State transitions (accept/publish) likely UI/Publisher-only; do not attempt unless you explicitly ask.
- For public advisory text, avoid βFixed byβ / βFix Commit(s)β sections, raw commit hashes, PR titles/numbers, and implementation summaries. Keep exact SHAs and PRs in internal notes.
---
Concurrency
Swift Concurrency (Approachable) - RepoBar Notes
Goal
Practical mental model: isolation first, async/await second.
Core Ideas
-
async/await: pause/resume, not background work.- Isolation domains: who can touch state, not which thread runs code.
- Structured concurrency: prefer
async let / TaskGroup over unstructured Task.- Inheritance: isolation flows from caller to callee unless you opt out.
- Compiler safety: isolation and
Sendable prevent data races.Async/Await (Deep Cut)
-
async marks a function that can suspend.-
await marks a suspension point; code resumes where it paused.-
await only inside async functions.- Sequential
await is serial; use async let for parallel I/O.- Most app work is I/O-bound;
await keeps UI responsive.- CPU-bound work still blocks the current actor unless you opt out.
Tasks (Units of Work)
-
Task {} starts async work from sync code; inherits actor, priority, task-locals.- SwiftUI
.task / .task(id:) auto-cancels when view disappears.-
TaskGroup: dynamic fan-out; child tasks are structured.- Cancellation propagates from parent to children.
- Errors cancel siblings and rethrow when results are consumed.
- Results arrive as tasks finish, not submission order.
- Waits for all: group returns after all children finish or cancel.
-
Task.detached {} inherits nothing (no actor, priority, task-locals); last resort.- Structured concurrency = tree of tasks, easier cleanup + cancellation.
Where Code Runs (Isolation Domains)
-
@MainActor: UI isolation; safe default for app code.-
actor: protects its own mutable state; exclusive access. Not a thread.-
nonisolated: opts out of actor isolation; cannot touch actor state.From Threads to Isolation
- Data race: concurrent access to same memory with at least one write.
- Swift model: isolate data, let compiler enforce boundaries.
- Runtime uses cooperative thread pool (limited to CPU cores); blocking it can deadlock.
- Avoid
DispatchSemaphore.wait() / sync waits in async code.Approachable Concurrency Defaults
-
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor: app starts on MainActor.-
SWIFT_APPROACHABLE_CONCURRENCY = YES: async stays on caller actor.- Xcode 26 enables both by default.
- Use
@concurrent for CPU-heavy work off main actor (Swift 6.2+).Isolation Inheritance Rules
- Functions run on caller isolation unless annotated.
- Closures inherit isolation from definition context.
-
Task {} inherits actor + priority + task-locals.-
Task.detached {} inherits nothing.Sendable (Crossing Boundaries)
-
Sendable types safe across isolation domains.- Structs/enums with
Sendable members are implicitly Sendable.- Actors and
@MainActor types are Sendable.- Classes need
final + immutable stored properties to be Sendable.-
@unchecked Sendable is a promise; wrong == data races.- Do not make everything
Sendable; only cross boundaries when needed.When to Introduce an Actor
- Use only when:
- State is non-
Sendable,- Operations must be atomic,
- It cannot live on an existing actor (often
MainActor).- Otherwise, keep on
@MainActor.Preferred Patterns
- Mark ViewModels
@MainActor by default.-
async let for parallel fetches; TaskGroup for dynamic sets.- Keep state on one actor; cross boundaries only when needed.
- If compiler complains, trace inheritance path.
- Start simple; add complexity only when you hit real problems.
Common Mistakes
- Thinking
async == background; CPU work still blocks without @concurrent.- Overusing
Task.detached instead of structured concurrency.- Creating too many actors for simple app state.
- Spamming
@unchecked Sendable instead of redesigning boundaries.- Calling
MainActor.run instead of annotating the function.- Blocking cooperative pool with semaphores or sync waits.
- Creating
Task inside async functions instead of async let/TaskGroup.Quick Reference
-
async: function can suspend.-
await: suspension point.-
Task {}: start async work, inherits context.-
Task.detached {}: start async work, no inheritance.-
@MainActor: UI isolation.-
actor: isolated mutable state.-
nonisolated: opt out of isolation.-
Sendable: safe to cross boundaries.-
@concurrent: run off main actor (Swift 6.2+).-
async let: parallel work.-
TaskGroup: dynamic parallel work.---
Mac App
---
summary: "Scaffold checklist for a new macOS menu bar app with Sparkle updates"
read_when:
- Scaffolding a new macOS menu bar app with Sparkle.
---
New macOS App Scaffold (Sparkle + DevID + shared release flow)
This is a practical, minimal checklist to get a new macOS (SwiftPM) menubar app ready for distribution via Sparkle and our shared release scripts.
1) Project skeleton
- SwiftPM package with
Resources for assets and Package.swift targeting macOS 15+.- Add Sparkle dependency in
Package.swift:-
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.8.1")- Target dependency:
.product(name: "Sparkle", package: "Sparkle")- Menubar entry point (MenuBarExtra) plus a thin Sparkle wrapper that enables updates only for signed/bundled builds.
2) Bundle identifiers & feeds
- Pick bundle id:
com.steipete.<appname> (no uppercase, no spaces).- Appcast URL:
https://raw.githubusercontent.com/steipete/<Repo>/main/appcast.xml- Embed in Info.plist (or generated plist in packaging script):
-
SUFeedURL = appcast URL-
SUPublicEDKey = Sparkle ed25519 public key (from your key pair)-
SUEnableInstallerLauncherService = true3) Sparkle keys
- Use the existing shared key unless the app must have its own. Keys live outside repos.
- Private key: base64, single line, no comments. Export path via
SPARKLE_PRIVATE_KEY_FILE.- Public key goes into Info.plist. Example shared public key:
AGCY8w5vHirVfGGDGc8Szc5iuOqupZSh9pMj/Qs67XI=4) Packaging & signing scripts (SwiftPM)
- Add
.mac-release.env at repo root with repo-owned metadata, artifact names, feed URL, public key expectation, precheck, and package command.- Add to
Scripts/:-
package_app.sh (build, write Info.plist with bundle id/version/Sparkle keys, codesign in debug or skip if not set).-
sign-and-notarize.sh (release build, DevID sign, notarize, zip app + dSYM, enforce key cleanliness).-
mac-release resolver wrapper that uses MAC_RELEASE_TOOL, sibling ../agent-scripts, or ~/Projects/agent-scripts.-
release.sh thin wrapper around Scripts/mac-release release.-
make_appcast.sh, verify_appcast.sh, check-release-assets.sh, changelog-to-html.sh, and generate-release-notes.sh thin wrappers around matching mac-release commands.-
test_live_update.sh (optional manual update smoke test, gated by RUN_SPARKLE_UPDATE_TEST=1).- Keep
version.env as the single source for MARKETING_VERSION and BUILD_NUMBER.5) Appcast
- Create
appcast.xml with an empty channel header:<?xml version="1.0" standalone="yes"?>
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title><AppName></title>
</channel>
</rss>-
release.sh should insert a new <item> per release (version, build, signature, length, enclosure URL).6) Required env vars for releases
-
SPARKLE_PRIVATE_KEY_FILE (single-line base64 key; no comments)-
APP_STORE_CONNECT_API_KEY_P8, APP_STORE_CONNECT_KEY_ID, APP_STORE_CONNECT_ISSUER_ID- Optional:
RUN_SPARKLE_UPDATE_TEST=1 to force the manual live-update check.7) Release flow (shared pattern)
1.
git status clean.2. Update
version.env + changelog.3.
Scripts/release.sh (runs lint/test, sign/notarize, appcast verify, GH release, asset check, tag/push).4. If
RUN_SPARKLE_UPDATE_TEST=1, perform manual update confirmation.8) Verification checklist
-
verify_appcast_entry passes (signatures & length match).- Enclosure URL returns 200 and matches appcast signature.
-
spctl, codesign --verify --deep --strict, stapler validate pass on the notarized app.- GH release has both zip and dSYM.
- Previous build can update via Sparkle (optional but recommended for major releases).
9) Common gotchas
- Sparkle private key file must not contain comments or blank linesβscripts will fail fast.
- Bundle id must match codesign identity & appcast entry; SUPublicEDKey must match the signing key pair.
- Before zipping a notarized app, run
xattr -cr <App>.app and delete ._* files, then zip with ditto --norsrc -c -k --keepParent β¦ to avoid AppleDouble files that break code signatures. When testing, extract with ditto -x -k (not unzip).- Shared release helpers now always download the enclosure, check the ed25519 signature, and run
codesign --verify + spctl on the extracted app before publishβno env flag needed.- Build numbers must monotonically increase; Sparkle compares
CFBundleVersion.10) Files to add in a new repo
-
version.env-
appcast.xml-
Scripts/: package_app.sh, sign-and-notarize.sh, release.sh, check-release-assets.sh, test_live_update.sh, validate_changelog.sh (if desired)- Update
Package.swift to include Sparkle.With these pieces in place, the app will align with CodexBar/Trimmy/RepoBar release hardening and shared Sparkle verification.
---
Npm Publish With 1password
---
summary: "Publish to npm via tmux + 1Password CLI (op)"
read_when:
- "Need npm publish without copy/paste secrets."
- "Need npm OTP/TOTP from 1Password."
---
npm publish via tmux + op
Goal: publish to npm without pasting tokens/passwords into terminal logs.
Hard rule: do not run op whoami, op item list, op item get, op read, or any other
1Password CLI command directly in a normal shell for this workflow. Use the tmux
session below first, and send every op command through that tmux session. Directop commands can trigger repeated 1Password desktop alerts.
Prereqs
- 1Password desktop app unlocked + CLI integration enabled.
- op installed.
- tmux installed.
tmux session (required)
Use a persistent tmux session so op auth survives across commands.
SOCKET_DIR="${CLAWDBOT_TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/clawdbot-tmux-sockets}"
mkdir -p "$SOCKET_DIR"
SOCKET="$SOCKET_DIR/op-auth.sock"
SESSION="op-auth-$(date +%Y%m%d-%H%M%S)"tmux -S "$SOCKET" new -d -s "$SESSION" -n shell
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op signin" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op whoami" Enter
All commands below assume that same tmux socket/session. If you need to discover
the item name or fields, do it inside tmux too, for example:
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op item list" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op item get '<Item>' --vault '<Vault>'" EnterPreferred: granular automation token (+ optional OTP)
Store a granular npm token in 1Password (item field token), plus TOTP if required.
For Peter's npm account, the 1Password item is op://Private/Npmjs.
TOKEN_REF='op://Private/Npmjs/token'
OTP_REF='op://Private/Npmjs/one-time password?attribute=otp'tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "NODE_AUTH_TOKEN=\"\$(op read \"$TOKEN_REF\" | tr -d \"\\n\")\" npm publish --otp \"\$(op read \"$OTP_REF\" | tr -d \"\\n\")\"" Enter
Notes:
- tr -d "\n" avoids accidental extra submits when pasting/reading.
- Avoid printing token/OTP (no echo, no set -x, no pane capture right after OTP).
If youβre already logged in: OTP-only publish
If npm whoami works, you usually only need OTP for publish:
OTP_REF='op://<Vault>/<Item>/one-time password?attribute=otp'
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "npm publish --otp \"\$(op read \"$OTP_REF\" | tr -d \"\\n\")\"" EnterTip: unset CI tokens so you donβt accidentally override your local login:
env -u NPM_TOKEN -u NODE_AUTH_TOKEN npm whoamiFallback: npm login using op buffers (no echo)
When password auth is unavoidable, avoid typing secrets by piping into tmux
buffers and pasting. Peter's npm account is stored in the 1Password itemNpmjs in the Private vault.
USER_REF='op://Private/Npmjs/name'
PASS_REF='op://Private/Npmjs/password'
EMAIL_REF='op://Private/Npmjs/email'
OTP_REF='op://Private/Npmjs/one-time password?attribute=otp'load buffers (strip trailing newline)
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op read \"$USER_REF\" | tr -d \"\\n\" | tmux -S \"$SOCKET\" load-buffer -b npm_user -" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op read \"$PASS_REF\" | tr -d \"\\n\" | tmux -S \"$SOCKET\" load-buffer -b npm_pass -" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op read \"$EMAIL_REF\" | tr -d \"\\n\" | tmux -S \"$SOCKET\" load-buffer -b npm_email -" Enterrun login; paste at prompts (repeat pattern for Email/OTP)
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "npm login --auth-type=legacy" Enter
tmux -S "$SOCKET" paste-buffer -t "$SESSION":1.1 -b npm_user
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- Enter
tmux -S "$SOCKET" paste-buffer -t "$SESSION":1.1 -b npm_pass
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- Enter
tmux -S "$SOCKET" paste-buffer -t "$SESSION":1.1 -b npm_email
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- Enter
tmux -S "$SOCKET" paste-buffer -t "$SESSION":1.1 -b npm_otp
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- EnterIf the item has duplicate labels, extract by field purpose/type from JSON inside
tmux instead of reading by label:
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op item get Npmjs --vault Private --format json | node -e \"let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{const item=JSON.parse(s);const fields=item.fields||[];const pick=(fn)=>fields.find(fn)?.value||'';process.stdout.write(pick(f=>f.purpose==='USERNAME'))})\" | tmux -S \"$SOCKET\" load-buffer -b npm_user -" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op item get Npmjs --vault Private --format json | node -e \"let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{const item=JSON.parse(s);const fields=item.fields||[];const pick=(fn)=>fields.find(fn)?.value||'';process.stdout.write(pick(f=>f.purpose==='PASSWORD'&&f.type==='CONCEALED'))})\" | tmux -S \"$SOCKET\" load-buffer -b npm_pass -" Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "op item get Npmjs --vault Private --format json | node -e \"let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{const item=JSON.parse(s);const fields=item.fields||[];const pick=(fn)=>fields.find(fn)?.value||'';process.stdout.write(pick(f=>f.label==='email'))})\" | tmux -S \"$SOCKET\" load-buffer -b npm_email -" EnterGotchas:
- If npm says βIncorrect or missing passwordβ, the 1Password password is stale or the paste didnβt reach the prompt.
- Donβt run tmux capture-pane after pasting OTP (it may echo); wait 30β60s if you must debug.
- Repeated reads of the password field can trigger multiple 1Password βpassword used/copiedβ alerts; OTP-only flow avoids that entirely.
Verify
npm whoami
npm view <pkg> versionCleanup
tmux -S "$SOCKET" kill-session -t "$SESSION"
rm -f "$SOCKET"---
RELEASING
---
summary: 'Shared release guardrails (GitHub releases + changelog hygiene)'
read_when:
- Preparing a release or editing release notes.
---
Shared Release Guardrails
- Title every GitHub release as <Project> <version> β never the version alone.
- Release body = the curated changelog bullets for that version, verbatim and in order; no extra meta text.
- Attach all shipping artifacts (zips/tarballs/checksums/dSYMs as applicable) that the downstream clients expect.
- If the repo has its own release doc, follow it; otherwise adapt this guidance to the stack and add a repo-local checklist.
- When a release publishes, verify the tag, assets, and notes on GitHub before announcing; fix mismatches immediately (retitle, re-upload assets, or retag if necessary).
- NPM releases: assume login is already set up; publish may require the userβs 6-digit OTP or it will fail. If OTP/TOTP is in 1Password, prefer op (see docs/npm-publish-with-1password.md).
---
RELEASING MAC
---
summary: 'Reusable macOS release playbook (Sparkle, notarization, GitHub releases)'
read_when:
- Shipping or debugging a macOS release.
---
Releasing macOS Apps (Sparkle + GitHub)
Reusable checklist distilled from recent VibeTunnel, Trimmy, and CodexBar releases. Adapt the script names and paths to the target repo before running anything.
Must read: this master file lives at ~/Projects/agent-scripts/docs/RELEASING-MAC.md. Open it alongside any repo-local release doc and reconcile differences before starting.Scope & Assumptions
- Swift/SwiftUI macOS app shipped outside the App Store, updated via Sparkle (stable + optional prerelease feed).
- Artifacts distributed through GitHub Releases; appcast XML is committed in the repo root.
- Signing uses Developer ID Application cert and ed25519 Sparkle keys; notarization uses App Store Connect API keys.
- Long-running steps (build, notarization, release scripts) should run in tmux/screen to avoid timeouts.
Prerequisites
- Tools: Xcode 16.4+ (or project minimum),
swift toolchain, notarytool, Sparkle CLI (sign_update, generate_keys, generate_appcast), gh.- Credentials in env (export once per session):
-
APP_STORE_CONNECT_KEY_ID, APP_STORE_CONNECT_ISSUER_ID, APP_STORE_CONNECT_API_KEY_P8-
SPARKLE_PRIVATE_KEY_FILE (file-based ed25519 key) and, if used, SPARKLE_ACCOUNT- Repo clean and on main; fast, stable internet for notarization; Apple Developer services green.
- Keep the previous public build installed in
/Applications/<App>.app to verify the Sparkle update path.Versioning Rules
- Single source of truth (e.g.,
version.xcconfig or Info.plist): set both MARKETING_VERSION and CURRENT_PROJECT_VERSION.- Build numbers must monotonically increase; Sparkle compares
CFBundleVersion, not the marketing string. Always bump the build before tagging/publishing and keep the appcast sparkle:version in sync.- Pre-release suffixes (beta/rc) belong in the source-of-truth version before running release scriptsβavoid double-suffix mistakes.
- For npm/pnpm packages, every beta/rc publish must use a new semver with a suffix (e.g.,
1.2.3-beta.1); npm will not let you overwrite an existing version/tag.- If there are sibling surfaces (e.g., web UI), align their versions with the macOS app before releasing.
- Immediately after publishing, add a fresh
Unreleased section and a placeholder for the next patch version at the top of the changelog so new changes donβt land in the shipped section.Prep: Review History & Changelog
- Verify the latest published release/tag on GitHub (ensure assets are present and match the appcast) before starting any new release work.
- Read all commits since that tag (including merges) and skim the diff to capture user-visible changes.
- Curate the changelog before anything else:
- Focus on user-facing changes only; omit other projects, tests, or internal tweaks unless they materially affect users.
- Order entries from most interesting/impactful to least.
- If a feature was added and then removed within the release window, donβt mention it (never shipped).
- If anything is unclear or contentious, ask the user whether to add/remove it.
- After curation, resort the changelog section for the new version so it matches the above guidance.
Pre-flight
1) Sync + sanity
git checkout main && git pull --rebase
git status2) Open the repoβs release doc (if any) and this master file (
~/Projects/agent-scripts/docs/RELEASING-MAC.md); resolve any conflicts in favor of the current project ownerβs direction.3) Update version + changelog (changelog is the release-notes source).
4) Run the projectβs lint/typecheck/tests (e.g.,
swiftformat ., swiftlint --strict, swift test).5) Ensure Sparkle key file exists and do a quick test sign:
echo test > /tmp/sparkle.txt
sign_update -f "$SPARKLE_PRIVATE_KEY_FILE" /tmp/sparkle.txt --account "${SPARKLE_ACCOUNT:-default}"
rm /tmp/sparkle.txt6) Clear stuck DMG volumes if needed:
for v in /Volumes/; do [[ $v == /<App>* ]] && hdiutil detach "$v" -force; doneBuild, Sign, Notarize
- Prefer the repoβs scripted entry point. Common options:
-
./scripts/release.sh stable|beta <n> (handles build β notarize β appcast β release; supports --resume/--status)-
./Scripts/sign-and-notarize.sh (SwiftPM apps; produces <App>-<ver>.zip and staples)- Typical expectations:
- Release (or universal) configuration, arm64 at minimum; some projects also ship universal binaries.
- Sign all nested frameworks/XPCs; use the scriptβs flagsβdo not change
--deep usage unless the script requires it.- Notarization via
notarytool with the exported API key; staple after success.- Before zipping, strip resource forks/extended attributes from the app (
xattr -cr <App>.app && find <App>.app -name '._*' -delete) and zip with ditto --norsrc -c -k --keepParent β¦ to avoid AppleDouble files that invalidate signatures.- Avoid
unzip when testing locally; use ditto -x -k <zip> /Applications to prevent ._* files that break signatures.- The shared release helpers now always download the enclosure, verify the ed25519 signature, and run
codesign --verify plus the system distribution policy check on the extracted app before publishingβno opt-in flag needed. They prefer syspolicy_check distribution and fall back to spctl on older macOS versions.Shared release skill
- Canonical entry point:
~/Projects/agent-scripts/skills/release-mac-app/scripts/mac-release.- Each app repo owns a
.mac-release.env manifest with app metadata, artifact names, feed URLs, key public-key expectation, and repo-local package/precheck commands.- Repo scripts should call a checked-in
Scripts/mac-release resolver, which uses MAC_RELEASE_TOOL, a sibling ../agent-scripts checkout, or ~/Projects/agent-scripts.- Release scripts should be thin wrappers around
Scripts/mac-release commands (release, make-appcast, verify-appcast, check-assets, changelog-html, notes).-
release/sparkle_lib.sh is a compatibility shim only; do not build new app integrations on it.-
mac-release release checks a clean tree, finalized changelog, monotonic appcast version/build, Sparkle key/public-key match, precheck command, package command, appcast generation/verification, GitHub release assets, and optional live update smoke.Sparkle Signing & Appcast
Policy: Ship full updates only (no deltas). Remove any
<sparkle:deltas> blocks before publishing the appcast.1) Generate signature for the shipping artifact (DMG or ZIP):
sign_update -f "$SPARKLE_PRIVATE_KEY_FILE" path/to/<App>-<ver>.dmg --account "${SPARKLE_ACCOUNT:-default}"2) Update the correct appcast (stable vs prerelease). Ensure:
-
sparkle:shortVersionString == marketing version-
sparkle:version == build number (unique and increasing)-
sparkle:edSignature matches the signature you just generated3) If scripts exist (
generate-appcast.sh, make_appcast.sh, etc.), use them; otherwise edit appcast XML carefully using the existing entry as a template.4) Validate signatures and feed:
- Run any helper (
./scripts/validate-sparkle-signature.sh) if provided.-
sign_update -p <zip> output matches sparkle:edSignature in the appcast.- Doubleβcheck you used the correct key account:
sign_update --account <app-account> -p <zip> must match the appcast signature, and the appβs SUPublicEDKey must be the public key for that account.-
curl -I "<enclosure-url>" returns 200.-
curl "<appcast-url>" | head shows the new build number/signature/length.- Verify update flow using the previous installed build and Sparkle UI.
GitHub Release & Tag
1) Tag the release after artifacts are ready:
git tag v<version> (or let the release script tag).2) Create the GitHub release (pre-release for betas), title
<App> <version>, body = changelog section for that version.3) Upload artifacts: DMG/ZIP and the dSYM archive (zip it and attach alongside the main artifact for symbolicated crash debugging). Upload the appcast if it is served via Releases. Ensure enclosure URLs in the appcast point to the uploaded assets and return 200/OK. The shared helpers already re-download the enclosure and run codesign/spctl; if the repo ships a release check script (e.g.,
Scripts/check-release-assets.sh), run it after publishing to verify both zip and dSYM are present.4) Release notes correctness:
- Header must be exactly
<App> <version> β no prefixes/suffixes.- Body must be a copy of the curated changelog for that version (user-facing items only, same order).
- Confirm every bullet from the changelog is present; nothing extra.
5) Push tags/commits once appcast and release notes are correct.
6) After verifying GitHub uploads, delete local release artifacts (ZIP/DMG/dSYM archives) from the repo workspaceβdo not leave binaries checked out or staged. Keep only committed source/doc changes.
7) Post-release bookkeeping: edit
CHANGELOG.md to add Unreleased plus the next patch version header (e.g., if 0.5.3 shipped, add 0.5.4 β Unreleased) so upcoming changes have a landing spot.Verification (Definition of Done)
- Download the published artifact, install via
ditto, launch, and verify:-
syspolicy_check distribution <App>.app (or spctl --assess --type execute --verbose <App>.app on older macOS versions)-
codesign --verify --deep --strict --verbose <App>.app-
stapler validate <App>.app- Check Sparkle update path from the previous installed build (stable and prerelease if applicable).
- Curl the appcast and enclosure URL; confirm the new entry, correct build number, and non-404 asset.
- Spot-check artifact size against recent releases to catch bundled dev files.
- For multi-surface apps, confirm version strings match across app UI and companion surfaces.
- GitHub release notes verified: header is
<App> <version> only; body matches changelog bullets and order.- Sparkle verification complete: signatures match, appcast entry correct, update tested from prior build when possible.
- Appcast/cache note: if Sparkle still reports the old version, relaunch/wait briefly (feed caching) before retagging; fix build/appcast first. The appcast is the single source of truth for published versionsβkeep it authoritative; avoid parallel βtracking tables.β
Final Sign-Off (agent handoff)
- Re-read the GitHub release page: title exactly
<App> <version>; body matches the curated changelog (no missing/extra bullets).- Re-open the appcast in a browser/
curl to confirm the new entry, signature, and enclosure URL are present and 200/OK.- Confirm local checks: system distribution policy,
codesign, and stapler on the downloaded artifact; app launches; update path works from previous build.- Log any deviations or manual fixes (e.g., regenerated signature) in the task notes before handing off.
Recovery / Resume
- If a scripted release stops mid-flight, rerun with
--resume or consult any .release-state the script writes.- After notarization success but before publish, you can recover manually:
1) Create DMG/ZIP if missing (
./scripts/create-dmg.sh or ./Scripts/package_app.sh).2) Sign with Sparkle (
sign_update -f β¦).3) Manually edit appcast with the new signature.
4) Create/repair the GitHub release and push appcast changes.
One-Page Checklist
- [ ] Opened repo-local release doc and this master guide (
~/Projects/agent-scripts/docs/RELEASING-MAC.md); resolved any conflicts.- [ ] Version + build number updated in the single source of truth (and synced to any sibling surfaces).
- [ ] Changelog entry authored for this version.
- [ ] Lint/typecheck/tests green.
- [ ] Sparkle key verified with test sign_update.
- [ ] Release script run (or build + sign + notarize completed).
- [ ] Sparkle signature generated with
-f and applied to appcast; build number unique.- [ ] Verify the published enclosure matches the appcast entry:
curl -L -o /tmp/update.zip <enclosure-url> && sign_update --verify /tmp/update.zip <appcast-signature> -f "$SPARKLE_PRIVATE_KEY_FILE" (fails if the wrong key/signature is used).- [ ] Tag + GitHub release created; assets uploaded; URLs in appcast resolve (200/OK).
- [ ] After publishing, bump
CHANGELOG.md: move the shipped notes under the released version, increment its patch number, and start a new Unreleased section for the next patch.- [ ] Downloaded artifact passes system distribution policy,
codesign, and stapler; no ._* files.- [ ] Update flow validated from a previous version (if appcast was edited, re-run a live update after the change to confirm the new signature is accepted; clear
~/Library/Caches/com.<bundle-id> if Sparkle cached a bad download).- [ ] Appcast shows the correct notes (single-version chunk), and artifact size looks sane.
- [ ] GitHub release notes header is
<App> <version> and body matches changelog bullets exactly.- [ ] Manual Sparkle verification done (signature comparison, appcast curl, optional live update test).
- [ ] Local release artifacts (ZIP/DMG/dSYM zips) removed from the repo workspace after upload/verification.
---
Slash Commands
---
summary: 'Slash commands overview and redirect to docs/slash-commands.'
read_when:
- Editing or adding slash commands.
---
Slash Commands
Moved to docs/slash-commands/. See docs/slash-commands/README.md for the index.
1. Create a markdown file in ~/.codex/prompts/:
echo "# /mycommand\n\nYour prompt instructions..." > ~/.codex/prompts/mycommand.md2. Use the command in any Codex/Claude Code session:
/mycommand3. The agent will execute the prompt from the file
Best Practices
- Be specific: Include exact commands, safety checks, and exit conditions
- Document constraints: No destructive git, coordination rules, scope boundaries
- Make them reusable: Avoid task-specific details (dates, ticket numbers)
- Test them: Run the slash command to verify it works as expected
- Version control: Consider storing project-specific commands in .claude/commands/ (repo-local)
Project-Local Commands
For project-specific workflows, you can also create commands in the repo root:
.claude/commands/ - For Claude Code.cursor/commands/ - For Cursor AI
These are checked into version control and shared with the team.
This Project's Commands
This repository includes the following commands in both .claude/commands/ and .cursor/commands/:
.claude/commands/ .cursor/commands/
βββ automerge.md βββ automerge.md
βββ build.md βββ build.md
βββ commit.md βββ commit.md
βββ commitgroup.md βββ commitgroup.md
βββ improve.md βββ improve.md
βββ fix.md βββ fix.md
βββ massageprs.md βββ massageprs.mdAvailable commands:
- /automerge - Automated PR review & merge
- /build - Build validation with fixes
- /commit - Selective commit helper
- /commitgroup - Group multiple commits logically
- /cppp - Commit all changes in grouped commits and push
- /different - Post-review reflection: what would you change?
- /doit - Enter autonomous coding mode and execute the plan
- /improve - Post-ship retro helper
- /fix - Run quality checks & fix all failures
- /massageprs - Continuous PR maintenance loop
These commands work identically in both Claude Code and Cursor.
---
Subagent
---
summary: 'Multi-agent system directives and coordination rules. Master reference for agent behavior.'
read_when:
- Coordinating subagents or running tmux-based agent sessions.
---
Claude Subagent Quickstart
CLI Basics
- Launch long-running subagents inside tmux so the session can persist. Example:
tmux new-session -d -s claude-haiku 'claude --model haiku'
tmux attach -t claude-haiku Once inside the session, run /model to confirm the active alias (haiku maps to Claude 3.5 Haiku) and switch models if needed.
- Need to queue instructions without attaching? Use tmux send-keys -t <name> "your command" Enter to inject text into a running agent session.
- Always switch to the fast Haiku model upfront (claude --model haiku --dangerously-skip-permissions β¦ or /model haiku in-session) to keep turnaround fast.
- Two modes:
- One-shot tasks (single summary, short answer): run claude --model haiku --dangerously-skip-permissions --print β¦ in a tmux session, wait with sleep 30, then read the output buffer.
- Interactive tasks (multi-file edits, iterative prompts): start claude --model haiku --dangerously-skip-permissions in tmux, send prompts with tmux send-keys, and capture completed responses with tmux capture-pane. Expect to sleep between turns so Haiku can finish before you scrape the pane.
- A manual supervisor loop can launch Claude the same way (claude --dangerously-skip-permissions "<prompt>") to keep tmux automation flowing.
One-Shot Prompts
- The CLI accepts the prompt as a trailing argument in one-shot mode. Multi-line prompts can be piped:
echo "..." | claude --print.- Add
--output-format json when you need structured fields (e.g., summary + bullets) for post-processing.- Keep prompts explicit about reading full files: βRead docs/example.md in full and produce a 2β3 sentence summary covering all sections.β
Bulk Markdown Conversion
- Produce the markdown inventory first (
pnpm run docs:list) and feed batches of filenames to your Claude session.- For each batch, issue a single instruction like βRewrite these files with YAML front matter summaries, keep all other content verbatim.β Haiku can loop over multi-file edits when you provide the explicit list.
- After Claude reports success, diff each file locally (
git diff docs/<file>.md) before moving to the next batch.Supervisor Loop Notes
- There is no checked-in Ralph helper in this repo. For supervisor/worker loops, launch the worker in tmux and drive it with
tmux send-keys.- Supervisor responses should end with an explicit next action such as
CONTINUE, SEND: <message>, or RESTART so the operator can route the next turn without ambiguity.---
Update Changelog
---
summary: 'Checklist for curating CHANGELOG.md from recent commits'
read_when:
- Updating CHANGELOG.md or drafting release notes.
---
Update CHANGELOG.md
Purpose: curate user-facing changes since the last release tag and record them in CHANGELOG.md (Unreleased section) for this repo. Derived from the /update-changelog prompt, the macOS release notes guide, and CodexBar/Trimmy AGENTS notes.
Scope & Inputs
- Read the repoβs
AGENTS.MD first (and the repo-local release doc if it exists, e.g., docs/RELEASING.md in app projects).- Baseline version: use the provided baseline; otherwise the latest tag from
git describe --tags --abbrev=0.- Target file: the repoβs
CHANGELOG.md (keep Trimmy/CodexBar entries app-specific).Steps
1) Pick baseline
- If none given:
git describe --tags --abbrev=0 β <tag>.2) Collect commits since baseline
git log <tag>..HEAD --oneline --reverseSkim the diff as needed to understand user-visible impact.
3) Curate entries (user-facing only)
- Include: shipped features, fixes, breaking changes, notable UX or behavior tweaks.
- Exclude: internal refactors, typo-only edits, dependency bumps without user impact, features added then removed in the same window.
- Order by impact: breaking β features β fixes β misc.
- Add PR/issue numbers when available (
#123)βif you work commit-only, skip the reference and keep the bullet concise (avoid raw hashes).- For Trimmy and CodexBar: changelog must stay user-focused; add entries only relevant to that app.
4) Edit
CHANGELOG.md- Ensure there is an
## Unreleased section at the top; create it if missing.- Append bullets under
Unreleased; keep existing style (bullets, past-tense verbs or short descriptors, code in backticks).- If preparing a release, keep the βUnreleasedβ block separate from the versioned section and move the curated notes under the new version when tagging.
5) Sanity checks
- Markdown renders; no duplicate entries; wording concise.
- If a release just shipped, start a fresh
Unreleased section for the next patch (per docs/RELEASING-MAC.md guidance).Quick format example
Unreleased
- Added configurable status probe refresh interval. #123
- Fixed menu bar icon dimming on sleep/wake. #128---
Windows
---
summary: "Windows setup notes for running agent scripts"
read_when:
- Working on Windows or PowerShell setups for agent scripts.
---
Windows notes
- Install Git for Windows and ensure git is on PATH.
- Install Bun (needed to run the Bun-based shims in bin/): irm https://bun.sh/install.ps1 | iex. The installer drops bun.exe in %USERPROFILE%\.bun\bin and adds it to the user PATH; restart shells to pick it up.
- Running the shims from PowerShell:
- bun bin/docs-list
Note: Windows may not honor the UNIX shebang line when launching shims inbin/directly. Usingbun bin/<tool> ...is the most reliable cross-shell invocation.
---
CHANGELOG
---
summary: Timeline of guardrail helper changes mirrored from Sweetistics and related repos.
---
Changelog
Unreleased
- Added headless Sparkle signing through scoped 1Password references, with public-key validation, mode-0600 temporary files, and cleanup on success or failure.
- Corrected GitHub secret provisioning to omit --body for stdin and added a skill validation guard against the literal-dash trap.
- Taught the clawsweeper-status snapshot to report queue handoff health, the ready/admissible split, backoff and parked reasons, and shed-since-reset, so exact-review items parked on retry exhaustion are no longer invisible behind a healthy verdict.
- Added the project-structure skill: a TypeScript symbol-map generator that compresses a repository into one context-loadable file with dense/skeleton/exports tiers, plugin-boundary listings, and measured token budgets.
- Removed the obsolete scoped-commit helper and returned commit recipes to standard Git now that agent work uses isolated worktrees.
- Made the million-token Codex provider and context settings an explicit atomic invariant, with a fatal preflight diagnostic for the unrecoverable openai plus 922K/700K split configuration.
- Added a fleet audit and repair action that disables Claude commit, pull-request, and session-link attribution while preserving unrelated settings and detecting higher-precedence overrides.
- Added narrow Homebrew 6 trust handling for exact third-party formulae already declared in a fleet profile.
- Made Apple-classified outdated/unusable Xcode runtimes and unavailable simulator devices required fleet drift, with a booted-device-safe audit and repair action.
- Established the SF Mini's classic OpenSSH fleet path, documented symmetric tailnet TCP 22 policy and proof rules, and recorded the MiniClaw duplicate-daemon regression and public-SSH fallback.
- Added the separately owned SF Mac Mini and distinguished its local/Tailscale names from FoundationClaw while its trusted SSH path remains pending.
- Verified FoundationClaw's provider identity, installed Tailscale and Jump Desktop Connect v10, and documented its data-preserving credential-reset escalation before GUI activation.
- Added ClawMac provider-outage triage that escalates console, NIC-link, and switch-port inspection without repeated power cycles or data-affecting recovery.
- Restored MiniClaw's canonical Homebrew Tailscale node and removed its duplicate GUI identity from fleet guidance.
- Removed obsolete Mac identities from remote fleet discovery guidance after pruning them from Tailscale.
- Reconciled the remote-Mac topology with provider purchases, including FoundationClaw's MacStadium identity and MiniClaw's canonical Tailscale identity.
- Reserved GPT-5.6's maximum output budget in codex-huge-context and moved fleet compaction to a verified 922K input window with a 700K safety threshold.
- Made codex-first treat the Gorilla-backed Clawdex endpoint as already model-routed, preventing recursive Codex delegation after the fleet proxy migration.
- Added a secret-safe Codex direct-API preflight so million-token launches fail before an unauthenticated Responses request when a machine is missing its Keychain delivery copy.
- Generalized interactive 1Password routing to select the active approval workstation within the matching personal or work-managed environment while preserving service-account isolation and safe offline fallback.
2026-07-17 β 0.12.0
Highlights
- Turned
maintainer-orchestrator into a long-running control plane for autonomous queue triage, proof-driven changes, dependency maintenance, and release proposals across Peter's repositories.- Added fleet maintenance, safe repository synchronization, package ownership audits, and Xcode fleet management for Peter's Macs.
- Replaced the old Codex review path with isolated structured autoreview and added Claude Code-only
codex-first delegation for implementation-heavy work.- Added
scripts/sync-skills so Codex and Claude share one canonical skill and instruction mirror across agent-scripts, manager, and repo-owned skills.- Hardened 1Password, npm, and macOS release workflows around scoped service access, stable tool identities, noninteractive signing, and verified publication boundaries.
Maintainer Orchestration
- Expanded
maintainer-orchestrator with one tracked Codex thread per repository, 30-lane scheduling, durable status, forgotten-work preservation, exact-head landing, dependency sweeps, VISION capture, and release-readiness proposals.- Added a dedicated OpenClaw mode with root-owned discovery, qualified execution lanes, contributor routing, live permission checks, serialized landing, and OpenClaw-specific proof and changelog rules.
- Added autonomous GitHub queue triage with URL-first item briefs, maintainer-comment routing, author context, live proof requirements, safe spam closure, and explicit Peter decision briefs.
- Added the non-majority repository ledger, owner-maintained crawl-family overrides, and clearer root ownership for orchestration policy and worker titles.
- Made dependency updates, internal operating repositories, bounded cleanup, safe dirty fast-forwards, and candidate-scoped release blockers autonomous.
- Improved ClawSweeper status reporting for worker capacity, exact-review occupancy, workflow waiters, bounded API reads, and accurate failure and closure counts.
- Tightened shared agent policy around exact-head proof, contributor credit, screenshot safety, post-merge recaps, background-task visibility, public mutation, and release authority.
Review and Agent Workflows
- Replaced
codex-review with structured autoreview, adding isolated Codex, Claude, and Pi review, safe bundle validation, regression provenance, security checks, parallel tests, and bounded multi-pass review.- Added Claude Code-only
codex-first routing for implementation, fixing, exploration, rebasing, and landing mechanics, including safe use of the ChatGPT app-bundled Codex CLI. Thanks @notorious-d-e-v.- Added current model, effort, fast-mode, liveness, deterministic resume, and self-delegation guardrails to the Codex workflow.
- Made GitHub deep review and project triage prefer current source, real behavior reproduction, exact PR heads, and factual contributor trust signals.
- Routed screenshot and login-dependent browser work through existing Chrome state, with safe attach recovery and no silent isolated-browser fallback.
- Added explicit compatibility contracts, clean bounded-refactor guidance, generated-code skepticism, and scoped opportunistic cleanup rules.
Fleet, Release, and Remote Operations
- Added
fleet-maintenance for host health, package updates, repository synchronization, ownership collisions, disk cleanup, and service-impact reporting.- Added
xcode-sync for signed Xcode inventory, stable and prerelease slot management, build-identity checks, platform compatibility, and verified installation.- Added dependency-light fleet repo audit and update helpers with batched snapshots, clean fast paths, dirty-work preservation, collision checks, and safe fast-forwards.
- Added
release-mac-app and shared macOS release helpers for changelog notes, Sparkle appcasts, signing, notarization, GitHub assets, and post-release verification.- Hardened macOS releases for passwordless isolated keychains, preloaded secrets, modern distribution validation, Bash 3.2, lightweight tags, bracketed changelog versions, and archive version parsing.
- Refreshed remote-Mac topology and network-boundary guidance, signed local app testing, locked-Mac Git fallback, and Cloudflare-only ClickClack deployment.
- Kept GitHub reads on the Octopool shim and added cache-health recovery before live GitHub fallback.
Credentials and Safety
- Unified 1Password work on one tracked tmux session with scoped service-account access first, consent-gated desktop fallback, exact-field reads, known-item routing, and TCC-safe
~/bin/op updates.- Unified npm authentication around reusable service sessions, safe field selection, token caching, login fallback, package reservation, publication verification, and a generic authenticated command wrapper.
- Added internal-information, confidentiality, device-aware image upload, API-key storage, and approved-destination guardrails without blocking authorized private research.
- Standardized the canonical test Gmail account, OpenClaw deployment account, personal versus corporate Mac routing, and pre-approved Gmail service login behavior.
Skills and Tools
- Added
scripts/sync-skills to build Codex whole-root links, Claude's flat skill mirror, shared instruction pointers, deterministic collision handling, and stale-link pruning.- Added skills for fleet maintenance, Xcode sync, Codex delegation, Twilio SMS, Wrangler, Things, Reminders, SSH diagnosis, agent transcripts, and shared macOS releases.
- Added
skill-cleaner inventory, duplicate, usage, and prompt-budget audits plus isolated --root-only scans. Thanks @its-How.- Added browser-tools network capture with filtering and follow mode. Thanks @mvanhorn.
- Hardened browser-tools startup, profile copying, symlink handling, and console flags. Thanks @ShiroKSH.
- Fixed xurl's OpenClaw npm installer metadata. Thanks @not-stbenjam.
- Made skill validation explicitly UTF-8-safe under C locales. Thanks @chaochaoweb3.
- Added skills.sh grouping metadata for shared skills. Thanks @vyctorbrzezowski.
- Exposed shared behavior validation, session viewing, crabbox, and crawl-family skills through the canonical mirror while removing duplicated bundled copies.
2026-05-14 β Video Transcript Dependency Update
- Updated
video-transcript-downloader to youtube-transcript-plus 2.0.0.2026-05-14 β Codex Review Finding Detection
- Updated
codex-review to capture review output, report elapsed time, fail on reported P0-P3 findings, and treat empty review output as non-clean.2026-05-14 β Codex Review Full Access
- Added
codex-review --full-access for nested review runs that need localhost bind/listen tests without sandbox noise.2026-05-14 β GitHub Search Shim Guidance
- Added AGENTS guidance to prefer shimmed
gh / gitcrawl gh for broad reads and avoid raw Search API POST mistakes.2026-05-14 β Codex Review Base Caveat
- Documented that
codex review --base must not include an inline prompt; use a separate follow-up pass for custom instructions.- Clarified that committed or PR branch review must use branch/base mode, not
--uncommitted / local mode.2026-05-14 β Codex Review Loop Guidance
- Clarified that
codex-review should iterate until no accepted findings remain and document intentional rejections with useful inline comments when warranted.2026-05-14 β README Skills Overview
- Rewrote the README around agent instructions, skills, helper scripts, and sync expectations; removed stale copied-origin notes.
2026-05-14 β Codex Review Skill
- Added a
codex-review skill and helper for closeout reviews, with stdout-only default output and subagent filtering guidance for noisy review output.2026-05-13 β Checkout Discipline
- Added CLI checkout/worktree guardrails: stay in repo cwd by default, never create worktrees unless asked, and treat sibling checkouts under
~/Projects as user-managed.2026-05-13 β Skill Metadata Guardrails
- Added generic skill-description guidance and quieter browser recovery notes to reduce noisy auth prompts and token-heavy skill metadata.
2026-05-11 β clawmac GUI Access Note
- Documented the Peekaboo through Jump Desktop workflow for clawmac GUI prompts and Chrome Safe Storage verification.
- Documented
crabmac as Peter's typo/alias for clawmac.2025-12-22 β Remove Custom rm Shim
- Dropped
bin/rm and scripts/trash.ts; rely on the system trash command for recoverable deletes.2025-12-17 β Remove Runner; Keep Guardrails
- Removed the
runner wrapper and scripts/runner.ts now that modern Codex sessions handle long-running/background work directly.- Kept the safety-critical bits as standalone shims:
bin/rm (moves deletes to Trash via scripts/trash.ts).- Dropped the
find -delete interception and the bin/sleep shim.2025-12-02 β Release Preflight Helpers
- Added shared release helpers in
release/sparkle_lib.sh: clean working-tree check, Sparkle key probe, changelog finalization/notes extraction, and appcast monotonicity guard for version/build.- Documented the helper functions in
docs/RELEASING-MAC.md so Trimmy/CodexBar-style release scripts can reuse them.2025-11-18 β Console Log Capture
- Added
console command to scripts/browser-tools.ts for capturing and monitoring Chrome DevTools console output with real-time formatting, type filtering (log, error, warn, etc.), continuous follow mode, and configurable timeouts with automatic object serialization.2025-11-22 β Search & Content Extraction
- Added
search and content commands to scripts/browser-tools.ts for Google SERP scraping with optional readable markdown extraction and single-URL readability output, leveraging the existing DevTools-connected Chrome instance.-
eval now supports --pretty-print to inspect complex objects with indentation and colors.2025-11-15 β Chrome Browser Tools
- Added
scripts/browser-tools.ts, a DevTools-ready Chrome helper copied from the Oracle repo so agents can inspect, screenshot, and terminate sessions without dragging in the full CLI. The workflow is inspired by Mario Zechnerβs βWhat if you donβt need MCP?β.- Documented the new helper in the README so downstream repos know how to run
pnpm tsx scripts/browser-tools.ts --help.2025-11-16 β Browser Tools Pipe Detection
- Updated
scripts/browser-tools.ts to enumerate and kill Chrome instances started with --remote-debugging-pipe (the default for Peekaboo/Tachikoma) in addition to the classic --remote-debugging-port. List/kill now show βdebugging pipeβ when no port exists and still fetch tab metadata when it does.- README now notes the optional
NODE_PATH=$(npm root -g) trick so the helper can run from bare copies of the repo without a local package.json.2025-11-14 β Compact Runner Summaries
- The runner's completion log now defaults to a compact
exit <code> in <time> format so long commands don't repeat the entire input line.- Added the
RUNNER_SUMMARY_STYLE env var with compact (default), minimal, and verbose options so agents can pick how much detail they want without editing the script.- Timeout heuristics now understand both
pnpm and bun invocations automatically, so long-running Bun scripts/tests get the same guardrails without repo-specific patches.-
sleep invocations longer than 30 seconds are clamped to the 30s ceiling instead of erroring, which keeps wait hacks working while still honoring the AGENTS.MD limit.2025-11-08 β Sleep Guardrail & Git Shim Refresh
- Runner now rejects any
sleep argument longer than 30 seconds, mirroring the AGENTS rule and preventing long blocking waits.- Added
bin/sleep so plain sleep calls automatically route through the runner and inherit the enforcement without extra flags.- Simplified
bin/git to delegate directly to the runner + system git, eliminating the bespoke policy checker while keeping consent gates identical.2025-11-08 β Guardrail Sync & Docs Hardening
- Synced guardrail helpers with Sweetistics so downstream repos share the same runner, docs-list helper, and supporting scripts.
- Expanded README guidance around runner usage, portability, and multi-repo sync expectations.
- Tightened path ignores and refreshed misc. helper utilities (e.g.,
toArray) to reduce drift across repos.2025-11-08 β Initial Toolkit Import
- Established the repo with the Sweetistics guardrail toolkit (runner, git policy enforcement, docs-list helper, etc.).
- Ported documentation from the main product repo so other projects inherit the identical safety rails and onboarding notes.
---
README
Agent Scripts
Shared agent instructions, skills, and small portable helpers for Peter's local workspaces.
This repo is the canonical place for:
- AGENTS.MD: shared hard rules for Codex/Claude-style agents
- skills/: reusable workflow skills, including repo-owned skills exposed by symlink
- scripts/: dependency-light helpers used across projects
- hooks/: local guardrails such as skill validation
Skills
Skills are the main routing layer. Each skills/<name>/SKILL.md has YAML front matter:
---
name: skill-name
description: "Short generic trigger phrase."
---Rules:
- Keep descriptions short and generic; optimize for routing, not documentation.
- Keep skill bodies terse and operational.
- Prefer helper scripts under skills/<name>/scripts/ when a workflow has repeatable commands.
- Validate after edits: scripts/validate-skills.
- Quote description in front matter.
Global discovery is built by scripts/sync-skills (idempotent; run on every Mac after cloning or adding skills):
- Codex scans nested dirs, so it gets whole-root links: ~/.codex/skills/agent-scripts -> ~/Projects/agent-scripts/skills, ~/.codex/skills/manager -> ~/Projects/manager/skills.
- Claude Code loads only ~/.claude/skills/<name>/SKILL.md (exactly one level deep; per-entry symlinks are followed, category subfolders are not scanned β verified on 2.1.197). It gets a flat per-skill link mirror covering both repos plus machine-local ~/.codex/skills/<name> extras.
- Name collisions resolve agent-scripts > manager > codex-local; the script prints skipped duplicates and prunes broken/stale managed links.
Shared personal skills live as real folders in skills/. Public OpenClaw shared skills live in ../agent-skills and are exposed here with tracked relative symlinks. Repo-owned skills stay canonical in their repo and are exposed here the same way, for example:
skills/autoreview -> ../../agent-skills/skills/autoreview
skills/discrawl -> ../../discrawl/.agents/skills/discrawlCurrent symlinked repo-owned skills include birdclaw, discrawl, gog, imsg, slacrawl, wacli, and wacrawl.
Agent Instructions
Shared hard rules live in AGENTS.MD.
Global setup (also maintained by scripts/sync-skills; Claude Code reads CLAUDE.md only, so it links to the shared AGENTS.MD):
- ~/.codex/AGENTS.md -> ~/Projects/agent-scripts/AGENTS.MD
- ~/.claude/CLAUDE.md -> ~/Projects/agent-scripts/AGENTS.MD
- ~/.claude/AGENTS.md -> ~/Projects/agent-scripts/AGENTS.MD
Downstream repos should use a pointer-style AGENTS.MD:
READ ~/Projects/agent-scripts/AGENTS.MD BEFORE ANYTHING (skip if missing).Repo-specific rules go below that pointer. Do not copy the shared blocks into downstream repos.
Helpers
scripts/sync-skills
- Builds the per-machine skill mirror: Codex whole-root links, Claude flat per-skill links, shared AGENTS.MD pointers.
- Idempotent; prints changes only, prunes broken/stale managed links, never clobbers real files.
scripts/validate-skills
- Checks every skills/*/SKILL.md.
- Verifies YAML front matter plus required name and description.
- Enable as a local hook with git config core.hooksPath hooks.
scripts/docs-list.ts
- Walks docs/.
- Enforces summary and read_when front matter.
- Prints onboarding summaries for repos that wire it in.
scripts/browser-tools.ts
- Standalone Chrome DevTools helper.
- Common commands: start --profile, nav <url>, eval '<js>', screenshot, console, network, search --content "<query>", content <url>, inspect, kill --all --force.
- Build optional binary with bun build scripts/browser-tools.ts --compile --target bun --outfile bin/browser-tools.
Syncing
Treat this repo as canonical for shared agent rules and portable helper scripts.
When syncing downstream repos:
- Pull latest here first.
- Ensure each target repo starts with the pointer-style AGENTS.MD.
- Preserve repo-local rules below the pointer.
- Copy helper changes both directions only when the helper is meant to stay byte-identical.
- Keep scripts dependency-free and portable; no repo-specific imports or path aliases.
For submodules, repeat the pointer check inside each subrepo, push those changes, then bump submodule SHAs in the parent repo.
---