# tschnorpfeil/nodch architecture

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

- Interactive diagram: https://gitdiagram.com/tschnorpfeil/nodch
- Repository: https://github.com/tschnorpfeil/nodch
- Video tour (about a minute): https://gitdiagram.com/tschnorpfeil/nodch/video

## Overview

nodch is a macOS notch interface for a running Nod server, not a separate chat client. The workflow is: invoke the prompt, compose by typing or dictation and attach files, send to Nod, display progress and answers, then respond to questions or explicitly approve/decline actions. Settings configure the server and credentials. The graph includes the client/state and presentation layers; relationships not demonstrated by the excerpts or README are omitted or marked unverified.

Main entry points: [`app/Sources/Nodch/Island/IslandController.swift`](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandController.swift) (Island controller), [`app/Sources/NodchCore/Client/NodClient.swift`](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodClient.swift) (Nod API client), [`app/Sources/Nodch/Island/IslandModel.swift`](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandModel.swift) (Island model), [`app/Sources/Nodch/Settings/SettingsModel.swift`](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/SettingsModel.swift) (Settings model)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["Mac App"]
  node_app_entry["App startup<br/>[main.swift]"]
  node_app_delegate["App lifecycle<br/>[AppDelegate.swift]"]
  node_commands["App commands<br/>[AppCommands.swift]"]
end

subgraph group_island["Island Experience"]
  node_controller["Island controller"]
  node_presenter["Island presenter"]
  node_views["Island views"]
  node_compact_view["Compact view"]
  node_island_model["Island model<br/>[IslandModel.swift]"]
  node_drop_reader["Drop reader<br/>[DropReader.swift]"]
  node_voice["Dictation capture"]
  node_transcription["Speech transcription"]
  node_markdown["Markdown rendering"]
end

subgraph group_core["Nod Integration"]
  node_geometry["Island geometry"]
  node_presentation["Island presentation"]
  node_prompt_draft["Prompt draft<br/>[PromptDraft.swift]"]
  node_session["Nod session<br/>[NodSession.swift]"]
  node_client["Nod API client<br/>[NodClient.swift]"]
  node_state["State mapping<br/>[NodState.swift]"]
  node_configuration["API configuration"]
end

subgraph group_settings["Connection Settings"]
  node_settings_model["Settings model"]
  node_settings_view["Settings window<br/>[SettingsView.swift]"]
  node_connection_settings["Saved connection"]
  node_connection_check["Connection test"]
  node_token_store[("Keychain tokens")]
end

node_person(("Mac user"))
node_nod_server["Running Nod"]

node_person -->|"invokes shortcut"| node_commands
node_person -->|"drops files"| node_controller
node_app_entry -->|"starts app"| node_app_delegate
node_app_delegate -->|"creates"| node_controller
node_controller -->|"drives"| node_island_model
node_controller -->|"updates"| node_presenter
node_controller -->|"reads drops"| node_drop_reader
node_controller -->|"controls mic"| node_voice
node_presenter -->|"presents"| node_views
node_presenter -->|"presents"| node_compact_view
node_views -->|"reads state"| node_island_model
node_views -->|"renders text"| node_markdown
node_island_model -->|"applies prompt effects"| node_prompt_draft
node_voice -->|"transcribes speech"| node_transcription
node_controller -->|"uses layout"| node_geometry
node_controller -->|"derives reactions"| node_presentation
node_app_delegate -->|"creates"| node_settings_model
node_settings_view -->|"drives settings"| node_settings_model
node_settings_model -->|"resolves connection"| node_connection_settings
node_settings_model -->|"tests connection"| node_connection_check
node_connection_settings -->|"builds config"| node_configuration
node_connection_settings -.->|"stores token"| node_token_store
node_connection_check -->|"checks API"| node_client
node_session -->|"fetches and mutates"| node_client
node_client -->|"builds requests"| node_configuration
node_client -->|"calls HTTP API"| node_nod_server
node_client -->|"decodes state"| node_state
node_session -->|"maps updates"| node_state
node_island_model -.->|"submits actions"| node_session

