### 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 --json number,title,author,baseRefName,headRefName,isDraft,mergeable,maintainerCanModify` - Skim: `gh pr view --comments` and `gh pr diff ` 2) Checkout + suggested fixes - `gh pr checkout ` - 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.: `- (#) — thanks @` - 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 --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 --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: 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 ```sh 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 ```sh git checkout "$base" git pull --ff-only git checkout -b "temp/landpr-$prnum" ``` 3) Checkout PR + rebase onto temp ```sh 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 ```sh git add CHANGELOG.md git commit -m "fix: (#$prnum) (thanks @$contrib)" land_sha=$(git rev-parse HEAD) ``` 7) Push rebased PR branch (fork-safe) ```sh 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 ```sh git checkout "$base" git pull --ff-only ``` 9b) Return to `main` (final local state) ```sh git checkout main git pull --ff-only git branch --show-current ``` 10) Comment with SHAs + thanks ```sh merge_sha=$(gh pr view "$PR" --json mergeCommit --jq '.mergeCommit.oid') gh pr comment "$PR" --body "Landed via temp rebase onto $base. - Gate: - Land commit: $land_sha - Merge commit: $merge_sha Thanks @$contrib!" ``` 11) Verify state == `MERGED` ```sh gh pr view "$PR" --json state,mergedAt --jq '.state + \" @ \" + .mergedAt' ``` 12) Cleanup ```sh 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 --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 `## — 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 — `. - 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 --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: "" --- # /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/` 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 --state open` - also search upstream: `gh pr list -R --search "" --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 ` then `git cherry-pick …` - fetch latest published versions: - `npm view 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 `<=`) - `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.` (no uppercase, no spaces). - Appcast URL: `https://raw.githubusercontent.com/steipete//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` = true ## 3) 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 <AppName> ``` - `release.sh` should insert a new `` 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` 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. Direct `op` 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. ```bash 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: ```bash 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 '' --vault ''" Enter ``` ## Preferred: 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`. ```bash 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: ```bash OTP_REF='op:////one-time password?attribute=otp' tmux -S "$SOCKET" send-keys -t "$SESSION":1.1 -- "npm publish --otp \"\$(op read \"$OTP_REF\" | tr -d \"\\n\")\"" Enter ``` Tip: unset CI tokens so you don’t accidentally override your local login: ```bash env -u NPM_TOKEN -u NODE_AUTH_TOKEN npm whoami ``` ## Fallback: `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 item `Npmjs` in the `Private` vault. ```bash 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 -" Enter # run 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 -- Enter ``` If the item has duplicate labels, extract by field purpose/type from JSON inside tmux instead of reading by label: ```bash 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 -" Enter ``` Gotchas: - 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 ```bash npm whoami npm view version ``` ## Cleanup ```bash 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 ` ` — 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` 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 ```bash git checkout main && git pull --rebase git status ``` 2) 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: ```bash echo test > /tmp/sparkle.txt sign_update -f "$SPARKLE_PRIVATE_KEY_FILE" /tmp/sparkle.txt --account "${SPARKLE_ACCOUNT:-default}" rm /tmp/sparkle.txt ``` 6) Clear stuck DMG volumes if needed: ```bash for v in /Volumes/*; do [[ $v == */* ]] && hdiutil detach "$v" -force; done ``` ## Build, Sign, Notarize - Prefer the repo’s scripted entry point. Common options: - `./scripts/release.sh stable|beta ` (handles build → notarize → appcast → release; supports `--resume`/`--status`) - `./Scripts/sign-and-notarize.sh` (SwiftPM apps; produces `-.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 && find .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 /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 `` blocks before publishing the appcast. 1) Generate signature for the shipping artifact (DMG or ZIP): ```bash sign_update -f "$SPARKLE_PRIVATE_KEY_FILE" path/to/-.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 generated 3) 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 ` output matches `sparkle:edSignature` in the appcast. - Double‑check you used the correct key account: `sign_update --account -p ` must match the appcast signature, and the app’s `SUPublicEDKey` must be the public key for that account. - `curl -I ""` returns 200. - `curl "" | 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` (or let the release script tag). 2) Create the GitHub release (pre-release for betas), title ` `, 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** ` ` — 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` (or `spctl --assess --type execute --verbose .app` on older macOS versions) - `codesign --verify --deep --strict --verbose .app` - `stapler validate .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 ` ` 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 ` `; 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 && sign_update --verify /tmp/update.zip -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.` if Sparkle cached a bad download). - [ ] Appcast shows the correct notes (single-version chunk), and artifact size looks sane. - [ ] GitHub release notes header is ` ` 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/`: ```bash echo "# /mycommand\n\nYour prompt instructions..." > ~/.codex/prompts/mycommand.md ``` 2. **Use the command** in any Codex/Claude Code session: ```text /mycommand ``` 3. **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/`: ```bash .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.md ``` **Available 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: ```bash 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 "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 ""`) 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/.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: `, 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` → ``. 2) **Collect commits since baseline** ```bash git log ..HEAD --oneline --reverse ``` Skim 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 ```markdown ## 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 in `bin/` directly. Using `bun bin/ ...` 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?”](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-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 in