Personal preferences and instructions for all projects.
Headless-first: This is a headless indie dev shop. Adrien works from an iPad via Telegram — assume he is never on a laptop or on the device running Claude Code. A Mac Mini runs all automation. Every solution must be scriptable, CLI-driven, and zero-GUI. Manual dashboard steps are a failure mode. If a one-time manual setup enables future automation, do it eagerly. Try things first — if a CLI tool exists, install it and run it. If there are multiple valid approaches, pick the best one and go. The only time to stop and ask is when you hit an actual wall requiring Adrien's physical presence, and even then minimize it to one action.
Never delegate back what you can do now: If a task is within your capabilities — running a command, making a config change, cleaning up after yourself — just do it. Saying "you can delete X" or "you should run Y" when you have the tools is a failure mode.
When running via Telegram (indicated by --append-system-prompt mentioning Telegram), these tools are unavailable and must NEVER be used:
- AskUserQuestion - Requires interactive terminal UI; ask questions as plain text instead
- EnterPlanMode / ExitPlanMode - Requires interactive approval; just proceed with implementation
These are also enforced via
--disallowed-toolsin the bridge, but this note ensures the constraint survives context compaction.
Inclusive Language Standards:
- Use "allowlist" and "denylist" instead of "whitelist" and "blacklist"
- Use "main" or "primary" instead of "master" for branch names (unless repo convention differs)
- Use "leader/follower" or "primary/replica" instead of "master/slave" for technical systems
- Use person-first language when referring to disabilities
- Use gender-neutral terms: "they/them", "developer" not "guys", "humanity" not "mankind"
- Avoid unnecessarily gendered terms: "staffing" not "manning", "synthetic" not "man-made"
NEVER include time estimates of any scale (hours, days, weeks) in project planning, task breakdowns, or documentation. Focus on task clarity, deliverables, and acceptance criteria without duration estimates.
Detailed workflows are available as skills. Use these when working in specific domains:
- python-dev - Modern uv-based Python workflow, testing patterns, virtual environment management
- git-workflow - Branch strategies, protected branch workflow, post-merge cleanup
- self-healing-errors - Error handling patterns for LLM-maintained automation
- apple-platform-dev - Swift architecture, Metal, Core Data, iOS/macOS development
- swift-quality - SwiftUI code quality rules, refactoring strategies, linting, compiler warnings, tooling
- whisper-tool (
~/Developer/whisper-tool/) — Local audio transcription using faster-whisper.cd ~/Developer/whisper-tool && uv run transcribe /path/to/audio.m4a # plain text cd ~/Developer/whisper-tool && uv run transcribe /path/to/audio.m4a --json # JSON with timestamps cd ~/Developer/whisper-tool && uv run transcribe /path/to/audio.m4a --words # word-level timestamps cd ~/Developer/whisper-tool && uv run transcribe *.m4a --output-dir ./out/ # batch # Models: tiny, base (default), small, medium, large-v3
File move/delete safety enforced by pre-bash hook — warns on rm/mv without preceding verification (cp/ls/test).
All beads live in repo-local databases (.beads/ in each repo). There is no global/cross-project beads database. Every bead belongs to a specific repo.
If a repo doesn't have beads initialized yet, initialize it before creating issues:
- Use the
beads-initskill if available, or run manually:bd init,echo "y" | bd doctor --fix, addsync-branch: "beads-sync"to.beads/config.yaml, commit.beads/and.gitattributes - This applies to any git repo where you're creating task/feature/bug beads
Cross-project items that don't belong to a specific repo should be tracked in Ernest's memory — not as beads.
Bead creation: In repos with scripts/bd-create.py, always use the validated wrapper (python3 scripts/bd-create.py) instead of raw bd create — it enforces required fields and proper scoring for Forge dispatch.
Use ~/Developer/worktrees/ for git worktree development sessions.
Feature branches use bead-based naming when work is tracked by a bead:
beads-abc123/fix-login-bug— bead ID + slug from titlebeads-def456/add-dark-mode
For non-bead work (exploration, quick fixes), any descriptive branch name is fine. The only hard rule: never commit directly to protected branches (develop, main, master, production, release). This is enforced by pre-tool-use hooks.
Legacy claude/* branches still exist in some repos and are valid — they just aren't the convention anymore.
CLAUDE.md files document current state - how things are configured and work. They should NOT track task completion or recent changes. Historical context is acceptable when it explains why something is configured a certain way, but frame it as background rather than "recently completed work."
Always update CLAUDE.md proactively. When your changes affect conventions, architecture, tool usage, workflows, or configuration documented in any CLAUDE.md, update it immediately as part of the same task. Never ask permission — just do it. Treat CLAUDE.md like code: if you change the behavior, change the docs.
Secrets stored in pass (password-store) — GPG-encrypted flat files in ~/.password-store/.
Retrieve in Python: from passstore import get_secret; token = get_secret("service-name")
Retrieve via CLI: pass show <secret-name>
Canonical registry: ~/Developer/Fanta/scripts/passstore.py → SERVICES dict has all secret names and descriptions.
Recovery secrets (GPG key, SSH keys) live in Proton Pass — manual access only.
- Org:
synodic-studioongithub.com. Auth viaghCLI. - No CI on VCS — quality gates are local pre-push hooks.
- No PRs/reviews — all repos use direct commit to
develop. Force-push blocked on default branches.
- Instance:
https://db.synodic.coon Vultr VPS (173.199.90.59/ Tailscale100.72.154.94) - Admin:
admin@synodic.co, password inpass show pocketbase-admin-password - Data dir on Vultr:
/opt/pocketbase/ - Projects: podcast-pusher (
pp_*collections), SoMuchCoffee (roaster, shop, shop_group)
- Account ID:
8d8cc2d3d5644764958ee0331e3c0092 - DNS API Token:
pass show cloudflare-dns-api-token - Wrangler CLI (
wrangler): Use API tokens from keychain viaCLOUDFLARE_API_TOKENenv var. Never usewrangler login— the API tokens are headless, no browser OAuth needed. - Deploy pattern — Pages projects:
CLOUDFLARE_API_TOKEN=$(pass show cloudflare-pages-api-token) \ CLOUDFLARE_ACCOUNT_ID=8d8cc2d3d5644764958ee0331e3c0092 \ npx wrangler pages deploy <output-dir> --project-name <name> --branch main
- Deploy pattern — Workers:
cd <worker-dir> && \ CLOUDFLARE_API_TOKEN=$(pass show cloudflare-workers-api-token) \ npx wrangler deploy
- Custom domains: Add via API (
POST /pages/projects/<name>/domains), then CNAME DNS record pointing to<name>.pages.dev - synodic.co zone ID:
b2a93f571cd21f76232dc3d606c1b042 - kj6.dev zone ID:
b79a7c5565a7e290f850b1b91019790c
iOS test build distribution at preview.kj6.dev via Cloudflare Pages. Script: ~/Developer/scripts/deploy-preview.sh — the apple-release skill has the full workflow in its ota-preview.md reference.
Always override baseURL for preview deploys — Hugo bakes it into all links. Details in the develop-preview skill.
Rules (always apply to Swift/Apple projects):
- All new Swift projects use Tuist (
tuist init), not Xcode GUI project creation - All Apple apps must separate Debug/Release builds (
.debugbundle ID suffix, debug icon overlay — NOT display name). Use thedebug-buildsskill for full conventions. - Set
ITSAppUsesNonExemptEncryption = NOin Info.plist for standard-encryption apps - Run swift quality commands before returning control after Swift changes
- Never open or launch Xcode — it consumes resources and blocks the user's machine. All builds/tests go through
tuistCLI commands exclusively (tuist build,tuist test,tuist generate --no-open). ALWAYS pass--no-opentotuist generate— it opens Xcode by default. Do not usexcodebuilddirectly — Tuist wraps it. Theswift-lspplugin is disabled. - All apps must display version and build number in their UI — settings screen if one exists, otherwise best judgment (about page, footer, etc.). Use
CFBundleShortVersionStringandCFBundleVersion. - Devices: iPhone 15 Pro (
Enterprise15P), Apple Watch (Belluno)
Full reference (Tuist commands, ASC API, TestFlight, screenshots, Xcode MCP, Debug/Release details, swift quality commands): The apple-platform-dev skill has the full config in its apple-config.md reference.
CRITICAL: Never expose Adrien's real email addresses in any external context. Real addresses are strictly for internal/private use (git config, local tools).
For anything submitted externally (App Store, TestFlight, forms, accounts, services):
- Use SimpleLogin aliases at
synodic.coonly - Generate aliases as
studio.<context>-<random>@synodic.co - Example:
studio.deskdays-7k3@synodic.co,studio.testflight-p2@synodic.co - SimpleLogin regex:
studio\..+-.+(enforces context + random suffix) - When in doubt, ask Adrien before submitting any email anywhere