Kakuの指定領域を過去の修正履歴や操作経路の違いから点検し、潜在的な不具合や使い勝手の落とし穴を探して、根拠と影響範囲を整理するスキル。
- 公開前にKakuの特定領域を点検したいとき
- 修正後に関連する操作経路も調べたいとき
- シェル初期設定をクリーンな環境で検証
KakuのmacOS版を公開するための事前確認からビルド、署名・公証、配布までを進め、安定版やNightlyの公開と失敗後の再開を支援します。
Run the Kaku macOS release flow end-to-end: preflight, build, notarize, tag, upload to GitHub Releases, dispatch the Homebrew tap, or publish the rolling Nightly preview package. Source of truth is scripts/release.sh and scripts/nightly.sh; this skill records release prerequisites and recovery hints without embedding private machine setup.
KakuのmacOS版を、事前確認からビルド、署名、Appleによる公証、タグ作成、GitHub Releasesへのアップロードまで進めます。安定版ではHomebrew tapの更新を扱い、Nightlyでは継続更新するプレビュー用DMGを公開します。scripts/release.shとscripts/nightly.shを基準に、失敗した段階からの再開方法も案内します。
Kakuの公開担当者が、バージョンやリリースノート、認証情報の準備を確認しながら配布を進めたいときに向いています。自動テストでは確認しにくいウィンドウ、タブ、シェル連携などの手動確認項目も整理されています。
macOSの署名証明書、GitHub認証、公証用のrcodesignまたはnotarytoolの認証情報が必要です。安定版は変更のないmainがorigin/mainと同期していることが条件です。事前確認だけではソース検査の完了を示しません。認証の復旧には非公開のローカル手順書を使い、再開には対応する成果物が必要です。
この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
scripts/release.sh is authoritative. This skill captures the release prerequisites and the order Tang and the agent rely on each release. Exact credential locations and one-time recovery commands live in the ignored .claude/release.local.md, never in this tracked file.
Before any stable or Nightly release, run the non-secret checks under Verify. The release dry-run is the authoritative credential gate: it accepts either the rcodesign path or the notarytool fallback, including environment overrides. If it passes, do not load machine-specific recovery context. If a signing identity or every notarization path is missing or stale, then check for and read .claude/release.local.md; on Tang's release machine it is the required recovery layer. If the local runbook is absent, stop and ask for it instead of guessing a path or replacing credentials.
./scripts/release.sh --dry-run # preflight only
KAKU_ASC_API_KEY_PATH=/dev/null ./scripts/release.sh # known rcodesign compatibility issue
./scripts/release.sh # full release
./scripts/nightly.sh # rolling Nightly DMG for fixes already on main
release.sh must run on main, with a clean tree, in sync with origin/main. nightly.sh has no branch or clean-tree gate; it only refuses to publish when HEAD is not yet on tw93/Kaku. Both auto-detect the signing identity and read notarization creds from the login keychain.
The KAKU_ASC_API_KEY_PATH=/dev/null prefix selects notarytool before submission for a known non-network compatibility issue. Do not switch backends or disable S3 acceleration to bypass a network failure. Submission and timestamp failures allow one retry on the same route; if it fails again, stop, diagnose read-only, and wait for the maintainer to resolve the network before resuming. A stored profile name does not prove that its notarytool login exists; verify the profile or use the API-key recovery below.
scripts/nightly.sh is authoritative for the rolling nightly GitHub prerelease. It builds a release-grade universal app, signs, notarizes, staples, copies dist/Kaku.dmg to dist/Kaku-nightly.dmg, and recreates the nightly release. It does not bump versions, create a V* tag, update Homebrew, or refresh any stable release surface.
Rules:
tw93/Kaku before deleting the old nightly release../scripts/nightly.sh has completed and gh release view nightly -R tw93/Kaku --json tagName,targetCommitish,publishedAt,assets,url points at the intended commit with Kaku-nightly.dmg.--upload-only unless the existing dist/Kaku.dmg is already known to be a signed, notarized, stapled build from the intended commit.The ignored .claude/release.local.md is the canonical map from Tang's local backup paths to these script inputs. The tracked contract is limited to what the scripts consume: either KAKU_ASC_API_KEY_PATH or the kaku-asc-api-key-path login-keychain item for rcodesign, and either KAKU_NOTARYTOOL_PROFILE or the kaku-notarytool-profile login-keychain item for the fallback. Do not delete or rewrite the local recovery map merely because its paths are machine-specific.
rcodesign is preferred on macOS 26+ because notarytool can SIGBUS. The scripts also accept the notarytool fallback when its prerequisites are available; use the release dry-run to check eligibility and the actual notarization result to verify success. It is not in homebrew core.
cargo install apple-codesign # binary: rcodesign, lands in ~/.cargo/bin
The private JSON supplied through the environment or keychain path must use rcodesign's native issuer_id, key_id, and private_key format. Do not record its location in tracked docs.
Create the notarytool profile with the maintainer's private Apple ID, team ID, and app-specific password outside the repository. Pass its profile name through KAKU_NOTARYTOOL_PROFILE or the expected login-keychain item; never paste the source values or the import command into a tracked runbook.
security find-identity -v -p codesigning | grep 'Developer ID Application'
gh auth status
./scripts/release.sh --dry-run
When the dry-run reports a notarization failure, use command -v rcodesign, security find-generic-password -s 'kaku-asc-api-key-path', and security find-generic-password -s 'kaku-notarytool-profile' as separate diagnostics. They are not an AND gate: one complete notarization backend is sufficient.
Before invoking release.sh, confirm in this order:
kaku/Cargo.toml and kaku-gui/Cargo.toml versions match (e.g. 0.10.0).assets/shell-integration/config_version.txt is the intended schema version, with highlight rows in the matching docs..github/RELEASE_NOTES.md first heading is # V<version> <suffix> (uppercase V, used as the GitHub Release title).Changelog and Chinese 更新日志 sections in RELEASE_NOTES.md cover the same items. Register: one full stop per item, declarative middle register, neither literary nor conversational; the item count follows the number of distinct user-visible outcomes (the previous release's count is history, not a quota), and length is measured against the previous release before publishing.origin/main.Use ./scripts/prep_release.sh <bump> to draft the version bump and notes when starting from an older tag. Run it with --no-edit --no-push: it commits with the checkout's local git identity, which can be the wrong account for the day, so fill in the notes and the config_update_highlights.tsv stub rows, then fold them into that unpushed commit with git -c user.name=… -c user.email=… commit --amend --reset-author before pushing (V0.25.0). Tang typically edits the resulting .github/RELEASE_NOTES.md by hand to apply the announcement-writing style (community first, 2 to 4 highlights, user-experience framing).
These are the areas that produce the most post-release bug reports and that CI cannot see (visual layout, native AppKit, shell-in-user-env).
Hand the maintainer a release-shaped build for this pass, not make app: that one is a debug build, and remote-terminal latency and scrolling feel nothing like the shipped app. PROFILE=release-opt BUILD_ARCH=native ./scripts/build.sh --app-only (about 20 minutes, signed with the local identity) differs from the release only in notarization and the second architecture; swapping it into /Applications and restarting lets the maintainer test in the Kaku they use every day. Run them by hand in the built dist/Kaku.app before tagging. Automated coverage already exists for the testable slices: tab width-budget + hover hit-testing have unit tests in kaku-gui/src/tabbar.rs, and local-outside-function / shell syntax is gated by shellcheck + the setup_zsh smoke. The list below is what still needs a human.
macOS window (#408, #414): on first launch, a single click on the title bar / top inset must not maximize the window; drag the window while it fills the desktop; flip system light/dark and confirm all windows refresh; enter and exit fullscreen cleanly.
Tab bar (#409, #435, #439, #443, #445, #447): check both tab_bar_at_bottom true/false; open enough tabs to overflow a narrow window and confirm titles truncate but every tab stays clickable; rename a tab, then click another to switch and confirm no position scramble; confirm a tmux/shell status prompt renders in the bar without clipping. Exercise the status dot through idle, running, pending or attention, and cleared states on active and inactive tabs, with the tab bar at both the top and bottom; idle must not leave a dot behind.
Shell setup (#420, #432, #441, #450): from a clean HOME, run kaku init and confirm z / syntax-highlight / autosuggestions are active in a fresh shell; run kaku init --update-only and confirm it exits clean; open a new shell and confirm ~/.config/kaku/zsh/kaku.zsh sources with no error.
AI chat (#418, #431): run kaku chat, quit, then run it again in the same window and confirm it reopens.
Render timing / stale drawable (#452, #458): on the bundled WebGpu backend, sleep the Mac then wake it and confirm the window repaints instead of freezing on the old frame while keystrokes still reach the shell; connect or disconnect an external display and confirm no frozen frame or geometry jump; open a new window straight into fullscreen and resize it, confirming it fills without a stale first frame.
Hyperlinks (#547): Cmd-hover a URL that the terminal soft-wraps and confirm both rows target the full URL. Then print a URL exactly as wide as the terminal, followed by \r\n and unindented unrelated text; the target must exclude that text. Terminal and surface tests cover the grouping; check the built app hover target too.
Mouse recovery (#551): in both zsh and fish, run printf '\033[?1003;1006h' and return to the prompt; moving the mouse must not insert escape sequences. Also keep a mouse-enabled TUI running and confirm mouse input still works until it exits.
Settings lifecycle and custom configs (#545): start the app with a minimal standalone --config-file, switch between Kaku Light and Kaku Dark, and confirm Settings edits that file and the main window follows. Save and exit Settings repeatedly; no destroyed-window repaint panic should appear.
Tab bar pointer paths (V0.22.0): with 2+ tabs and the bar at the bottom, tap just above a tab and confirm it switches; middle-click to paste on the last terminal row and confirm no tab closes; right-click an inactive tab, choose Close Tab several times and confirm the app stays up and closes that tab while you stay on yours.
Split panes with dimming (#562): set inactive_pane_hsb = { brightness = 0.7 }, split top|bottom with the tab bar at top and at bottom, focus each pane, and confirm the dimmed background stops exactly at the line with no undimmed strip on the right or bottom edge; split into three panes and confirm two dimmed neighbours still show a faint line; drag the line and confirm it does not jump a row on grab.
When a release fixes a bug outside this list, add the reproduction here so the next release re-checks it.
| Scope | Command |
|---|---|
| Format | make fmt-check |
| Compile | make check |
| Tests | make test |
| Release notes version match | ./scripts/check_release_notes.sh |
| Config schema versioning | ./scripts/check_release_config.sh |
| Config release readiness | ./scripts/check_config_release_readiness.sh |
| Full preflight | ./scripts/release.sh --dry-run |
release.sh --dry-run stops after preflight and does not run source checks. The normal release reuses successful CI Checks for the current HEAD; otherwise stage:checks runs the local checks below, as described in AGENTS.md. A passing dry-run alone is not source-check evidence.
./scripts/release.sh runs these stages in order. Each is timed and labeled [stage:<name>].
main in sync with origin/main, version consistency, gh auth, release notes, config, latest Build Validation workflow run on main green (an in-progress run only warns), profile, signing identity, notarization creds.make fmt-check && make check && make test locally. RUN_CLIPPY=1 adds local clippy in either case. SKIP_TESTS=1 skips local tests (avoid)../scripts/build.sh, PROFILE=release-opt, BUILD_ARCH=universal. Output: dist/Kaku.app, dist/Kaku.dmg, dist/kaku_for_update.zip, dist/kaku_for_update.zip.sha256../scripts/notarize.sh. Tries rcodesign first; falls back to notarytool only for a non-network rcodesign failure when a notarytool profile exists.git tag -a V<version> -m 'Release V<version>' then git push origin V<version>. Idempotent: reuses an existing tag at HEAD instead of dying.gh release create V<version> (or gh release edit if it already exists) with the dmg, zip, and sha256. Title is taken from the first # line of RELEASE_NOTES.md.repository_dispatch (kaku_release_published) to tw93/homebrew-tap triggering bump.yml. Polls Casks/kakuku.rb through the GitHub contents API for the new version (default 12 attempts, 15s apart). The official homebrew/cask token is kaku and is bumped by Homebrew livecheck from the GitHub release; this stage only updates the personal tap for existing tw93/tap/kakuku installs.release.sh accepts these flags to skip already-completed stages:
| Flag | Skips | Use when |
|---|---|---|
--notarize-only | build | Build succeeded; notarization failed or was interrupted. |
--upload-only | build, notarize | Notarized dist/Kaku.app and Kaku.dmg exist on disk; only need to tag + upload + tap. |
--tap-only | build, notarize, upload | GitHub release exists; only the Homebrew tap dispatch needs to rerun. |
Resume flags require the corresponding artifacts in dist/ to still be present.
Submission ID received and then fails: the submission was created but the DMG upload to Apple's S3 did not finish (there is no Successfully uploaded file line), so that submission stays In Progress forever and waiting on it is pointless. Once the network is back, resubmit the same artifacts with ./scripts/release.sh --notarize-only; a good submission came back Accepted in about four minutes (V0.25.0).HTTP 408: Upload body timed out or EOF: the proxy cut the long upload; gh release create then deletes the new release and keeps the tag. Rerun env -u HTTPS_PROXY -u HTTP_PROXY -u ALL_PROXY -u https_proxy -u http_proxy -u all_proxy ./scripts/release.sh --upload-only (gh reads only proxy variables, not the macOS system proxy). Upload failures may be retried up to five times, 30 seconds apart (maintainer 2026-10-20); V0.26.0 went through on the first direct retry even with the route on a TUN interface. Start a full release with the same env -u prefix.Local main is not synchronized with origin/main: push the pending commit. release.sh requires the tag to point at a commit that exists on origin.rcodesign not found: cargo install apple-codesign, then verify with which rcodesign. Do not try brew install rcodesign; it is not a core formula.No Developer ID Application certificate found: re-import the certificate from the maintainer-approved private backup through Keychain Access, using the password from the private runbook. Never add either location to this file.Notarization credentials not found: follow the ignored private setup runbook to provision one of the environment/keychain inputs described under Credential prerequisites, then rerun ./scripts/release.sh --dry-run. The script otherwise prompts interactively, which fails in non-interactive shells.s3 upload error: HTTP connect timeout occurred after 3.1s identifies the failed upload connection, not a credential fault. notarize.sh retries once on rcodesign and stops if the network failure persists. Preserve the signed artifact, report the blocked submission, and resume only after the maintainer resolves the network; do not switch to notarytool to retry the same failure.No Keychain password item found for profile: a profile-name entry alone does not establish a working login. An installed Apple notarytool can reuse the existing ASC .p8 key with --key, --key-id, and --issuer, without creating a Keychain login. Resolve the inputs from the private runbook and keep their values out of displayed commands and logs. For S3 upload failures, apply the same one-retry network budget above and keep the signed artifact fixed. After Accepted, retrieve the submission log and verify its SHA-256 against the submitted DMG, then run ./scripts/notarize.sh --staple-only and ./scripts/nightly.sh --upload-only from the same source commit. See Apple's notarization API workflow.kakuku <version> to tw93/homebrew-tap main on success; verify with gh api repos/tw93/homebrew-tap/commits/main --jq .commit.message. The verifier reads the cask through the GitHub contents API (Accept: application/vnd.github.raw), not the Fastly-cached download_url. Network errors retry once and stop, and other API errors stop immediately; the 12-poll budget only waits for a version change. A version-poll timeout means the expected version was not observed: open the run URL the script printed. If the tap commit is present the release is complete. Widen the window with HOMEBREW_TAP_VERIFY_ATTEMPTS / HOMEBREW_TAP_VERIFY_SLEEP_SECONDS, or rerun ./scripts/release.sh --tap-only; REQUIRE_HOMEBREW_TAP_UPDATE=0 only downgrades the failure to a warning.rcodesign notarization failed right after the log shows "status": "Accepted": Apple accepted; the step died stapling. rcodesign cannot staple an unsigned DMG, which is what build.sh produces, and the script used to pass --staple (removed 2026-09-10). Do not touch credentials. Recover with ./scripts/notarize.sh --staple-only then ./scripts/nightly.sh --upload-only.codesign: A timestamp was expected but was not found (or timestamp service is not available): the timestamp request failed during signing; this message alone does not establish a certificate fault or identify the network cause. build.sh retries timestamp failures once before aborting. If that retry fails, stop the release, perform read-only network diagnosis, and report the blocked signing step. Resume only after the maintainer resolves the network problem; do not rerun the build or change proxy settings to retry the same failure.codesign: code object is not signed at all, In subcomponent: .../MacOS/k while signing kaku-gui: kaku-gui is the bundle's main executable and codesign validates its siblings as nested code, so every other executable in Contents/MacOS must already be signed. build.sh signs kaku and k before kaku-gui since 2026-09-10; if a new helper binary is added to the bundle, add it to that loop before kaku-gui.stapler fails with CloudKit timeout, exit code 68: the log reads The staple and validate action failed! Error 68 right after Notarization accepted. Notarization already succeeded; only ticket retrieval from api.apple-cloudkit.com timed out. Do not re-notarize. One ./scripts/notarize.sh --staple-only retry is allowed; if the network failure repeats, stop for read-only diagnosis and wait for the maintainer to resolve it. Only after stapling succeeds, resume with ./scripts/release.sh --upload-only. The staple-only path regenerates kaku_for_update.zip and its sha256 on purpose: attaching the ticket changes the app, so the in-app update archive must be rebuilt after stapling, never before.| Variable | Default | Purpose |
|---|---|---|
KAKU_SIGNING_IDENTITY | auto-detect | Override the Developer ID Application identity. |
KAKU_ASC_API_KEY_PATH | keychain item kaku-asc-api-key-path | Path to rcodesign ASC API key JSON. |
KAKU_NOTARYTOOL_PROFILE | keychain item kaku-notarytool-profile | notarytool keychain profile name. |
HOMEBREW_TAP_TOKEN | gh auth token | GitHub token for tap dispatch. |
REQUIRE_HOMEBREW_TAP_UPDATE | 1 | Set to 0 to allow release to succeed when tap dispatch fails. |
HOMEBREW_TAP_VERIFY_ATTEMPTS | 12 | Polls of the tap cask before the verifier gives up. |
HOMEBREW_TAP_VERIFY_SLEEP_SECONDS | 15 | Seconds between tap cask polls. |
RUN_CLIPPY | 0 | Set to 1 to run cargo clippy during stage:checks. |
SKIP_TESTS | 0 | Set to 1 to skip make test during stage:checks. |
OUT_DIR | <repo>/dist | Override artifact output directory. |
PROFILE | release-opt | Cargo profile. Only release and release-opt are accepted. |
BUILD_ARCH | universal | Passed through to build.sh. |
GitHub Release URL: https://github.com/tw93/Kaku/releases/tag/V<version>.
Official Homebrew cask users get the new version after Homebrew livecheck/bump; verify with brew update && brew info --cask kaku. Personal-tap users get it once the tap workflow finishes; verify with brew info --cask tw93/tap/kakuku.
In-app updates (kaku-gui/src/update.rs, Kaku's own updater, not Sparkle) download kaku_for_update.zip and its .sha256 from the latest GitHub Release.
Add the six positive reactions to the new release; this is part of shipping. Skip -1 and confused.
id=$(gh api repos/tw93/Kaku/releases/tags/V<version> --jq .id)
for c in +1 laugh heart hooray rocket eyes; do
gh api -X POST "repos/tw93/Kaku/releases/$id/reactions" -f content="$c"
done
For the announcement post (X / WeChat): community first, 2-4 highlights, user-experience framing, one opinionated sentence. The release notes file is a different artifact; do not paste it as the announcement.
まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
Kakuの指定領域を過去の修正履歴や操作経路の違いから点検し、潜在的な不具合や使い勝手の落とし穴を探して、根拠と影響範囲を整理するスキル。