click node_app_entry "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/main.swift"
click node_app_delegate "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/AppDelegate.swift"
click node_commands "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/AppCommands.swift"
click node_controller "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandController.swift"
click node_presenter "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandPresenter.swift"
click node_views "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandPanelView.swift"
click node_compact_view "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandCompactView.swift"
click node_island_model "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandModel.swift"
click node_drop_reader "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/DropReader.swift"
click node_voice "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Voice/MicrophoneVoice.swift"
click node_transcription "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Voice/Transcription.swift"
click node_markdown "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandMarkdown.swift"
click node_geometry "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/IslandGeometry.swift"
click node_presentation "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/IslandPresentation.swift"
click node_prompt_draft "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/PromptDraft.swift"
click node_session "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodSession.swift"
click node_client "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodClient.swift"
click node_state "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodState.swift"
click node_configuration "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodConfiguration.swift"
click node_settings_model "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/SettingsModel.swift"
click node_settings_view "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/SettingsView.swift"
click node_connection_settings "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Settings/ConnectionSettings.swift"
click node_connection_check "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Settings/ConnectionCheck.swift"
click node_token_store "https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/KeychainTokenStore.swift"

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_app_entry,node_app_delegate,node_commands,node_person toneBlue
class node_controller,node_presenter,node_views,node_compact_view,node_island_model,node_drop_reader,node_voice,node_transcription,node_markdown toneAmber
class node_geometry,node_presentation,node_prompt_draft,node_session,node_client,node_state,node_configuration toneMint
class node_settings_model,node_settings_view,node_connection_settings,node_connection_check,node_token_store toneRose
class node_nod_server toneIndigo
```

## Components

### Mac App

- [App startup](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/main.swift): `app/Sources/Nodch/main.swift`
- [App lifecycle](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/AppDelegate.swift): `app/Sources/Nodch/AppDelegate.swift`
- [App commands](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/AppCommands.swift): `app/Sources/Nodch/Settings/AppCommands.swift`

### Island Experience

- [Island controller](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandController.swift): `app/Sources/Nodch/Island/IslandController.swift`
- [Island presenter](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandPresenter.swift): `app/Sources/Nodch/Island/IslandPresenter.swift`
- [Island views](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandPanelView.swift): `app/Sources/Nodch/Island/IslandPanelView.swift`
- [Compact view](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandCompactView.swift): `app/Sources/Nodch/Island/IslandCompactView.swift`
- [Island model](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandModel.swift): `app/Sources/Nodch/Island/IslandModel.swift`
- [Drop reader](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/DropReader.swift): `app/Sources/Nodch/Island/DropReader.swift`
- [Dictation capture](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Voice/MicrophoneVoice.swift): `app/Sources/Nodch/Voice/MicrophoneVoice.swift`
- [Speech transcription](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Voice/Transcription.swift): `app/Sources/Nodch/Voice/Transcription.swift`
- [Markdown rendering](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Island/IslandMarkdown.swift): `app/Sources/Nodch/Island/IslandMarkdown.swift`

### Nod Integration

- [Island geometry](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/IslandGeometry.swift): `app/Sources/NodchCore/Island/IslandGeometry.swift`
- [Island presentation](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/IslandPresentation.swift): `app/Sources/NodchCore/Island/IslandPresentation.swift`
- [Prompt draft](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Island/PromptDraft.swift): `app/Sources/NodchCore/Island/PromptDraft.swift`
- [Nod session](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodSession.swift): `app/Sources/NodchCore/Client/NodSession.swift`
- [Nod API client](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodClient.swift): `app/Sources/NodchCore/Client/NodClient.swift`
- [State mapping](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodState.swift): `app/Sources/NodchCore/Client/NodState.swift`
- [API configuration](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Client/NodConfiguration.swift): `app/Sources/NodchCore/Client/NodConfiguration.swift`

### Connection Settings

- [Settings model](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/SettingsModel.swift): `app/Sources/Nodch/Settings/SettingsModel.swift`
- [Settings window](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/SettingsView.swift): `app/Sources/Nodch/Settings/SettingsView.swift`
- [Saved connection](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Settings/ConnectionSettings.swift): `app/Sources/NodchCore/Settings/ConnectionSettings.swift`
- [Connection test](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/NodchCore/Settings/ConnectionCheck.swift): `app/Sources/NodchCore/Settings/ConnectionCheck.swift`
- [Keychain tokens](https://github.com/tschnorpfeil/nodch/blob/main/app/Sources/Nodch/Settings/KeychainTokenStore.swift): `app/Sources/Nodch/Settings/KeychainTokenStore.swift`

### Other components

- **Mac user**
- **Running Nod**

## Connections

- Mac user → App commands: invokes shortcut
- Mac user → Island controller: drops files
- App startup → App lifecycle: starts app (evidence: `app/Sources/Nodch/main.swift`)
- App lifecycle → Island controller: creates (evidence: `app/Sources/Nodch/AppDelegate.swift`)
- Island controller → Island model: drives (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- Island controller → Island presenter: updates (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- Island controller → Drop reader: reads drops (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- Island controller → Dictation capture: controls mic (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- Island presenter → Island views: presents (evidence: `app/Sources/Nodch/Island/IslandPresenter.swift`)
- Island presenter → Compact view: presents (evidence: `app/Sources/Nodch/Island/IslandPresenter.swift`)
- Island views → Island model: reads state (evidence: `app/Sources/Nodch/Island/IslandPanelView.swift`)
- Island views → Markdown rendering: renders text (evidence: `app/Sources/Nodch/Island/IslandPanelView.swift`)
- Island model → Prompt draft: applies prompt effects (evidence: `app/Sources/Nodch/Island/IslandModel.swift`)
- Dictation capture → Speech transcription: transcribes speech (evidence: `app/Sources/Nodch/Voice/MicrophoneVoice.swift`)
- Island controller → Island geometry: uses layout (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- Island controller → Island presentation: derives reactions (evidence: `app/Sources/Nodch/Island/IslandController.swift`)
- App lifecycle → Settings model: creates (evidence: `app/Sources/Nodch/AppDelegate.swift`)
- Settings window → Settings model: drives settings (evidence: `app/Sources/Nodch/Settings/SettingsView.swift`)
- Settings model → Saved connection: resolves connection (evidence: `app/Sources/Nodch/Settings/SettingsModel.swift`)
- Settings model → Connection test: tests connection (evidence: `app/Sources/Nodch/Settings/SettingsModel.swift`)
- Saved connection → API configuration: builds config (evidence: `app/Sources/NodchCore/Settings/ConnectionSettings.swift`)
- Saved connection → Keychain tokens: stores token
- Connection test → Nod API client: checks API (evidence: `app/Sources/NodchCore/Settings/ConnectionCheck.swift`)
- Nod session → Nod API client: fetches and mutates (evidence: `app/Sources/NodchCore/Client/NodSession.swift`)
- Nod API client → API configuration: builds requests (evidence: `app/Sources/NodchCore/Client/NodClient.swift`)
- Nod API client → Running Nod: calls HTTP API
- Nod API client → State mapping: decodes state (evidence: `app/Sources/NodchCore/Client/NodClient.swift`)
- Nod session → State mapping: maps updates (evidence: `app/Sources/NodchCore/Client/NodSession.swift`)
- Island model → Nod session: submits actions
