add microphone capture and stable code signing for TCC persistence
Adds --capture-mic/--mic-output for a second, independently-captured audio track (mic vs system, written to separate outputs to avoid interleaving corruption). Embeds Info.plist at link time so the binary carries a stable CFBundleIdentifier and the usage-description keys TCC requires, and adds scripts/build-signed.sh + scripts/create-signing-identity.sh so a rebuilt binary keeps the same signing identity instead of losing granted permissions on every rebuild. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# Builds audiotee, signs it with a stable identity, and installs it to a
|
||||
# fixed path. Both steps matter for Core Audio process tap / microphone TCC
|
||||
# permissions to survive across rebuilds — see CONTEXT.md §6.2 and §8:
|
||||
#
|
||||
# - SwiftPM ad-hoc-signs debug/release builds by default. Ad-hoc signatures
|
||||
# are keyed off the binary's own hash, so every rebuild looks like a new
|
||||
# app to TCC and permission has to be re-granted.
|
||||
# - TCC has also been observed keying on binary path, so builds are installed
|
||||
# to a fixed location outside .build/.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/build-signed.sh # build, sign, install to ~/bin
|
||||
# scripts/build-signed.sh --reset-tcc # also reset TCC state for this
|
||||
# # binary, useful after changing
|
||||
# # Info.plist or the signing identity
|
||||
#
|
||||
# Requires a self-signed code-signing certificate in your keychain. If you
|
||||
# don't have one yet:
|
||||
# 1. Open Keychain Access
|
||||
# 2. Keychain Access menu > Certificate Assistant > Create a Certificate...
|
||||
# 3. Name it (e.g. "audiotee-dev"), Identity Type: Self Signed Root,
|
||||
# Certificate Type: Code Signing
|
||||
# 4. Create it, then in Keychain Access double-click it, expand "Trust",
|
||||
# and set "Code Signing" to "Always Trust"
|
||||
# Override auto-detection with: AUDIOTEE_SIGNING_IDENTITY="Your Cert Name"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
BUNDLE_ID="com.stephanetailland.audiotee"
|
||||
INSTALL_DIR="${AUDIOTEE_INSTALL_DIR:-$HOME/bin}"
|
||||
INSTALL_PATH="$INSTALL_DIR/audiotee"
|
||||
RESET_TCC=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--reset-tcc) RESET_TCC=true ;;
|
||||
*)
|
||||
echo "Unknown argument: $arg" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -n "${AUDIOTEE_SIGNING_IDENTITY:-}" ]]; then
|
||||
IDENTITY="$AUDIOTEE_SIGNING_IDENTITY"
|
||||
else
|
||||
# Real identity lines look like ` 1) <hash> "Name"`; the "N valid
|
||||
# identities found" summary line has no ")" and must not be counted.
|
||||
IDENTITY_LINES="$(security find-identity -v -p codesigning | grep '^ *[0-9]*)' || true)"
|
||||
IDENTITY_COUNT="$(printf '%s\n' "$IDENTITY_LINES" | grep -c . || true)"
|
||||
if [[ "$IDENTITY_COUNT" -eq 0 ]]; then
|
||||
echo "Error: no code-signing identity found in your keychain." >&2
|
||||
echo "See the comment at the top of this script for how to create one." >&2
|
||||
exit 1
|
||||
elif [[ "$IDENTITY_COUNT" -gt 1 ]]; then
|
||||
echo "Error: multiple code-signing identities found. Set AUDIOTEE_SIGNING_IDENTITY" >&2
|
||||
echo "to the one to use:" >&2
|
||||
echo "$IDENTITY_LINES" >&2
|
||||
exit 1
|
||||
fi
|
||||
IDENTITY="$(printf '%s\n' "$IDENTITY_LINES" | sed -n 's/.*"\(.*\)"/\1/p')"
|
||||
fi
|
||||
|
||||
echo "Building (release)..."
|
||||
swift build -c release
|
||||
|
||||
BUILT_BINARY="$REPO_ROOT/.build/release/audiotee"
|
||||
|
||||
echo "Signing with identity: $IDENTITY"
|
||||
codesign --force --sign "$IDENTITY" --identifier "$BUNDLE_ID" "$BUILT_BINARY"
|
||||
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
cp "$BUILT_BINARY" "$INSTALL_PATH"
|
||||
|
||||
echo "Installed to $INSTALL_PATH"
|
||||
codesign -dvvv "$INSTALL_PATH"
|
||||
|
||||
if [[ "$RESET_TCC" == true ]]; then
|
||||
echo "Resetting TCC state for $BUNDLE_ID..."
|
||||
tccutil reset SystemAudioCaptureRequests "$BUNDLE_ID" || true
|
||||
tccutil reset Microphone "$BUNDLE_ID" || true
|
||||
fi
|
||||
Reference in New Issue
Block a user