# felipap/nudge architecture

> Architecture diagram of the GitHub repository felipap/nudge, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/felipap/nudge
- Repository: https://github.com/felipap/nudge

## Overview

Nudge is a macOS focus-session app: users configure screen access and an AI backend, set an activity and duration, then the app periodically captures the screen, assesses whether it matches the goal, and nudges when it does not. The graph separates desktop orchestration, user-facing windows, capture/session processing, AI assessment, and persisted state. Several subsystem links are supported only by README or SOURCE INDEX references; unsampled implementation details are not inferred.

Main entry points: [`src/lib/capture-service.ts`](https://github.com/felipap/nudge/blob/main/src/lib/capture-service.ts) (Capture scheduler), [`windows/shared/ipc.ts`](https://github.com/felipap/nudge/blob/main/windows/shared/ipc.ts) (Renderer IPC API), [`src/ipc.ts`](https://github.com/felipap/nudge/blob/main/src/ipc.ts) (Main IPC handlers), [`src/main.ts`](https://github.com/felipap/nudge/blob/main/src/main.ts) (App lifecycle)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_desktop["Desktop runtime"]
  node_main["App lifecycle<br/>[main.ts]"]
  node_windowmgr["Window manager<br/>[windows.ts]"]
  node_tray["Tray controls<br/>[tray.ts]"]
  node_ipc["Main IPC handlers<br/>[ipc.ts]"]
end

subgraph group_windows["User windows"]
  node_preloadipc["Renderer IPC API<br/>[ipc.ts]"]
  node_onboard["Onboarding flow<br/>[index.tsx]"]
  node_modelsetup["Model selection<br/>[index.tsx]"]
  node_settings["Settings screens<br/>[index.tsx]"]
  node_input["Goal input<br/>[index.tsx]"]
  node_activeui["Active session UI<br/>[index.tsx]"]
end

subgraph group_session["Session processing"]
  node_capture["Capture scheduler<br/>[capture-service.ts]"]
  node_screenshot["Screen capture<br/>[screenshot.ts]"]
end

subgraph group_ai["AI assessment"]
  node_ai_dispatch["AI assessment API<br/>[index.ts]"]
  node_openai_assess["OpenAI assessment<br/>[index.ts]"]
  node_gemini_assess["Gemini assessment<br/>[index.ts]"]
  node_cloud_assess["Cloud proxy assessment<br/>[assess-capture.ts]"]
  node_goal_feedback["Goal feedback<br/>[goal-feedback.ts]"]
end

subgraph group_state["State and services"]
  node_store[("Persisted app state<br/>[index.ts]")]
  node_store_backend["File persistence<br/>[backend.ts]"]
  node_state_types["Session and capture types<br/>[types.ts]"]
  node_telemetry["Telemetry<br/>[telemetry.ts]"]
  node_logger["Logging and errors<br/>[logger.ts]"]
end

node_user(("User"))
node_ai_service["AI service"]
node_notification["macOS notifications"]

node_user -->|"configures"| node_onboard
node_user -->|"sets activity"| node_input
node_main -->|"registers"| node_ipc
node_main -->|"creates windows"| node_windowmgr
node_main -->|"starts"| node_capture
node_main -->|"creates"| node_tray
node_onboard -->|"uses"| node_preloadipc
node_modelsetup -->|"updates settings"| node_preloadipc
node_settings -->|"checks permissions"| node_preloadipc
node_input -->|"requests backend"| node_preloadipc
node_activeui -->|"controls session"| node_preloadipc
node_preloadipc -->|"invokes handlers"| node_ipc
node_ipc -->|"reads and updates"| node_store
node_ipc -->|"requests feedback"| node_goal_feedback
node_ipc -->|"registers onboarding"| node_telemetry
node_capture -->|"captures screen"| node_screenshot
node_capture -->|"assesses screenshot"| node_ai_dispatch
node_capture -->|"reads and updates"| node_store
node_capture -->|"sends nudge"| node_notification
node_ai_dispatch -.->|"dispatches"| node_openai_assess
node_ai_dispatch -.->|"dispatches"| node_gemini_assess
node_ai_dispatch -.->|"dispatches"| node_cloud_assess
node_openai_assess -->|"sends image"| node_ai_service
node_cloud_assess -->|"proxies requests"| node_ai_service
node_goal_feedback -.->|"requests feedback"| node_ai_service
node_store -->|"persists through"| node_store_backend
node_store -->|"uses state types"| node_state_types
node_capture -->|"logs events"| node_logger

click node_main "https://github.com/felipap/nudge/blob/main/src/main.ts"
click node_windowmgr "https://github.com/felipap/nudge/blob/main/src/windows.ts"
click node_tray "https://github.com/felipap/nudge/blob/main/src/tray.ts"
click node_ipc "https://github.com/felipap/nudge/blob/main/src/ipc.ts"
click node_preloadipc "https://github.com/felipap/nudge/blob/main/windows/shared/ipc.ts"
click node_onboard "https://github.com/felipap/nudge/blob/main/windows/onboard/App/index.tsx"
click node_modelsetup "https://github.com/felipap/nudge/blob/main/windows/onboard/App/step4-model/index.tsx"
click node_settings "https://github.com/felipap/nudge/blob/main/windows/settings/App/screen/index.tsx"
click node_input "https://github.com/felipap/nudge/blob/main/windows/main/App/InputScreen/index.tsx"
click node_activeui "https://github.com/felipap/nudge/blob/main/windows/main/App/ActiveSessionScreen/index.tsx"
click node_capture "https://github.com/felipap/nudge/blob/main/src/lib/capture-service.ts"
click node_screenshot "https://github.com/felipap/nudge/blob/main/src/lib/screenshot.ts"
click node_ai_dispatch "https://github.com/felipap/nudge/blob/main/src/ai/index.ts"
click node_openai_assess "https://github.com/felipap/nudge/blob/main/src/ai/openai/assess-capture/index.ts"
click node_gemini_assess "https://github.com/felipap/nudge/blob/main/src/ai/gemini/assess-capture/index.ts"
click node_cloud_assess "https://github.com/felipap/nudge/blob/main/src/ai/cloud/assess-capture.ts"
click node_goal_feedback "https://github.com/felipap/nudge/blob/main/src/ai/goal-feedback.ts"
click node_store "https://github.com/felipap/nudge/blob/main/src/store/index.ts"
click node_store_backend "https://github.com/felipap/nudge/blob/main/src/store/backend.ts"
click node_state_types "https://github.com/felipap/nudge/blob/main/src/store/types.ts"
click node_telemetry "https://github.com/felipap/nudge/blob/main/src/lib/telemetry.ts"
click node_logger "https://github.com/felipap/nudge/blob/main/src/lib/logger.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_windowmgr,node_tray,node_ipc,node_user toneBlue
class node_preloadipc,node_onboard,node_modelsetup,node_settings,node_input,node_activeui toneAmber
class node_capture,node_screenshot toneMint
class node_ai_dispatch,node_openai_assess,node_gemini_assess,node_cloud_assess,node_goal_feedback toneRose
class node_store,node_store_backend,node_state_types,node_telemetry,node_logger,node_ai_service,node_notification toneIndigo
```

## Components

### Desktop runtime

- [App lifecycle](https://github.com/felipap/nudge/blob/main/src/main.ts): `src/main.ts`
- [Window manager](https://github.com/felipap/nudge/blob/main/src/windows.ts): `src/windows.ts`
- [Tray controls](https://github.com/felipap/nudge/blob/main/src/tray.ts): `src/tray.ts`
- [Main IPC handlers](https://github.com/felipap/nudge/blob/main/src/ipc.ts): `src/ipc.ts`

### User windows

- [Renderer IPC API](https://github.com/felipap/nudge/blob/main/windows/shared/ipc.ts): `windows/shared/ipc.ts`
- [Onboarding flow](https://github.com/felipap/nudge/blob/main/windows/onboard/App/index.tsx): `windows/onboard/App/index.tsx`
- [Model selection](https://github.com/felipap/nudge/blob/main/windows/onboard/App/step4-model/index.tsx): `windows/onboard/App/step4-model/index.tsx`
- [Settings screens](https://github.com/felipap/nudge/blob/main/windows/settings/App/screen/index.tsx): `windows/settings/App/screen/index.tsx`
- [Goal input](https://github.com/felipap/nudge/blob/main/windows/main/App/InputScreen/index.tsx): `windows/main/App/InputScreen/index.tsx`
- [Active session UI](https://github.com/felipap/nudge/blob/main/windows/main/App/ActiveSessionScreen/index.tsx): `windows/main/App/ActiveSessionScreen/index.tsx`

### Session processing

- [Capture scheduler](https://github.com/felipap/nudge/blob/main/src/lib/capture-service.ts): `src/lib/capture-service.ts`
- [Screen capture](https://github.com/felipap/nudge/blob/main/src/lib/screenshot.ts): `src/lib/screenshot.ts`

### AI assessment

- [AI assessment API](https://github.com/felipap/nudge/blob/main/src/ai/index.ts): `src/ai/index.ts`
- [OpenAI assessment](https://github.com/felipap/nudge/blob/main/src/ai/openai/assess-capture/index.ts): `src/ai/openai/assess-capture/index.ts`
- [Gemini assessment](https://github.com/felipap/nudge/blob/main/src/ai/gemini/assess-capture/index.ts): `src/ai/gemini/assess-capture/index.ts`
- [Cloud proxy assessment](https://github.com/felipap/nudge/blob/main/src/ai/cloud/assess-capture.ts): `src/ai/cloud/assess-capture.ts`
- [Goal feedback](https://github.com/felipap/nudge/blob/main/src/ai/goal-feedback.ts): `src/ai/goal-feedback.ts`

### State and services

- [Persisted app state](https://github.com/felipap/nudge/blob/main/src/store/index.ts): `src/store/index.ts`
- [File persistence](https://github.com/felipap/nudge/blob/main/src/store/backend.ts): `src/store/backend.ts`
- [Session and capture types](https://github.com/felipap/nudge/blob/main/src/store/types.ts): `src/store/types.ts`
- [Telemetry](https://github.com/felipap/nudge/blob/main/src/lib/telemetry.ts): `src/lib/telemetry.ts`
- [Logging and errors](https://github.com/felipap/nudge/blob/main/src/lib/logger.ts): `src/lib/logger.ts`

### Other components

- **User**
- **AI service**
- **macOS notifications**

## Connections

- User → Onboarding flow: configures (evidence: `README.md`)
- User → Goal input: sets activity (evidence: `README.md`)
- App lifecycle → Main IPC handlers: registers (evidence: `src/main.ts`)
- App lifecycle → Window manager: creates windows (evidence: `src/main.ts`)
- App lifecycle → Capture scheduler: starts (evidence: `src/main.ts`)
- App lifecycle → Tray controls: creates (evidence: `src/main.ts`)
- Onboarding flow → Renderer IPC API: uses (evidence: `windows/onboard/App/index.tsx`)
- Model selection → Renderer IPC API: updates settings (evidence: `windows/onboard/App/step4-model/index.tsx`)
- Settings screens → Renderer IPC API: checks permissions (evidence: `windows/settings/App/screen/index.tsx`)
- Goal input → Renderer IPC API: requests backend (evidence: `windows/main/App/InputScreen/useEvolvingFeedback.ts`)
- Active session UI → Renderer IPC API: controls session
- Renderer IPC API → Main IPC handlers: invokes handlers (evidence: `windows/shared/ipc.ts`)
- Main IPC handlers → Persisted app state: reads and updates (evidence: `src/ipc.ts`)
- Main IPC handlers → Goal feedback: requests feedback (evidence: `src/ipc.ts`)
- Main IPC handlers → Telemetry: registers onboarding (evidence: `src/ipc.ts`)
- Capture scheduler → Screen capture: captures screen (evidence: `src/lib/capture-service.ts`)
- Capture scheduler → AI assessment API: assesses screenshot (evidence: `src/lib/capture-service.ts`)
- Capture scheduler → Persisted app state: reads and updates (evidence: `src/lib/capture-service.ts`)
- Capture scheduler → macOS notifications: sends nudge (evidence: `README.md`)
- AI assessment API → OpenAI assessment: dispatches
- AI assessment API → Gemini assessment: dispatches
- AI assessment API → Cloud proxy assessment: dispatches
- OpenAI assessment → AI service: sends image (evidence: `README.md`)
- Cloud proxy assessment → AI service: proxies requests (evidence: `README.md`)
- Goal feedback → AI service: requests feedback
- Persisted app state → File persistence: persists through (evidence: `src/store/index.ts`)
- Persisted app state → Session and capture types: uses state types (evidence: `src/store/index.ts`)
- Capture scheduler → Logging and errors: logs events (evidence: `src/lib/capture-service.ts`)
