# BroV — guide for AI coding agents BroV is a personal, never-published fork of Coucou (github.com/Louis-CFM/coucou, MIT, imported at 83708fe). Native macOS app in `NotchBuddy/`: an animated character in the MacBook notch that shows Claude Code sessions, lets the user approve/answer from the notch, and chats — with the user's own `claude` CLI as its brain (no API key). ## Where things are - `NotchBuddy/Sources/App/` — Mac app code. `NotchBuddy/Sources/CoucouKit/` — shared models, the character engine (`BotEngine.swift`), pills (`PillCatalog.swift`). - `NotchBuddy/Sources/App/ClaudeCodeCLI.swift` — runs `claude -p … --output-format stream-json --resume ` for the chat. - `NotchBuddy/Resources/sounds/` — WAV sounds. - `NotchBuddy/project.yml` — XcodeGen project (never edit the `.xcodeproj` by hand; it is git-ignored and regenerated). ## Build ``` bash scripts/build.sh # xcodegen + xcodebuild, installs ~/Applications/BroV.app, relaunches bash scripts/render-brov.sh # character in every state → /tmp/brov-states.png ``` DerivedData must stay outside ~/Documents (iCloud adds Finder attributes and codesign fails). ``` ``` ## Rules - Personal use only: never publish to GitHub or any public place. The original Coucou name, Mochi character and icon are not used in BroV. - Swift 6, SwiftUI + AppKit. One dependency: SwiftTerm (term.macOS tabs). The character is 11 Memoji images (`Resources/memoji`) moved by `BotEngine` at 30 fps. - Secrets live in the Keychain or the root-only network core folder, never in git. - Never block Claude Code: if the app doesn't answer, the hook exits immediately. - Never overwrite `~/.claude/settings.json`: dated backup, merge, write only after the user confirms. - Never approve a Claude Code permission without an explicit click. - When spawning `claude`, strip `CLAUDECODE` from the environment and close stdin. - Pill IDs are stable contract values: never rename an existing pill ID. ## Network core (globe 🌐 in the header) - mihomo runs as root: LaunchDaemon `local.maksar.brov.netd`, binary + config + keys + API secret in `/Library/Application Support/BroV/` (root, 0700). Nothing user-writable is read by root. - BroV never sees the config or the API secret: it talks to the narrow root helper `scripts/netcore/netctl.py` (LaunchDaemon `local.maksar.brov.netctl`, socket `/var/run/brov-netctl.sock`, only the installing user) — commands: state, select, delay, tun, add_key, remove_key. - `scripts/netcore/gen.py` builds the config (Amnezia keys → provider `keys/amnezia.yaml`, WireGuard clients, VLESS subscription). Install/update: `sudo sh scripts/netcore/install.sh` (verifies the mihomo SHA256, migrates keys). Never commit keys, configs or the guide (`~/.brov-secrets`). - Reloading the whole core config drops every connection (including this chat); group switches and provider reloads don't.