# ilyasturki/dircmp architecture

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

- Interactive diagram: https://gitdiagram.com/ilyasturki/dircmp
- Repository: https://github.com/ilyasturki/dircmp

## Overview

dircmp is a terminal directory and file comparison tool with an interactive TUI plus scriptable `diff` and `check` commands. The main workflow resolves local or rclone-backed paths, scans both sides, compares entries, and presents a navigable side-by-side tree; users can open file diffs or resolve differences with copy, delete, and undo/redo actions. Additional branches cover ignore rules, preferences and keybindings, remote access, and CLI output. Relationships reflect the excerpts, SOURCE INDEX references, and README; unsampled implementations are represented only where documented.

Main entry points: [`src/main.tsx`](https://github.com/ilyasturki/dircmp/blob/main/src/main.tsx) (CLI dispatcher), [`src/app.tsx`](https://github.com/ilyasturki/dircmp/blob/main/src/app.tsx) (TUI application), [`src/utils/ignore.ts`](https://github.com/ilyasturki/dircmp/blob/main/src/utils/ignore.ts) (Ignore rules), [`src/hooks.ts`](https://github.com/ilyasturki/dircmp/blob/main/src/hooks.ts) (Directory scan hook)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["Entry points"]
  node_main["CLI dispatcher<br/>[main.tsx]"]
  node_app["TUI application<br/>[app.tsx]"]
end

subgraph group_compare["Scan and compare"]
  node_scan_hook["Directory scan hook<br/>[hooks.ts]"]
  node_scanner["Filesystem scanner<br/>[scanner.ts]"]
  node_remote["Remote mounts<br/>[rclone.ts]"]
  node_ignore["Ignore rules<br/>[ignore.ts]"]
  node_compare_engine["Entry comparison<br/>[compare.ts]"]
end

subgraph group_tui["Interactive TUI"]
  node_reducer["Application state<br/>[reducer.ts]"]
  node_panels["Directory panels"]
  node_entry_row["Entry rows<br/>[entry-row.tsx]"]
  node_directory_diff["Directory diff view<br/>[directory-diff.tsx]"]
  node_file_diff_view["File diff viewer<br/>[file-diff.tsx]"]
  node_diff_client["Diff worker client<br/>[diff-client.ts]"]
  node_diff_worker["Diff worker<br/>[diff-worker.ts]"]
  node_diff_compute["Diff computation<br/>[diff-compute.ts]"]
  node_keymap["Keymap<br/>[keymap.ts]"]
  node_hooks["Navigation hooks<br/>[hooks.ts]"]
  node_keyboard_hints["Keyboard hints<br/>[keyboard-hints.tsx]"]
  node_theme["Theme and ANSI<br/>[theme.ts]"]
end

subgraph group_actions["Resolution and settings"]
  node_execute["Action executor<br/>[execute-action.ts]"]
  node_undo["Undo history<br/>[undo.ts]"]
  node_config["Preferences<br/>[config.ts]"]
  node_keybindings["Keybinding settings<br/>[keybindings.ts]"]
  node_paths["Config paths<br/>[paths.ts]"]
  node_ignore_dialog["Ignore editor<br/>[ignore-dialog.tsx]"]
  node_preferences_dialog["Preferences editor"]
  node_dialog["Dialog primitives<br/>[dialog.tsx]"]
  node_input["Text input<br/>[text-input.tsx]"]
end

subgraph group_cli["Scriptable CLI"]
  node_cli_scan["CLI scan adapter<br/>[scan.ts]"]
  node_directory_diff_cli["Directory diff output<br/>[directory-diff.ts]"]
  node_directory_check["Directory check<br/>[directory-check.ts]"]
  node_file_diff_cli["File diff command<br/>[file-diff.ts]"]
  node_file_check["File check command<br/>[file-check.ts]"]
end

node_user(("User or script"))

node_user -->|"invokes"| node_main
node_main -->|"launches TUI"| node_app
node_main -->|"resolves remotes"| node_remote
node_main -->|"loads rules"| node_ignore
node_main -->|"routes diff"| node_directory_diff_cli
node_main -->|"routes check"| node_directory_check
node_main -->|"routes file diff"| node_file_diff_cli
node_main -->|"routes file check"| node_file_check
node_app -->|"requests scans"| node_scan_hook
node_app -->|"dispatches actions"| node_reducer
node_app -->|"runs actions"| node_execute
node_app -->|"renders view"| node_directory_diff
node_scan_hook -->|"scans directories"| node_scanner
node_scan_hook -->|"handles remotes"| node_remote
node_scan_hook -->|"filters scans"| node_ignore
node_scanner -.->|"reads filesystem"| node_user
node_reducer -->|"compares entries"| node_compare_engine
node_directory_diff -.->|"renders panels"| node_panels
node_panels -.->|"renders rows"| node_entry_row
node_directory_diff -->|"opens file diff"| node_file_diff_view
node_file_diff_view -.->|"requests diff"| node_diff_client
node_diff_client -->|"posts requests"| node_diff_worker
node_diff_worker -->|"computes rows"| node_diff_compute
node_app -->|"uses shortcuts"| node_keymap
node_app -->|"uses navigation"| node_hooks
node_keymap -->|"defines hints"| node_keyboard_hints
node_execute -.->|"records undo"| node_undo
node_execute -.->|"updates rules"| node_ignore
node_preferences_dialog -->|"saves preferences"| node_config
node_ignore_dialog -->|"edits patterns"| node_ignore
node_preferences_dialog -->|"uses dialog"| node_dialog
node_preferences_dialog -->|"uses inputs"| node_input
node_ignore_dialog -->|"uses dialog"| node_dialog
node_config -->|"gets config path"| node_paths
node_keybindings -->|"gets config path"| node_paths
node_directory_diff_cli -->|"scans inputs"| node_cli_scan
node_directory_diff_cli -->|"compares entries"| node_compare_engine
node_directory_check -->|"scans inputs"| node_cli_scan
node_directory_check -->|"compares entries"| node_compare_engine
node_cli_scan -->|"scans trees"| node_scanner
node_cli_scan -->|"applies rules"| node_ignore
node_file_diff_cli -.->|"prints diff"| node_user
node_file_check -.->|"returns status"| node_user

click node_main "https://github.com/ilyasturki/dircmp/blob/main/src/main.tsx"
click node_app "https://github.com/ilyasturki/dircmp/blob/main/src/app.tsx"
click node_scan_hook "https://github.com/ilyasturki/dircmp/blob/main/src/hooks.ts"
click node_scanner "https://github.com/ilyasturki/dircmp/blob/main/src/utils/scanner.ts"
click node_remote "https://github.com/ilyasturki/dircmp/blob/main/src/utils/rclone.ts"
click node_ignore "https://github.com/ilyasturki/dircmp/blob/main/src/utils/ignore.ts"
click node_compare_engine "https://github.com/ilyasturki/dircmp/blob/main/src/utils/compare.ts"
click node_reducer "https://github.com/ilyasturki/dircmp/blob/main/src/reducer.ts"
click node_panels "https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/directory-panel.tsx"
click node_entry_row "https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/entry-row.tsx"
click node_directory_diff "https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/directory-diff.tsx"
click node_file_diff_view "https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff.tsx"
click node_diff_client "https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-client.ts"
click node_diff_worker "https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-worker.ts"
click node_diff_compute "https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-compute.ts"
click node_keymap "https://github.com/ilyasturki/dircmp/blob/main/src/keymap.ts"
click node_hooks "https://github.com/ilyasturki/dircmp/blob/main/src/hooks.ts"
click node_execute "https://github.com/ilyasturki/dircmp/blob/main/src/execute-action.ts"
click node_undo "https://github.com/ilyasturki/dircmp/blob/main/src/utils/undo.ts"
click node_config "https://github.com/ilyasturki/dircmp/blob/main/src/utils/config.ts"
click node_keybindings "https://github.com/ilyasturki/dircmp/blob/main/src/utils/keybindings.ts"
click node_paths "https://github.com/ilyasturki/dircmp/blob/main/src/utils/paths.ts"
click node_ignore_dialog "https://github.com/ilyasturki/dircmp/blob/main/src/components/dialogs/ignore-dialog.tsx"
click node_preferences_dialog "https://github.com/ilyasturki/dircmp/blob/main/src/components/dialogs/preferences-dialog.tsx"
click node_dialog "https://github.com/ilyasturki/dircmp/blob/main/src/components/dialog.tsx"
click node_input "https://github.com/ilyasturki/dircmp/blob/main/src/components/text-input.tsx"
click node_keyboard_hints "https://github.com/ilyasturki/dircmp/blob/main/src/components/keyboard-hints.tsx"
click node_theme "https://github.com/ilyasturki/dircmp/blob/main/src/utils/theme.ts"
click node_cli_scan "https://github.com/ilyasturki/dircmp/blob/main/src/cli/scan.ts"
click node_directory_diff_cli "https://github.com/ilyasturki/dircmp/blob/main/src/cli/directory-diff.ts"
click node_directory_check "https://github.com/ilyasturki/dircmp/blob/main/src/cli/directory-check.ts"
click node_file_diff_cli "https://github.com/ilyasturki/dircmp/blob/main/src/cli/file-diff.ts"
click node_file_check "https://github.com/ilyasturki/dircmp/blob/main/src/cli/file-check.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_app,node_user toneBlue
class node_scan_hook,node_scanner,node_remote,node_ignore,node_compare_engine toneAmber
class node_reducer,node_panels,node_entry_row,node_directory_diff,node_file_diff_view,node_diff_client,node_diff_worker,node_diff_compute,node_keymap,node_hooks,node_keyboard_hints,node_theme toneMint
class node_execute,node_undo,node_config,node_keybindings,node_paths,node_ignore_dialog,node_preferences_dialog,node_dialog,node_input toneRose
class node_cli_scan,node_directory_diff_cli,node_directory_check,node_file_diff_cli,node_file_check toneIndigo
```

## Components

### Entry points

- [CLI dispatcher](https://github.com/ilyasturki/dircmp/blob/main/src/main.tsx): `src/main.tsx`
- [TUI application](https://github.com/ilyasturki/dircmp/blob/main/src/app.tsx): `src/app.tsx`

### Scan and compare

- [Directory scan hook](https://github.com/ilyasturki/dircmp/blob/main/src/hooks.ts): `src/hooks.ts`
- [Filesystem scanner](https://github.com/ilyasturki/dircmp/blob/main/src/utils/scanner.ts): `src/utils/scanner.ts`
- [Remote mounts](https://github.com/ilyasturki/dircmp/blob/main/src/utils/rclone.ts): `src/utils/rclone.ts`
- [Ignore rules](https://github.com/ilyasturki/dircmp/blob/main/src/utils/ignore.ts): `src/utils/ignore.ts`
- [Entry comparison](https://github.com/ilyasturki/dircmp/blob/main/src/utils/compare.ts): `src/utils/compare.ts`

### Interactive TUI

- [Application state](https://github.com/ilyasturki/dircmp/blob/main/src/reducer.ts): `src/reducer.ts`
- [Directory panels](https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/directory-panel.tsx): `src/components/panels/directory-panel.tsx`
- [Entry rows](https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/entry-row.tsx): `src/components/panels/entry-row.tsx`
- [Directory diff view](https://github.com/ilyasturki/dircmp/blob/main/src/components/panels/directory-diff.tsx): `src/components/panels/directory-diff.tsx`
- [File diff viewer](https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff.tsx): `src/components/file-diff.tsx`
- [Diff worker client](https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-client.ts): `src/components/file-diff/diff-client.ts`
- [Diff worker](https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-worker.ts): `src/components/file-diff/diff-worker.ts`
- [Diff computation](https://github.com/ilyasturki/dircmp/blob/main/src/components/file-diff/diff-compute.ts): `src/components/file-diff/diff-compute.ts`
- [Keymap](https://github.com/ilyasturki/dircmp/blob/main/src/keymap.ts): `src/keymap.ts`
- [Navigation hooks](https://github.com/ilyasturki/dircmp/blob/main/src/hooks.ts): `src/hooks.ts`
- [Keyboard hints](https://github.com/ilyasturki/dircmp/blob/main/src/components/keyboard-hints.tsx): `src/components/keyboard-hints.tsx`
- [Theme and ANSI](https://github.com/ilyasturki/dircmp/blob/main/src/utils/theme.ts): `src/utils/theme.ts`

### Resolution and settings

- [Action executor](https://github.com/ilyasturki/dircmp/blob/main/src/execute-action.ts): `src/execute-action.ts`
- [Undo history](https://github.com/ilyasturki/dircmp/blob/main/src/utils/undo.ts): `src/utils/undo.ts`
- [Preferences](https://github.com/ilyasturki/dircmp/blob/main/src/utils/config.ts): `src/utils/config.ts`
- [Keybinding settings](https://github.com/ilyasturki/dircmp/blob/main/src/utils/keybindings.ts): `src/utils/keybindings.ts`
- [Config paths](https://github.com/ilyasturki/dircmp/blob/main/src/utils/paths.ts): `src/utils/paths.ts`
- [Ignore editor](https://github.com/ilyasturki/dircmp/blob/main/src/components/dialogs/ignore-dialog.tsx): `src/components/dialogs/ignore-dialog.tsx`
- [Preferences editor](https://github.com/ilyasturki/dircmp/blob/main/src/components/dialogs/preferences-dialog.tsx): `src/components/dialogs/preferences-dialog.tsx`
- [Dialog primitives](https://github.com/ilyasturki/dircmp/blob/main/src/components/dialog.tsx): `src/components/dialog.tsx`
- [Text input](https://github.com/ilyasturki/dircmp/blob/main/src/components/text-input.tsx): `src/components/text-input.tsx`

### Scriptable CLI

- [CLI scan adapter](https://github.com/ilyasturki/dircmp/blob/main/src/cli/scan.ts): `src/cli/scan.ts`
- [Directory diff output](https://github.com/ilyasturki/dircmp/blob/main/src/cli/directory-diff.ts): `src/cli/directory-diff.ts`
- [Directory check](https://github.com/ilyasturki/dircmp/blob/main/src/cli/directory-check.ts): `src/cli/directory-check.ts`
- [File diff command](https://github.com/ilyasturki/dircmp/blob/main/src/cli/file-diff.ts): `src/cli/file-diff.ts`
- [File check command](https://github.com/ilyasturki/dircmp/blob/main/src/cli/file-check.ts): `src/cli/file-check.ts`

### Other components

- **User or script**

## Connections

- User or script → CLI dispatcher: invokes
- CLI dispatcher → TUI application: launches TUI (evidence: `src/main.tsx`)
- CLI dispatcher → Remote mounts: resolves remotes (evidence: `src/main.tsx`)
- CLI dispatcher → Ignore rules: loads rules (evidence: `src/main.tsx`)
- CLI dispatcher → Directory diff output: routes diff (evidence: `src/main.tsx`)
- CLI dispatcher → Directory check: routes check (evidence: `src/main.tsx`)
- CLI dispatcher → File diff command: routes file diff (evidence: `src/main.tsx`)
- CLI dispatcher → File check command: routes file check (evidence: `src/main.tsx`)
- TUI application → Directory scan hook: requests scans (evidence: `src/app.tsx`)
- TUI application → Application state: dispatches actions (evidence: `src/app.tsx`)
- TUI application → Action executor: runs actions (evidence: `src/app.tsx`)
- TUI application → Directory diff view: renders view (evidence: `src/app.tsx`)
- Directory scan hook → Filesystem scanner: scans directories (evidence: `src/hooks.ts`)
- Directory scan hook → Remote mounts: handles remotes (evidence: `src/hooks.ts`)
- Directory scan hook → Ignore rules: filters scans (evidence: `src/hooks.ts`)
- Filesystem scanner → User or script: reads filesystem
- Application state → Entry comparison: compares entries (evidence: `src/reducer.ts`)
- Directory diff view → Directory panels: renders panels
- Directory panels → Entry rows: renders rows
- Directory diff view → File diff viewer: opens file diff (evidence: `src/app.tsx`)
- File diff viewer → Diff worker client: requests diff
- Diff worker client → Diff worker: posts requests (evidence: `src/components/file-diff/diff-client.ts`)
- Diff worker → Diff computation: computes rows (evidence: `src/components/file-diff/diff-worker.ts`)
- TUI application → Keymap: uses shortcuts (evidence: `src/app.tsx`)
- TUI application → Navigation hooks: uses navigation (evidence: `src/app.tsx`)
- Keymap → Keyboard hints: defines hints (evidence: `src/keymap.ts`)
- Action executor → Undo history: records undo
- Action executor → Ignore rules: updates rules
- Preferences editor → Preferences: saves preferences (evidence: `src/components/dialogs/preferences-dialog.tsx`)
- Ignore editor → Ignore rules: edits patterns (evidence: `src/components/dialogs/ignore-dialog.tsx`)
- Preferences editor → Dialog primitives: uses dialog (evidence: `src/components/dialogs/preferences-dialog.tsx`)
- Preferences editor → Text input: uses inputs (evidence: `src/components/dialogs/preferences-dialog.tsx`)
- Ignore editor → Dialog primitives: uses dialog (evidence: `src/components/dialogs/ignore-dialog.tsx`)
- Preferences → Config paths: gets config path (evidence: `src/utils/config.ts`)
- Keybinding settings → Config paths: gets config path (evidence: `src/utils/keybindings.ts`)
- Directory diff output → CLI scan adapter: scans inputs (evidence: `src/cli/directory-diff.ts`)
- Directory diff output → Entry comparison: compares entries (evidence: `src/cli/directory-diff.ts`)
- Directory check → CLI scan adapter: scans inputs (evidence: `src/cli/directory-check.ts`)
- Directory check → Entry comparison: compares entries (evidence: `src/cli/directory-check.ts`)
- CLI scan adapter → Filesystem scanner: scans trees (evidence: `src/cli/scan.ts`)
- CLI scan adapter → Ignore rules: applies rules (evidence: `src/cli/scan.ts`)
- File diff command → User or script: prints diff
- File check command → User or script: returns status
