runtfy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ name: CI
2
+
3
+ "on":
4
+ push:
5
+ pull_request:
6
+
7
+
8
+ jobs:
9
+ test:
10
+ name: Test (Python ${{ matrix.python-version }} / ${{ matrix.os }})
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu-latest, macos-latest]
16
+ python-version: ["3.10", "3.11", "3.12"]
17
+
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Install dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ pip install -e ".[dev]"
31
+
32
+ - name: Run test suite
33
+ run: |
34
+ python -m pytest tests/ -v
@@ -0,0 +1,35 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ ENV/
15
+
16
+ # Testing & coverage
17
+ .pytest_cache/
18
+ .coverage
19
+ htmlcov/
20
+
21
+ # Local configs and secrets
22
+ .env
23
+ .env.*
24
+ config.toml
25
+ *.local
26
+
27
+ # Editor directories
28
+ .vscode/
29
+ .idea/
30
+ *.swp
31
+ *.swo
32
+
33
+ # OS files
34
+ .DS_Store
35
+ Thumbs.db
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-10-30
9
+
10
+ - Package scaffolding configured with `hatchling` build system, Python >= 3.10 support, and CLI entrypoint.
11
+ - Pseudo-terminal (PTY) runner (`runtfy/wrapper.py`) supporting transparent stdin, stdout, and stderr passthrough with exact exit code propagation.
12
+ - Configuration manager (`runtfy/config.py`) loading settings from `~/.config/runtfy/config.toml` with owner-only (`0o600`) permissions and fallback defaults.
13
+ - `runtfy init` subcommand generating cryptographically random topics and writing owner-only configuration files.
14
+ - Resilient notification sender (`runtfy/notifier.py`) targeting ntfy via standard library `urllib.request` with 5-second timeout, quiet-hours suppression, event toggles, and strict topic sanitization.
15
+ - Finish notification integration delivering command completion alerts with program basename, elapsed duration, exit status, and opt-in truncated output summaries.
16
+ - Claude Code hook installer (`runtfy install-hooks`) supporting unified diff previews, automatic timestamped backups, and idempotent hook registration.
17
+ - Claude Code lifecycle handlers (`runtfy hook-stop` and `runtfy hook-notify`) providing completion summaries and user input alerts without blocking agent execution.
18
+ - Opt-in `--lock-when-away` mode on macOS utilizing native `pmset displaysleepnow` and `IOHIDSystem` input event monitoring with an enforced 60-second cooldown.
19
+ - Opt-in `--lock-when-away` session locking on Linux via `loginctl`, `xdg-screensaver`, and `gnome-screensaver-command` fallbacks.
20
+ - Comprehensive manual verification checklist (`LOCK_CHECKLIST.md`) for macOS and Linux lock modes.
@@ -0,0 +1,64 @@
1
+ # Contributing to runtfy
2
+
3
+ Thank you for contributing to **runtfy**! We welcome bug reports, documentation updates, and pull requests.
4
+
5
+ ---
6
+
7
+ ## Development Setup
8
+
9
+ 1. **Clone the repository**:
10
+ ```bash
11
+ git clone https://github.com/adilkt16/runtfy.git
12
+ cd runtfy
13
+ ```
14
+
15
+ 2. **Install in editable mode with development dependencies**:
16
+ ```bash
17
+ pip install -e ".[dev]"
18
+ ```
19
+
20
+ 3. **Run the test suite**:
21
+ ```bash
22
+ python -m pytest tests/ -v
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Implementation Rules
28
+
29
+ Every contributor must adhere strictly to these core project rules:
30
+
31
+ 1. **No hardcoded secrets or machine-specific paths**:
32
+ - Never hardcode a topic, token, username, email, or absolute home directory path.
33
+ - Always resolve home directories dynamically using `pathlib.Path.home()`.
34
+ 2. **Never log or print the ntfy topic**:
35
+ - The ntfy topic is considered private. Never print it in debug output, local logs, or test reports.
36
+ 3. **No extraneous network calls**:
37
+ - runtfy must not connect to telemetry, metrics, or third-party tracking services.
38
+ - The only allowed network traffic is directly to the configured ntfy server.
39
+ - All automated unit tests must mock external network calls.
40
+ 4. **Use placeholders everywhere**:
41
+ - Use generic placeholders (such as `your-topic-here` and `~/.config/runtfy`) across all documentation, error strings, and tests.
42
+ 5. **Write tests for every change**:
43
+ - Every bug fix, feature, and refactor must include corresponding unit tests. Run `python -m pytest tests/ -v` and ensure all tests pass before opening a PR.
44
+ 6. **Ask before adding dependencies**:
45
+ - runtfy prioritizes remaining lightweight and audit-friendly. Avoid introducing third-party runtime dependencies without prior discussion and approval.
46
+
47
+ ---
48
+
49
+ ## Submitting a Pull Request
50
+
51
+ 1. Create a feature branch from `main`:
52
+ ```bash
53
+ git checkout -b feature/my-feature-name
54
+ ```
55
+ 2. Make your changes adhering to the coding rules.
56
+ 3. Run the full test suite and confirm 100% pass rate:
57
+ ```bash
58
+ python -m pytest tests/ -v
59
+ ```
60
+ 4. Verify that no secrets, machine paths, or personal emails are present in your diff:
61
+ ```bash
62
+ git diff
63
+ ```
64
+ 5. Commit your changes with clear, descriptive messages and submit a pull request on GitHub.
runtfy-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adil (adilkt16)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,110 @@
1
+ # Manual Verification Checklist: Lock-When-Away
2
+
3
+ This checklist covers manual verification of the `--lock-when-away` feature on macOS and Linux (FR7, FR8, FR12).
4
+
5
+ ---
6
+
7
+ ## Part 1: macOS Verification
8
+
9
+ Tested on macOS Monterey, Ventura, Sonoma, and Sequoia.
10
+
11
+ ### Prerequisites
12
+
13
+ 1. Confirm macOS Lock Screen settings:
14
+ - Open **System Settings** → **Lock Screen** (or **Security & Privacy** on older macOS).
15
+ - Ensure **Require password after display turns off or screen saver begins** is set to **Immediately**.
16
+ 2. Install `runtfy` locally:
17
+ ```bash
18
+ pip install -e .
19
+ ```
20
+ 3. Initialize a test topic and subscribe on your phone:
21
+ ```bash
22
+ runtfy init
23
+ ```
24
+ Confirm you have subscribed to the topic in the ntfy app.
25
+
26
+ ### Test Cases (macOS)
27
+
28
+ #### 1. Basic Screen Lock
29
+ - [ ] Run:
30
+ ```bash
31
+ runtfy --lock-when-away sleep 10
32
+ ```
33
+ - [ ] **Expected**:
34
+ - The display turns off / locks immediately via `pmset displaysleepnow`.
35
+ - No permission prompts (Accessibility or Input Monitoring) appear.
36
+ - After 10 seconds, wake the screen and log in.
37
+ - Phone receives notification: `runtfy: sleep finished` (`Status: ✓ success`).
38
+
39
+ #### 2. Input Alert During Lock
40
+ - [ ] Run:
41
+ ```bash
42
+ runtfy --lock-when-away sleep 30
43
+ ```
44
+ - [ ] Wait 3 seconds for the screen to lock and settle.
45
+ - [ ] Move the mouse or press any key on the keyboard while the screen is locked.
46
+ - [ ] **Expected**:
47
+ - Phone receives notification:
48
+ - **Title**: `runtfy: input detected`
49
+ - **Body**: `Someone typed or moved the mouse while your screen was locked.`
50
+
51
+ #### 3. Cooldown Verification (60-second cooldown)
52
+ - [ ] Keep the screen locked after triggering Test Case 2.
53
+ - [ ] Within 10–20 seconds of the first input alert, move the mouse again.
54
+ - [ ] **Expected**:
55
+ - **No second notification** is sent immediately (enforcing the 60-second cooldown).
56
+ - [ ] Wait at least 65 seconds, then move the mouse again.
57
+ - [ ] **Expected**:
58
+ - Phone receives a second notification: `runtfy: input detected`.
59
+
60
+ #### 4. Lock Failure Fallback (FR12)
61
+ - [ ] Simulate a lock failure (e.g. running in an environment where `pmset` fails):
62
+ ```bash
63
+ runtfy --lock-when-away echo "lock failure test"
64
+ ```
65
+ - [ ] **Expected**:
66
+ - If locking cannot be performed, the command (`echo "lock failure test"`) still executes and exits with its normal exit code.
67
+ - A notification alert is sent indicating that the screen could not be locked.
68
+
69
+ ---
70
+
71
+ ## Part 2: Linux Verification (v0.1)
72
+
73
+ Tested on Ubuntu 22.04+ (GNOME / systemd-logind).
74
+
75
+ ### Linux Scope & Behavior
76
+ - On Linux, `--lock-when-away` locks the session using `loginctl lock-session` (with fallbacks `xdg-screensaver lock` and `gnome-screensaver-command --lock`).
77
+ - **Input watching is NOT implemented on Linux in v0.1** (PRD non-goal). Linux receives the screen lock only.
78
+ - If locking fails, the command still runs and the user is alerted (FR12).
79
+
80
+ ### Test Cases (Linux)
81
+
82
+ #### 1. Basic Screen Lock (loginctl / xdg-screensaver)
83
+ - [ ] In a graphical Linux session (X11 or Wayland), run:
84
+ ```bash
85
+ runtfy --lock-when-away sleep 10
86
+ ```
87
+ - [ ] **Expected**:
88
+ - The desktop locks immediately via `loginctl lock-session` (or fallback).
89
+ - The command runs uninterrupted in the background.
90
+ - After 10 seconds, unlock the screen.
91
+ - Phone receives notification: `runtfy: sleep finished` (`Status: ✓ success`).
92
+
93
+ #### 2. No Input Alerts on Linux (v0.1 Scope)
94
+ - [ ] Run:
95
+ ```bash
96
+ runtfy --lock-when-away sleep 20
97
+ ```
98
+ - [ ] Move the mouse and type while locked.
99
+ - [ ] **Expected**:
100
+ - No input alert is sent (confirming input watching is inactive on Linux in v0.1).
101
+
102
+ #### 3. Lock Failure Fallback (FR12)
103
+ - [ ] Run on a headless terminal or SSH session without a graphical session manager:
104
+ ```bash
105
+ runtfy --lock-when-away echo "headless test"
106
+ ```
107
+ - [ ] **Expected**:
108
+ - A warning message is output indicating lock failure.
109
+ - The command runs and outputs `"headless test"`, exiting with code 0.
110
+ - Phone receives an alert that the screen could not be locked.
runtfy-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,205 @@
1
+ Metadata-Version: 2.5
2
+ Name: runtfy
3
+ Version: 0.1.0
4
+ Summary: A CLI tool that wraps terminal commands and notifies your phone when they finish or need input.
5
+ Project-URL: Homepage, https://github.com/adilkt16/runtfy
6
+ Project-URL: Repository, https://github.com/adilkt16/runtfy
7
+ Project-URL: Bug Tracker, https://github.com/adilkt16/runtfy/issues
8
+ Project-URL: Changelog, https://github.com/adilkt16/runtfy/blob/main/CHANGELOG.md
9
+ Author-email: Adil <adilkt16@users.noreply.github.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Adil (adilkt16)
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Classifier: Environment :: Console
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: MacOS
35
+ Classifier: Operating System :: POSIX :: Linux
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Requires-Python: >=3.10
41
+ Requires-Dist: tomli>=2.0.0; python_version < '3.11'
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest; extra == 'dev'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # runtfy
47
+
48
+ runtfy is an open-source command-line tool. It wraps terminal commands, such as long-running AI coding agent sessions, and sends push notifications to your phone when they complete or when Claude Code requires your input. It also features an opt-in lock-when-away mode that locks your screen while you are away and alerts you if anyone interacts with your machine.
49
+
50
+ ---
51
+
52
+ ## 1. What it does
53
+
54
+ Developers often launch long AI coding runs and walk away, only to find the run finished in minutes and sat idle, or paused for permissions. runtfy bridges this gap by sending instant push notifications to your phone without requiring accounts, hosted servers, or complex setups. It wraps any command cleanly in a pseudo-terminal and exits with the exact same exit code.
55
+
56
+ ---
57
+
58
+ ## 2. Install
59
+
60
+ Install with `pipx` (recommended):
61
+
62
+ ```bash
63
+ pipx install runtfy
64
+ ```
65
+
66
+ Or install with `pip`:
67
+
68
+ ```bash
69
+ pip install runtfy
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 3. Quick start
75
+
76
+ Initialize your private notification topic:
77
+
78
+ ```bash
79
+ runtfy init
80
+ ```
81
+
82
+ Wrap any terminal command:
83
+
84
+ ```bash
85
+ runtfy <your-command>
86
+ ```
87
+
88
+ Examples:
89
+
90
+ ```bash
91
+ runtfy sleep 10
92
+ runtfy pytest tests/
93
+ runtfy claude
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 4. ntfy setup
99
+
100
+ runtfy delivers notifications using [ntfy](https://ntfy.sh), an open-source HTTP-based notification service. No account is required.
101
+
102
+ 1. Install the **ntfy** app on your phone:
103
+ - **iOS**: Available on the [App Store](https://apps.apple.com/app/ntfy/id1625396347).
104
+ - **Android**: Available on [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) or [F-Droid](https://f-droid.org/packages/io.heckel.ntfy/).
105
+ 2. Open the ntfy app and tap **+** (**Subscribe to topic**).
106
+ 3. Enter your generated topic name:
107
+ ```
108
+ your-topic-here
109
+ ```
110
+ 4. Notifications sent by runtfy will immediately appear on your device.
111
+
112
+ ---
113
+
114
+ ## 5. Claude Code hooks
115
+
116
+ runtfy integrates directly with Claude Code via its built-in lifecycle hooks.
117
+
118
+ Install the hooks with:
119
+
120
+ ```bash
121
+ runtfy install-hooks
122
+ ```
123
+
124
+ What this does:
125
+ - Locates `~/.claude/settings.json`.
126
+ - Displays a unified diff of proposed changes.
127
+ - Creates a timestamped backup before writing.
128
+ - Adds the `Stop` hook (`runtfy hook-stop`) and `Notification` hook (`runtfy hook-notify`).
129
+ - Preserves all pre-existing hooks and is idempotent (safe to run multiple times).
130
+
131
+ To verify the installation, inspect `~/.claude/settings.json` to confirm `Stop` and `Notification` entries are present under `"hooks"`.
132
+
133
+ ---
134
+
135
+ ## 6. Lock-when-away
136
+
137
+ Lock your screen while away and alert on unauthorized input:
138
+
139
+ ```bash
140
+ runtfy --lock-when-away <command>
141
+ ```
142
+
143
+ Example:
144
+
145
+ ```bash
146
+ runtfy --lock-when-away claude
147
+ ```
148
+
149
+ ### Important details:
150
+ - **Opt-in only**: Screen locking is never active unless `--lock-when-away` is explicitly provided.
151
+ - **macOS**: Locks the display immediately using `pmset displaysleepnow` (requiring zero Accessibility permissions). It then watches the kernel HID idle counter; if someone touches the keyboard or moves the mouse while locked, runtfy sends an input alert to your phone with an enforced 60-second cooldown between notifications.
152
+ - **Linux (v0.1)**: Locks the graphical session using `loginctl lock-session` (with fallbacks to `xdg-screensaver` and `gnome-screensaver-command`). In v0.1, input alerts on Linux are out of scope; Linux receives the screen lock only.
153
+ - **Resilience**: If screen locking fails, the wrapped command continues to run and a warning notification is sent to your phone.
154
+
155
+ ---
156
+
157
+ ## 7. Configuration
158
+
159
+ Configuration lives at `~/.config/runtfy/config.toml` with owner-only (`0o600`) permissions:
160
+
161
+ ```toml
162
+ [runtfy]
163
+ topic = "your-topic-here" # ntfy topic; generated by runtfy init
164
+ summary = false # opt-in output summary
165
+ summary_lines = 5 # number of lines to include when summary = true
166
+
167
+ [quiet_hours]
168
+ enabled = false # silence notifications during specific hours
169
+ start = "22:00"
170
+ end = "08:00"
171
+
172
+ [events]
173
+ finish = true # notify when wrapped command or Claude session ends
174
+ waiting = true # notify when Claude Code needs input or permission
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 8. Privacy
180
+
181
+ - **Safe defaults**: Notifications contain only the program name (e.g. `claude`, never its arguments), exit code, duration, and status. Arguments are never included because they can contain secrets.
182
+ - **No output leakage**: Command output, file paths, and file contents are never transmitted by default.
183
+ - **Opt-in summaries**: Output summaries are strictly opt-in (`summary = true`).
184
+ - **Secret topic protection**: Your ntfy topic is generated locally, stored in owner-only configuration files (`chmod 600`), and is never printed in logs or committed to version control.
185
+ - **No credential handling**: runtfy never reads, stores, or handles operating system passwords.
186
+ - **No telemetry**: runtfy contains no analytics or tracking. All network calls go exclusively to the configured ntfy server.
187
+ - **Zero personal data**: The repository and default configurations contain no personal names, emails, usernames, or machine paths.
188
+
189
+ ---
190
+
191
+ ## 9. Self-hosting ntfy
192
+
193
+ If you prefer not to use the public `ntfy.sh` server or wish to avoid public server rate limits, you can host your own ntfy instance using Docker or official binary distributions. To direct runtfy to your private instance, set `server = "https://ntfy.example.com"` under `[runtfy]` in `~/.config/runtfy/config.toml`. Refer to the [official ntfy documentation](https://docs.ntfy.sh/) for self-hosting instructions.
194
+
195
+ ---
196
+
197
+ ## 10. Contributing
198
+
199
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup instructions, implementation rules, and pull request guidelines.
200
+
201
+ ---
202
+
203
+ ## 11. Licence
204
+
205
+ This project is licensed under the [MIT Licence](https://opensource.org/licenses/MIT).
runtfy-0.1.0/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # runtfy
2
+
3
+ runtfy is an open-source command-line tool. It wraps terminal commands, such as long-running AI coding agent sessions, and sends push notifications to your phone when they complete or when Claude Code requires your input. It also features an opt-in lock-when-away mode that locks your screen while you are away and alerts you if anyone interacts with your machine.
4
+
5
+ ---
6
+
7
+ ## 1. What it does
8
+
9
+ Developers often launch long AI coding runs and walk away, only to find the run finished in minutes and sat idle, or paused for permissions. runtfy bridges this gap by sending instant push notifications to your phone without requiring accounts, hosted servers, or complex setups. It wraps any command cleanly in a pseudo-terminal and exits with the exact same exit code.
10
+
11
+ ---
12
+
13
+ ## 2. Install
14
+
15
+ Install with `pipx` (recommended):
16
+
17
+ ```bash
18
+ pipx install runtfy
19
+ ```
20
+
21
+ Or install with `pip`:
22
+
23
+ ```bash
24
+ pip install runtfy
25
+ ```
26
+
27
+ ---
28
+
29
+ ## 3. Quick start
30
+
31
+ Initialize your private notification topic:
32
+
33
+ ```bash
34
+ runtfy init
35
+ ```
36
+
37
+ Wrap any terminal command:
38
+
39
+ ```bash
40
+ runtfy <your-command>
41
+ ```
42
+
43
+ Examples:
44
+
45
+ ```bash
46
+ runtfy sleep 10
47
+ runtfy pytest tests/
48
+ runtfy claude
49
+ ```
50
+
51
+ ---
52
+
53
+ ## 4. ntfy setup
54
+
55
+ runtfy delivers notifications using [ntfy](https://ntfy.sh), an open-source HTTP-based notification service. No account is required.
56
+
57
+ 1. Install the **ntfy** app on your phone:
58
+ - **iOS**: Available on the [App Store](https://apps.apple.com/app/ntfy/id1625396347).
59
+ - **Android**: Available on [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) or [F-Droid](https://f-droid.org/packages/io.heckel.ntfy/).
60
+ 2. Open the ntfy app and tap **+** (**Subscribe to topic**).
61
+ 3. Enter your generated topic name:
62
+ ```
63
+ your-topic-here
64
+ ```
65
+ 4. Notifications sent by runtfy will immediately appear on your device.
66
+
67
+ ---
68
+
69
+ ## 5. Claude Code hooks
70
+
71
+ runtfy integrates directly with Claude Code via its built-in lifecycle hooks.
72
+
73
+ Install the hooks with:
74
+
75
+ ```bash
76
+ runtfy install-hooks
77
+ ```
78
+
79
+ What this does:
80
+ - Locates `~/.claude/settings.json`.
81
+ - Displays a unified diff of proposed changes.
82
+ - Creates a timestamped backup before writing.
83
+ - Adds the `Stop` hook (`runtfy hook-stop`) and `Notification` hook (`runtfy hook-notify`).
84
+ - Preserves all pre-existing hooks and is idempotent (safe to run multiple times).
85
+
86
+ To verify the installation, inspect `~/.claude/settings.json` to confirm `Stop` and `Notification` entries are present under `"hooks"`.
87
+
88
+ ---
89
+
90
+ ## 6. Lock-when-away
91
+
92
+ Lock your screen while away and alert on unauthorized input:
93
+
94
+ ```bash
95
+ runtfy --lock-when-away <command>
96
+ ```
97
+
98
+ Example:
99
+
100
+ ```bash
101
+ runtfy --lock-when-away claude
102
+ ```
103
+
104
+ ### Important details:
105
+ - **Opt-in only**: Screen locking is never active unless `--lock-when-away` is explicitly provided.
106
+ - **macOS**: Locks the display immediately using `pmset displaysleepnow` (requiring zero Accessibility permissions). It then watches the kernel HID idle counter; if someone touches the keyboard or moves the mouse while locked, runtfy sends an input alert to your phone with an enforced 60-second cooldown between notifications.
107
+ - **Linux (v0.1)**: Locks the graphical session using `loginctl lock-session` (with fallbacks to `xdg-screensaver` and `gnome-screensaver-command`). In v0.1, input alerts on Linux are out of scope; Linux receives the screen lock only.
108
+ - **Resilience**: If screen locking fails, the wrapped command continues to run and a warning notification is sent to your phone.
109
+
110
+ ---
111
+
112
+ ## 7. Configuration
113
+
114
+ Configuration lives at `~/.config/runtfy/config.toml` with owner-only (`0o600`) permissions:
115
+
116
+ ```toml
117
+ [runtfy]
118
+ topic = "your-topic-here" # ntfy topic; generated by runtfy init
119
+ summary = false # opt-in output summary
120
+ summary_lines = 5 # number of lines to include when summary = true
121
+
122
+ [quiet_hours]
123
+ enabled = false # silence notifications during specific hours
124
+ start = "22:00"
125
+ end = "08:00"
126
+
127
+ [events]
128
+ finish = true # notify when wrapped command or Claude session ends
129
+ waiting = true # notify when Claude Code needs input or permission
130
+ ```
131
+
132
+ ---
133
+
134
+ ## 8. Privacy
135
+
136
+ - **Safe defaults**: Notifications contain only the program name (e.g. `claude`, never its arguments), exit code, duration, and status. Arguments are never included because they can contain secrets.
137
+ - **No output leakage**: Command output, file paths, and file contents are never transmitted by default.
138
+ - **Opt-in summaries**: Output summaries are strictly opt-in (`summary = true`).
139
+ - **Secret topic protection**: Your ntfy topic is generated locally, stored in owner-only configuration files (`chmod 600`), and is never printed in logs or committed to version control.
140
+ - **No credential handling**: runtfy never reads, stores, or handles operating system passwords.
141
+ - **No telemetry**: runtfy contains no analytics or tracking. All network calls go exclusively to the configured ntfy server.
142
+ - **Zero personal data**: The repository and default configurations contain no personal names, emails, usernames, or machine paths.
143
+
144
+ ---
145
+
146
+ ## 9. Self-hosting ntfy
147
+
148
+ If you prefer not to use the public `ntfy.sh` server or wish to avoid public server rate limits, you can host your own ntfy instance using Docker or official binary distributions. To direct runtfy to your private instance, set `server = "https://ntfy.example.com"` under `[runtfy]` in `~/.config/runtfy/config.toml`. Refer to the [official ntfy documentation](https://docs.ntfy.sh/) for self-hosting instructions.
149
+
150
+ ---
151
+
152
+ ## 10. Contributing
153
+
154
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup instructions, implementation rules, and pull request guidelines.
155
+
156
+ ---
157
+
158
+ ## 11. Licence
159
+
160
+ This project is licensed under the [MIT Licence](https://opensource.org/licenses/MIT).