fda-read — macOS Full Disk Access proxy
SkillFiles & storageUse macOS Terminal.app Full Disk Access as a proxy to copy TCC-protected files such as Messages/chat.db or AddressBook into a readable location for agent workflows.
Use fda-read — macOS Full Disk Access proxy in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add fda-read — macOS Full Disk Access proxy and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the fda-read skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by lev-os/agents in skills/fda-read/SKILL.md and read by Ahel’s review.
Read macOS TCC-protected files (Messages/chat.db, AddressBook, etc.) from a shell that does NOT have Full Disk Access, by delegating through Terminal.app which does.
Usage
# Copy a protected file to a readable location
fda-read <source_path> [<dest_dir>]
# Examples
fda-read ~/Library/Messages/chat.db # → /tmp/fda-read-chat.db (+ WAL + SHM)
fda-read ~/Library/Messages/chat.db /tmp/live # → /tmp/live/chat.db (+ WAL + SHM)
CRITICAL: SQLite WAL mode
macOS Messages.app uses SQLite WAL (Write-Ahead Log) mode. Recent messages live in chat.db-wal, NOT in chat.db. Copying only chat.db gives stale data. You MUST copy all 3 files:
chat.db— main databasechat.db-wal— write-ahead log (WHERE RECENT MESSAGES ARE)chat.db-shm— shared memory index
SQLite automatically reads the WAL when all 3 files are co-located. If you only copy chat.db, you'll miss messages that Messages.app shows but haven't been checkpointed to the main db yet.
This was discovered the hard way: session 2026-04-16, user could see Josh's 6:30pm messages in Messages.app GUI but our queries returned nothing until we copied WAL+SHM alongside chat.db.
How it works
Terminal.app was granted Full Disk Access in System Settings (macOS pop-up accepted by user). Any process Terminal.app spawns inherits that FDA grant. Claude Code's shell does NOT have FDA directly.
The skill invokes:
osascript -e "tell application \"Terminal\" to do script \"cp '$SRC' '$DEST' && echo DONE > '$DEST.done'\""
Then waits for $DEST.done to appear (max 10s), confirming the copy completed.
When to use
- Before querying live iMessage data (
~/Library/Messages/chat.db) - Before reading AddressBook (
~/Library/Application Support/AddressBook/) - Before any macOS TCC-protected file access from agent context
- When
sqlite3 ~/Library/Messages/chat.dbreturns "unable to open database file"
When NOT to use
- If your shell already has FDA (test:
sqlite3 ~/Library/Messages/chat.db "SELECT 1;") - For files that aren't TCC-protected (regular project files, /tmp, etc.)
- In CI/CD or headless environments (Terminal.app requires a display)
Canonical pattern
This is the official Leviathan pattern for protected macOS resource access:
- FDA-granted GUI app (Terminal.app) acts as proxy
- Shell requests copy via osascript
- Copy lands in /tmp (unrestricted)
- All downstream tools read from /tmp
Documented at: .lev/pm/captures/20260415-fda-canonical-path.yaml
Implementation
For agents: execute this sequence in Bash:
SRC="$1"
DEST_DIR="${2:-/tmp/fda-read-$(basename "$SRC" .db)}"
DONE_MARKER="${DEST_DIR}.done"
rm -f "$DONE_MARKER"
# Copy main db + WAL + SHM (all 3 required for fresh SQLite reads)
osascript -e "tell application \"Terminal\" to do script \"mkdir -p '$DEST_DIR' && cp '$SRC' '${SRC}-wal' '${SRC}-shm' '$DEST_DIR/' 2>/dev/null && chmod 644 '$DEST_DIR/'* && echo DONE > '$DONE_MARKER'\""
for i in $(seq 1 20); do [ -f "$DONE_MARKER" ] && break; sleep 0.5; done
if [ -f "$DONE_MARKER" ]; then
DB_FILE="$DEST_DIR/$(basename "$SRC")"
echo "fda-read: copied $SRC + WAL + SHM → $DEST_DIR/ ($(stat -f%z "$DB_FILE") bytes)"
rm -f "$DONE_MARKER"
# Verify WAL was included
if [ -f "$DEST_DIR/$(basename "$SRC")-wal" ]; then
echo "fda-read: WAL included ($(stat -f%z "$DEST_DIR/$(basename "$SRC")-wal") bytes)"
else
echo "fda-read: WARNING — WAL not found, recent data may be missing"
fi
else
echo "fda-read: TIMEOUT — Terminal.app may not have FDA or file doesn't exist" >&2
exit 1
fi
# Usage: query the copied db (WAL auto-read when co-located)
# sqlite3 "$DEST_DIR/$(basename "$SRC")" "SELECT ..."
Supersedes
~/digital/cyber/josh-imessage/dist/imessage_loader(PyInstaller binary with FDA) — still works but this is simpler~/digital/cyber/josh-imessage/manage_scheduler.sh— daemon scheduler can delegate to this pattern instead
Prerequisites
- Terminal.app listed in System Settings → Privacy & Security → Full Disk Access
- Terminal.app must be installed (ships with macOS)
- A display session (not headless/SSH)
Signals
- GitHub stars
- 23
- Forks
- 2
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
fda-read- Source
- github.com/lev-os/agents