# mahm0udnasr/sadd architecture

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

- Interactive diagram: https://gitdiagram.com/mahm0udnasr/sadd
- Repository: https://github.com/mahm0udnasr/sadd

## Overview

sadd is a Linux website blocker whose source of truth is a managed section of `/etc/hosts`. Users block or unblock normalized domains through CLI commands or the interactive TUI; timed blocks are removed by `expire`, while checks ask the system resolver whether blocking works. The graph preserves the documented group, blocklist, backup/restore, and read-only TUI capabilities. Some internal wiring is unsampled, so uncertain links are omitted rather than inferred.

Main entry points: [`internal/hosts/hosts.go`](https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/hosts.go) (Hosts file state), [`cmd/tui.go`](https://github.com/mahm0udnasr/sadd/blob/main/cmd/tui.go) (TUI launcher), [`internal/tui/tui.go`](https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/tui.go) (Interactive app), [`cmd/block.go`](https://github.com/mahm0udnasr/sadd/blob/main/cmd/block.go) (Block sites)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["Entry points"]
  node_binary["sadd binary<br/>[main.go]"]
  node_root["Command router<br/>[root.go]"]
end

subgraph group_blocking["Blocking features"]
  node_block["Block sites<br/>[block.go]"]
  node_unblock["Unblock sites<br/>[unblock.go]"]
  node_listing["List blocks<br/>[list.go]"]
  node_groups["Built-in groups<br/>[groups.go]"]
  node_groupcmd["Groups command<br/>[groups.go]"]
  node_blocklistcmd["Blocklist controls<br/>[blocklist.go]"]
  node_blocklist["List download and parsing<br/>[blocklist.go]"]
  node_check["Blocking check<br/>[check.go]"]
end

subgraph group_state["Hosts state"]
  node_hosts[("Hosts file state<br/>[hosts.go]")]
  node_hostswrite["Safe file writes<br/>[write.go]"]
  node_atomic["Atomic replacement<br/>[atomic.go]"]
  node_restore["Restore backup<br/>[restore.go]"]
end

subgraph group_services["System services"]
  node_expiry["Expire timed blocks<br/>[expire.go]"]
  node_timer["Systemd timers<br/>[timer.go]"]
  node_dns["System DNS lookup<br/>[dns.go]"]
end

subgraph group_interface["Interactive interface"]
  node_tui_cmd["TUI launcher<br/>[tui.go]"]
  node_tui["Interactive app<br/>[tui.go]"]
  node_forms["Action forms<br/>[forms.go]"]
  node_views["Screens and views<br/>[view.go]"]
end

node_user(("User"))
node_systemd(("systemd"))
node_resolver(("System resolver"))

node_user -->|"runs"| node_binary
node_binary -->|"executes"| node_root
node_root -->|"opens by default"| node_tui_cmd
node_root -->|"routes commands"| node_block
node_block -->|"updates"| node_hosts
node_block -->|"schedules expiry"| node_timer
node_unblock -->|"removes entries"| node_hosts
node_listing -->|"reads entries"| node_hosts
node_groupcmd -->|"lists groups"| node_groups
node_blocklistcmd -->|"downloads lists"| node_blocklist
node_blocklistcmd -->|"reads and updates"| node_hosts
node_check -->|"reads blocked domains"| node_hosts
node_check -->|"checks resolution"| node_dns
node_hostswrite -.->|"replaces safely"| node_atomic
node_restore -->|"restores backup"| node_hosts
node_expiry -->|"expires entries"| node_hosts
node_expiry -->|"reschedules"| node_timer
node_systemd -->|"runs at expiry"| node_expiry
node_timer -->|"creates timers"| node_systemd
node_tui_cmd -->|"starts app"| node_tui
node_tui_cmd -->|"reuses block logic"| node_block
node_tui_cmd -->|"wires list actions"| node_blocklistcmd
node_tui -->|"loads entries"| node_hosts
node_tui -->|"handles form actions"| node_forms
node_tui -->|"renders screens"| node_views
node_user -->|"checks a site"| node_check
node_resolver -->|"answers lookup"| node_dns

click node_binary "https://github.com/mahm0udnasr/sadd/blob/main/main.go"
click node_root "https://github.com/mahm0udnasr/sadd/blob/main/cmd/root.go"
click node_block "https://github.com/mahm0udnasr/sadd/blob/main/cmd/block.go"
click node_unblock "https://github.com/mahm0udnasr/sadd/blob/main/cmd/unblock.go"
click node_listing "https://github.com/mahm0udnasr/sadd/blob/main/cmd/list.go"
click node_groups "https://github.com/mahm0udnasr/sadd/blob/main/internal/groups/groups.go"
click node_groupcmd "https://github.com/mahm0udnasr/sadd/blob/main/cmd/groups.go"
click node_blocklistcmd "https://github.com/mahm0udnasr/sadd/blob/main/cmd/blocklist.go"
click node_blocklist "https://github.com/mahm0udnasr/sadd/blob/main/internal/blocklist/blocklist.go"
click node_check "https://github.com/mahm0udnasr/sadd/blob/main/cmd/check.go"
click node_hosts "https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/hosts.go"
click node_hostswrite "https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/write.go"
click node_atomic "https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/atomic.go"
click node_restore "https://github.com/mahm0udnasr/sadd/blob/main/cmd/restore.go"
click node_expiry "https://github.com/mahm0udnasr/sadd/blob/main/cmd/expire.go"
click node_timer "https://github.com/mahm0udnasr/sadd/blob/main/internal/timer/timer.go"
click node_dns "https://github.com/mahm0udnasr/sadd/blob/main/internal/dns/dns.go"
click node_tui_cmd "https://github.com/mahm0udnasr/sadd/blob/main/cmd/tui.go"
click node_tui "https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/tui.go"
click node_forms "https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/forms.go"
click node_views "https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/view.go"

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_binary,node_root,node_user toneBlue
class node_block,node_unblock,node_listing,node_groups,node_groupcmd,node_blocklistcmd,node_blocklist,node_check toneAmber
class node_hosts,node_hostswrite,node_atomic,node_restore toneMint
class node_expiry,node_timer,node_dns toneRose
class node_tui_cmd,node_tui,node_forms,node_views,node_systemd,node_resolver toneIndigo
```

## Components

### Entry points

- [sadd binary](https://github.com/mahm0udnasr/sadd/blob/main/main.go): `main.go`
- [Command router](https://github.com/mahm0udnasr/sadd/blob/main/cmd/root.go): `cmd/root.go`

### Blocking features

- [Block sites](https://github.com/mahm0udnasr/sadd/blob/main/cmd/block.go): `cmd/block.go`
- [Unblock sites](https://github.com/mahm0udnasr/sadd/blob/main/cmd/unblock.go): `cmd/unblock.go`
- [List blocks](https://github.com/mahm0udnasr/sadd/blob/main/cmd/list.go): `cmd/list.go`
- [Built-in groups](https://github.com/mahm0udnasr/sadd/blob/main/internal/groups/groups.go): `internal/groups/groups.go`
- [Groups command](https://github.com/mahm0udnasr/sadd/blob/main/cmd/groups.go): `cmd/groups.go`
- [Blocklist controls](https://github.com/mahm0udnasr/sadd/blob/main/cmd/blocklist.go): `cmd/blocklist.go`
- [List download and parsing](https://github.com/mahm0udnasr/sadd/blob/main/internal/blocklist/blocklist.go): `internal/blocklist/blocklist.go`
- [Blocking check](https://github.com/mahm0udnasr/sadd/blob/main/cmd/check.go): `cmd/check.go`

### Hosts state

- [Hosts file state](https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/hosts.go): `internal/hosts/hosts.go`
- [Safe file writes](https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/write.go): `internal/hosts/write.go`
- [Atomic replacement](https://github.com/mahm0udnasr/sadd/blob/main/internal/hosts/atomic.go): `internal/hosts/atomic.go`
- [Restore backup](https://github.com/mahm0udnasr/sadd/blob/main/cmd/restore.go): `cmd/restore.go`

### System services

- [Expire timed blocks](https://github.com/mahm0udnasr/sadd/blob/main/cmd/expire.go): `cmd/expire.go`
- [Systemd timers](https://github.com/mahm0udnasr/sadd/blob/main/internal/timer/timer.go): `internal/timer/timer.go`
- [System DNS lookup](https://github.com/mahm0udnasr/sadd/blob/main/internal/dns/dns.go): `internal/dns/dns.go`

### Interactive interface

- [TUI launcher](https://github.com/mahm0udnasr/sadd/blob/main/cmd/tui.go): `cmd/tui.go`
- [Interactive app](https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/tui.go): `internal/tui/tui.go`
- [Action forms](https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/forms.go): `internal/tui/forms.go`
- [Screens and views](https://github.com/mahm0udnasr/sadd/blob/main/internal/tui/view.go): `internal/tui/view.go`

### Other components

- **User**
- **systemd**
- **System resolver**

## Connections

- User → sadd binary: runs (evidence: `README.md`)
- sadd binary → Command router: executes (evidence: `main.go`)
- Command router → TUI launcher: opens by default (evidence: `cmd/root.go`)
- Command router → Block sites: routes commands (evidence: `cmd/root.go`)
- Block sites → Hosts file state: updates (evidence: `cmd/block.go`)
- Block sites → Systemd timers: schedules expiry (evidence: `cmd/block.go`)
- Unblock sites → Hosts file state: removes entries
- List blocks → Hosts file state: reads entries (evidence: `cmd/list.go`)
- Groups command → Built-in groups: lists groups (evidence: `cmd/groups.go`)
- Blocklist controls → List download and parsing: downloads lists (evidence: `cmd/blocklist.go`)
- Blocklist controls → Hosts file state: reads and updates (evidence: `cmd/blocklist.go`)
- Blocking check → Hosts file state: reads blocked domains (evidence: `cmd/check.go`)
- Blocking check → System DNS lookup: checks resolution (evidence: `cmd/check.go`)
- Safe file writes → Atomic replacement: replaces safely
- Restore backup → Hosts file state: restores backup (evidence: `cmd/restore.go`)
- Expire timed blocks → Hosts file state: expires entries (evidence: `cmd/expire.go`)
- Expire timed blocks → Systemd timers: reschedules (evidence: `cmd/expire.go`)
- systemd → Expire timed blocks: runs at expiry (evidence: `README.md`)
- Systemd timers → systemd: creates timers
- TUI launcher → Interactive app: starts app (evidence: `cmd/tui.go`)
- TUI launcher → Block sites: reuses block logic (evidence: `cmd/tui.go`)
- TUI launcher → Blocklist controls: wires list actions (evidence: `cmd/tui.go`)
- Interactive app → Hosts file state: loads entries (evidence: `internal/tui/tui.go`)
- Interactive app → Action forms: handles form actions (evidence: `internal/tui/tui.go`)
- Interactive app → Screens and views: renders screens (evidence: `internal/tui/view.go`)
- User → Blocking check: checks a site (evidence: `README.md`)
- System resolver → System DNS lookup: answers lookup (evidence: `README.md`)
