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.
- runtfy-0.1.0/.github/workflows/ci.yml +34 -0
- runtfy-0.1.0/.gitignore +35 -0
- runtfy-0.1.0/CHANGELOG.md +20 -0
- runtfy-0.1.0/CONTRIBUTING.md +64 -0
- runtfy-0.1.0/LICENSE +21 -0
- runtfy-0.1.0/LOCK_CHECKLIST.md +110 -0
- runtfy-0.1.0/PKG-INFO +205 -0
- runtfy-0.1.0/README.md +160 -0
- runtfy-0.1.0/docs/PRD.md +131 -0
- runtfy-0.1.0/pyproject.toml +44 -0
- runtfy-0.1.0/runtfy/__init__.py +1 -0
- runtfy-0.1.0/runtfy/cli.py +73 -0
- runtfy-0.1.0/runtfy/config.py +157 -0
- runtfy-0.1.0/runtfy/hooks.py +253 -0
- runtfy-0.1.0/runtfy/locker.py +194 -0
- runtfy-0.1.0/runtfy/notifier.py +142 -0
- runtfy-0.1.0/runtfy/wrapper.py +281 -0
- runtfy-0.1.0/tests/__init__.py +1 -0
- runtfy-0.1.0/tests/test_cli.py +27 -0
- runtfy-0.1.0/tests/test_config.py +117 -0
- runtfy-0.1.0/tests/test_finish_notification.py +124 -0
- runtfy-0.1.0/tests/test_hooks.py +164 -0
- runtfy-0.1.0/tests/test_hooks_handlers.py +111 -0
- runtfy-0.1.0/tests/test_locker.py +179 -0
- runtfy-0.1.0/tests/test_notifier.py +204 -0
- runtfy-0.1.0/tests/test_wrapper.py +46 -0
|
@@ -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
|
runtfy-0.1.0/.gitignore
ADDED
|
@@ -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).
|