Project-specific settings that override/extend the global ~/CLAUDE.md
| Path | Description |
|---|---|
| This project | ~/SaneApps/apps/SaneBar/ |
| Save outputs | ~/SaneApps/apps/SaneBar/outputs/ |
| Screenshots | ~/Desktop/Screenshots/ (label with project prefix) |
| Shared UI | ~/SaneApps/infra/SaneUI/ |
| Hooks/tooling | ~/SaneApps/infra/SaneProcess/ |
Sister apps: SaneClip, SaneVideo, SaneSync, SaneHosts, SaneAI, SaneClick, SaneSales, Sane Mac Utilities Bundle
| Document | When to Use |
|---|---|
| GitHub Issues | Bug reports and tracking |
| DEVELOPMENT.md | Full SOP, 12 rules, compliance |
| .claude/rules/ | Code style rules by file type |
| docs/DEBUGGING_MENU_BAR_INTERACTIONS.md | Positioning bugs, coordinate system |
┌─────────────────────────────────────────────────────┐
│ BEFORE YOU SHIP, ASK: │
│ │
│ 1. Does this REDUCE fear or create it? │
│ 2. Power: Does user have control? │
│ 3. Love: Does this help people? │
│ 4. Sound Mind: Is this clear and calm? │
│ │
│ Grandma test: Would her life be better? │
│ │
│ "Not fear, but power, love, sound mind" │
│ — 2 Timothy 1:7 │
└─────────────────────────────────────────────────────┘
→ Full philosophy: ~/SaneApps/meta/Brand/NORTH_STAR.md
When hooks fire: READ THE MESSAGE FIRST. The answer is in the prompt/hook/memory/SOP. Stop guessing. Start reading.
| Path | Purpose |
|---|---|
scripts/SaneMaster.rb |
Build tool - use instead of raw xcodebuild |
Core/ |
Foundation types, Managers, Services |
Core/Services/ |
Accessibility API wrappers, permission handling |
Core/Models/ |
Data models (StatusItemModel, etc.) |
UI/ |
SwiftUI views |
UI/Onboarding/ |
Permission request flow |
Tests/ |
Unit tests (regression tests go here) |
project.yml |
XcodeGen configuration |
SaneBar has local build issues on the MacBook Air. Prefer the Mac Mini build server when reachable.
# Check if mini is reachable (home network only — won't work from coffee shops)
ssh -o ConnectTimeout=3 mini 'echo ok' 2>/dev/null && echo "MINI AVAILABLE" || echo "MINI OFFLINE — use local"- Mini reachable → use
mini-build.shfor builds,mini-test-install.shfor DMG verification - Mini offline → fall back to local
SaneMaster.rbcommands below
# Build & Test (local fallback)
./scripts/SaneMaster.rb verify # Build + unit tests
./scripts/SaneMaster.rb test_mode # Kill -> Build -> Launch -> Logs
./scripts/SaneMaster.rb logs --follow # Stream live logs
./scripts/SaneMaster.rb verify_api X # Check if API exists in SDK
# Release & App Store
./scripts/SaneMaster.rb release_preflight # 9 pre-release safety checks
./scripts/SaneMaster.rb appstore_preflight # App Store submission compliance
# CI/CD Helpers
./scripts/SaneMaster.rb enable_ci_tests # Enable test targets for CI
./scripts/SaneMaster.rb restore_ci_tests # Restore project.yml from CI backup
./scripts/SaneMaster.rb fix_mocks # Add @testable import to mocks
./scripts/SaneMaster.rb monitor_tests # Run tests with timeout + progress
./scripts/SaneMaster.rb image_info <path> # Extract image info and base64
# Memory Health (MCP Knowledge Graph)
./scripts/SaneMaster.rb mh # Check entity/token counts
./scripts/SaneMaster.rb mcompact # Compact verbose entities
./scripts/SaneMaster.rb mcleanup # Generate MCP cleanup commands
# Circuit Breaker (Failure Tracking)
./scripts/SaneMaster.rb breaker_status # Check if breaker is OPEN/CLOSED
./scripts/SaneMaster.rb breaker_errors # Show failure messages
./scripts/SaneMaster.rb reset_breaker # Reset after investigation
# Session Management
./scripts/SaneMaster.rb session_end # End session + memory prompt
./scripts/SaneMaster.rb compliance # Show session compliance reportSaneBar uses position pre-seeding for NSStatusItem ordering, but that is only the first layer.
→ Start with docs/MENU_BAR_RUNTIME_PLAYBOOK.md
→ Lower-level positioning notes: docs/DEBUGGING_MENU_BAR_INTERACTIONS.md
// 1. SEED ordinal positions in UserDefaults BEFORE creating items
private static func seedPositionsIfNeeded() {
let defaults = UserDefaults.standard
if defaults.object(forKey: "NSStatusItem Preferred Position \(mainAutosaveName)") == nil {
defaults.set(0, forKey: "NSStatusItem Preferred Position \(mainAutosaveName)") // 0 = rightmost
}
if defaults.object(forKey: "NSStatusItem Preferred Position \(separatorAutosaveName)") == nil {
defaults.set(1, forKey: "NSStatusItem Preferred Position \(separatorAutosaveName)") // 1 = second
}
}
// 2. CREATE items AFTER seeding, assign autosaveName
init() {
Self.seedPositionsIfNeeded()
self.mainItem = NSStatusBar.system.statusItem(withLength: variableLength)
self.mainItem.autosaveName = Self.mainAutosaveName
// ...
}| Rule | Why |
|---|---|
| Seed BEFORE create | macOS reads position on item creation |
| Use ordinal (0,1,2) for first seed | Pixel-like values show up later as runtime/restored positions, not initial hints |
Treat autosaveName as identity only |
Apple documents save/restore identity, not pixel semantics or corruption recovery |
| Do not stop at pre-seeding | Current SaneBar also relies on display-width backups, geometry reliability checks, and startup recovery |
- See
docs/DEBUGGING_MENU_BAR_INTERACTIONS.mdfor full details
- Accessibility API: All menu bar scanning uses
AXUIElementAPIs - Verify APIs: Always run
verify_apibefore using Apple Accessibility APIs - Permission Flow:
UI/Onboarding/WelcomeView.swifthandles AX permission - Mini runtime proof: use
docs/MENU_BAR_RUNTIME_PLAYBOOK.mdfirst, including the Mini repro pack and system-TCC Accessibility checks - Services: Located in
Core/Services/(AccessibilityService, DiagnosticsService, etc.) - State:
@Observableclasses for UI state, actors for concurrent services
# Always verify these exist before coding:
./scripts/SaneMaster.rb verify_api AXUIElementCreateSystemWide Accessibility
./scripts/SaneMaster.rb verify_api kAXExtrasMenuBarAttribute Accessibility
./scripts/SaneMaster.rb verify_api AXUIElementCopyAttributeValue Accessibility
./scripts/SaneMaster.rb verify_api SMAppService ServiceManagementSaneBar has automated SOP enforcement via hooks:
Circuit Breaker (.claude/circuit_breaker.json):
- Trips at: 3x same error OR 5 total failures
- When tripped: Edit/Bash tools blocked until reset
- Reset:
./scripts/SaneMaster.rb reset_breaker
Memory Thresholds (auto-checked at session start/end):
- Entities: 60 (warn), 80 (critical)
- Tokens: 8,000 (warn), 12,000 (critical)
- Archive: Old entities moved to
.claude/memory_archive.jsonl
Hooks Active (via SaneProcess in .claude/settings.json):
session_start.rb- Project context, memory health, MCP verificationsaneprompt.rb- Prompt intelligence, staging detectionsanetools.rb- Pre-tool checks: MCP verification, circuit breaker, edit validationsanetrack.rb- Post-tool: failure tracking, feature reminders, tautology detectionsanestop.rb- Session summary, SOP score, weak spot tracking
Use Serena for project-specific knowledge:
read_memory # Check past learnings
write_memory # Save important findings
For cross-project knowledge graph, use official Memory MCP tools.
compact: trueworks onlist_technologies,get_sample_code,wwdc(NOT onsearch_apple_docs)analyze_api analysis="all"for comprehensive API analysisapple_docsas universal entry point (auto-routes queries)
resolve-library-idFIRST, thenquery-docs- SwiftUI ID:
/websites/developer_apple_swiftui(13,515 snippets!)
get_scripting_tips search_term: "keyword"to find scriptsget_scripting_tips list_categories: trueto browse- 13 categories including
13_developer(92 Xcode/dev scripts)
search_codeto find patterns in public repossearch_repositoriesto find reference implementations
| Command | When to Use | Shortcut |
|---|---|---|
/rewind |
Rollback code AND conversation after errors | Esc+Esc |
/context |
Visualize context window token usage | - |
/compact [instructions] |
Optimize memory with focus | - |
/stats |
See usage patterns (press r for date range) |
- |
| Shortcut | Action |
|---|---|
Esc+Esc |
Rewind to checkpoint |
Shift+Tab |
Cycle permission modes (Normal → Auto-Accept → Plan) |
Option+T |
Toggle extended thinking |
Ctrl+O |
Toggle verbose mode |
Ctrl+B |
Background running task |
Don't just run /compact - give it focus instructions:
/compact keep SaneBar accessibility patterns and bug fixes, archive general Swift tips
Skills in .claude/skills/ activate automatically based on context:
| Skill | Triggers When |
|---|---|
session-context-manager |
Checking memory health, session state |
memory-compactor |
Memory full, tokens high, need to archive |
codebase-explorer |
Searching code, finding implementations |
feature-reminders |
Claude checks itself for feature suggestions |
For large codebase searches, delegate to Explore subagent (Haiku-powered, saves context):
Task tool with subagent_type: Explore
Hooks will remind about features at appropriate times:
/rewindsuggested after errors/contextsuggested every 5 edits- Explore subagent suggested for complex searches
- Cannot sandbox: Accessibility API requires unsandboxed app
- Notarization: Use hardened runtime + Developer ID signing
- Entitlements: No sandbox, but hardened runtime required