hosts/docs/user-guide.md

272 lines
11 KiB
Markdown

# User guide
`hosts` is a keyboard-first terminal application for inspecting and editing the
system Hosts File. It starts in Read-only Mode and requires explicit sudo
authorization before it can change `/etc/hosts`.
> [!WARNING]
> `hosts` is alpha software. Read [Persistence and recovery](#persistence-and-recovery)
> before entering Privileged Mode. In particular, sorting and save
> failures can currently leave the interface and `/etc/hosts` out of sync.
## Before you begin
You need macOS or Linux, Python 3.13 or newer, `sudo`, and
[uv](https://docs.astral.sh/uv/). The normal user entry point runs the current
revision from the project's default branch:
```bash
uvx git+https://git.s1q.dev/phg/hosts.git
```
The project does not yet publish versioned releases. The `uvx` command can
therefore run newer code on a later invocation.
## Inspect the Hosts File safely
The application opens in Read-only Mode. In this mode you can:
- select a Host Entry and inspect all of its hostnames, comment, state, and DNS
details;
- search by hostname, IP address, or comment;
- use `Ctrl+F` to combine status, entry-type, DNS-resolution, and search
filters;
- sort by IP address or Canonical Hostname;
- show or hide Default Entries from the configuration screen; and
- reload `/etc/hosts` from disk.
The footer shows `Read-only` while system-file mutations are blocked. Press `?`
for in-application help.
### A warning about sorting
Sorting is intended as a view operation, but currently reorders the in-memory
Hosts File. If you later enter Privileged Mode and save or perform an auto-saved
mutation, that sorted order can be written to `/etc/hosts`. Reload with `Ctrl+R`
before entering Privileged Mode if you sorted only for inspection.
## Enter Privileged Mode
Press `Ctrl+E`. The application first checks for existing sudo authorization.
If authorization is not already available, it temporarily returns control of
the terminal to `sudo` and its configured PAM authentication method. Before
enabling mutations it verifies write access and creates a Pre-edit Backup.
If authorization, permission validation, or backup creation fails, the
application remains in Read-only Mode.
The footer shows `PRIVILEGED` while Privileged Mode is active. This label is
separate from the Entry Editor used to change one Host Entry.
## Change a Host Entry
In Privileged Mode:
- Press `n` to add a Host Entry.
- Press `Shift+N` to add a Host Entry based on the selected Host Entry. In a
terminal without the Kitty enhanced keyboard protocol, uppercase `N` is the
fallback, so Caps Lock also triggers this action.
- Select a non-default Host Entry and press `e` to open the Entry Editor.
- Press `d` and confirm to delete the selected Host Entry.
- Press `Space` to activate or deactivate the selected Host Entry.
- Press `Shift+Up` or `Shift+Down` to change its file order.
A Host Entry requires a valid IPv4 or IPv6 address, at least one valid hostname,
and may include a comment. The first hostname is its Canonical Hostname; any
additional hostnames are Aliases.
Default Entries represent protected baseline localhost or broadcasthost
mappings. They cannot be changed, deleted, activated, deactivated, or moved.
Successful mutations are saved to `/etc/hosts` immediately. Read the
status message after every action. If saving fails, the application restores
the Host Entries, visible selection, and undo/redo history from before the
action.
## Use a DNS Entry
Choose the DNS Name Entry type when adding or editing an entry, then provide:
- the DNS name whose address should be resolved; and
- one or more local hostnames that should map to that address.
The application resolves the DNS name in the background. A successful result
replaces the entry's stored IP address, records DNS metadata in the serialized
comment, activates a newly created DNS Entry, and saves the Hosts File. DNS
refresh is manual rather than continuous:
- Press `r` to refresh the selected DNS Entry.
- Press `Shift+R` to refresh all DNS Entries.
Both actions require Privileged Mode because a successful result changes
`/etc/hosts`. A failed lookup reports the failure and keeps the previously
stored mapping.
## Verify what is on disk
The details shown by the application normally match the last successful save.
To discard in-memory state and read `/etc/hosts` again, press `Ctrl+R`.
You can also inspect the file from another terminal:
```bash
sed -n '1,240p' /etc/hosts
```
Remember that saving is normalized rather than byte-preserving. The serializer
aligns fields, groups comments, removes original blank-line placement, and adds
a management header while retaining the modeled Host Entries and comments.
## Persistence and recovery
### What saves immediately
Adding, editing, deleting, moving, activating, deactivating, undoing, redoing,
and successfully refreshing DNS Entries save immediately. `Ctrl+S` explicitly
saves the entire current in-memory Hosts File.
If an immediate save fails, the application restores the complete pre-action
in-memory state, visible selection, and undo/redo history. A later mutation
therefore cannot accidentally persist the failed change.
### Restore the session Pre-edit Backup
Entering Privileged Mode creates one timestamped Pre-edit Backup below the
operating system's temporary directory. While that Privileged Mode session is
active, press `b` to open the restore review. It displays the exact backup
source path and `/etc/hosts` target path, then shows a Git-style diff of the
current Hosts File (before) and Pre-edit Backup (after restoration). At 120 or
more columns the diff is side by side; at smaller supported sizes it is a
unified diff. Use `[` and `]` to move between changed hunks, `f` to toggle the
full diff, and `r` to refresh it.
Choose **Restore Hosts File** only when those paths are the ones you intend.
The application copies the displayed backup over the Hosts File, reloads the
on-disk contents into the interface, and clears undo/redo history. If the copy
fails, the current Hosts File and interface remain unchanged and the status
message names the failure. The application checks both displayed files again
when you confirm; if either changed, it refreshes the diff and requires a new
confirmation. Cancel leaves both files unchanged.
The TUI does not list old backups, apply retention rules, or retain the session
association after leaving Privileged Mode. For recovery outside that session,
locate and restore a backup manually. Ask Python for the temporary directory on
your system:
```bash
python3 -c 'import tempfile; print(tempfile.gettempdir() + "/hosts-manager-backups")'
```
List the directory printed by that command. Backup files are named
`hosts.backup.<timestamp>`:
```bash
ls -lt /path/printed/by/the/previous/command
```
The application does not remove old Pre-edit Backups, apply retention rules, or
record which file belongs to a later session. Do not choose a backup solely
because it is the newest; inspect its timestamp and contents first.
### Restore manually outside the session
To restore a backup that is no longer associated with an active Privileged Mode
session:
1. Leave the application or return it to Read-only Mode.
2. Locate and inspect the intended Pre-edit Backup.
3. Copy that explicit file over `/etc/hosts` with sudo.
4. Relaunch the application or press `Ctrl+R` to verify the restored contents.
For example, after replacing the placeholder with the exact file you inspected:
```bash
sudo cp /exact/path/to/hosts.backup.TIMESTAMP /etc/hosts
```
This replaces the current Hosts File. Never paste a guessed path or automate
selection of the newest backup without inspecting it.
## Leave Privileged Mode
Press `Ctrl+E` again. The application clears its undo/redo history and forgets
which Pre-edit Backup belongs to the session. The backup file remains in the
temporary directory. It does not alter your cached sudo timestamp, including
authorization used by other terminal sessions.
## Configuration
Press `c` to open configuration. The supported screen controls whether Default
Entries are visible; they are hidden by default. The setting is stored at
`~/.config/hosts-manager/config.json`.
Other values may exist in that file but are internal until their behavior is
reachable through the TUI. Editing them manually is not a supported workflow.
## Troubleshooting
### Privileged Mode needs authentication
This is expected when no cached sudo authorization is available. `hosts` first
shows a temporary authentication notice, then `sudo` and PAM present any
configured authentication method, such as Touch ID or a password prompt.
`hosts` never collects credentials. Canceling authentication leaves the
application in Read-only Mode.
### Privileged Mode cannot be enabled
The application requires all three safety gates: valid sudo authorization,
write access to `/etc/hosts`, and successful creation of a Pre-edit Backup. A
failure in any gate leaves mutations disabled. Read the status message for the
specific failure.
### The display differs from `/etc/hosts`
This can occur after a failed save or sorting followed by other actions. Press
`Ctrl+R` to discard in-memory state and reload the file. If an unwanted change
reached disk, follow the manual restoration procedure above.
### DNS resolution fails
DNS resolution uses the operating system resolver and a per-query timeout. A
failure can result from an invalid DNS name, resolver failure, timeout, or no
address being returned. The application reports the failure rather than
continually retrying it.
## Key reference
### General
| Key | Action |
| --- | --- |
| `Up` / `Down` | Select a Host Entry |
| `Home` / `End` | Select the first or last visible Host Entry |
| `Page Up` / `Page Down` | Move by one page |
| `i` | Sort by IP address |
| `h` | Sort by Canonical Hostname |
| `Ctrl+R` | Reload `/etc/hosts` |
| `Ctrl+F` | Open advanced filters |
| `c` | Open configuration |
| `?` | Show help |
| `q` or `Ctrl+C` | Quit |
| `Ctrl+E` | Enter or leave Privileged Mode |
### Privileged Mode
| Key | Action |
| --- | --- |
| `n` | Add a Host Entry |
| `Shift+N` | Add a Host Entry based on the selected Host Entry (`N` fallback without enhanced keyboard support; Caps Lock also triggers it) |
| `e` | Open the selected Host Entry in the Entry Editor |
| `d` | Delete the selected Host Entry |
| `Space` | Activate or deactivate the selected Host Entry |
| `Shift+Up` / `Shift+Down` | Move the selected Host Entry |
| `r` | Refresh the selected DNS Entry |
| `Shift+R` | Refresh all DNS Entries |
| `Ctrl+Z` / `Ctrl+Y` | Undo or redo and save the result |
| `Ctrl+S` | Save the current in-memory state |
| `b` | Review session backup changes and confirm restoration |
Within the Entry Editor, use `Tab` and `Shift+Tab` to move between fields and
`Escape` to leave the form. If values changed, the application asks whether to
save, discard, or continue editing.