haoleme 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.
- haoleme-0.1.0/PKG-INFO +268 -0
- haoleme-0.1.0/README.md +258 -0
- haoleme-0.1.0/pyproject.toml +19 -0
- haoleme-0.1.0/setup.cfg +4 -0
- haoleme-0.1.0/src/haoleme/__init__.py +3 -0
- haoleme-0.1.0/src/haoleme/__main__.py +5 -0
- haoleme-0.1.0/src/haoleme/cli.py +3 -0
- haoleme-0.1.0/src/haoleme/cloud_server.py +3 -0
- haoleme-0.1.0/src/haoleme.egg-info/PKG-INFO +268 -0
- haoleme-0.1.0/src/haoleme.egg-info/SOURCES.txt +25 -0
- haoleme-0.1.0/src/haoleme.egg-info/dependency_links.txt +1 -0
- haoleme-0.1.0/src/haoleme.egg-info/entry_points.txt +3 -0
- haoleme-0.1.0/src/haoleme.egg-info/requires.txt +2 -0
- haoleme-0.1.0/src/haoleme.egg-info/top_level.txt +2 -0
- haoleme-0.1.0/src/remindrun/__init__.py +1 -0
- haoleme-0.1.0/src/remindrun/__main__.py +6 -0
- haoleme-0.1.0/src/remindrun/cli.py +789 -0
- haoleme-0.1.0/src/remindrun/cloud.py +263 -0
- haoleme-0.1.0/src/remindrun/cloud_server.py +1319 -0
- haoleme-0.1.0/src/remindrun/crypto.py +107 -0
- haoleme-0.1.0/src/remindrun/server.py +131 -0
- haoleme-0.1.0/src/remindrun/store.py +262 -0
- haoleme-0.1.0/tests/test_cli.py +141 -0
- haoleme-0.1.0/tests/test_cloud.py +77 -0
- haoleme-0.1.0/tests/test_cloud_server.py +276 -0
- haoleme-0.1.0/tests/test_crypto.py +62 -0
- haoleme-0.1.0/tests/test_store.py +67 -0
haoleme-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: haoleme
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Run commands with Haoleme monitoring and expose their status to the mobile app.
|
|
5
|
+
Author: Haoleme
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: cryptography>=42
|
|
9
|
+
Requires-Dist: qrcode>=7.4
|
|
10
|
+
|
|
11
|
+
# 好了么
|
|
12
|
+
|
|
13
|
+
好了么 is a command monitor for Linux/macOS machines with Android and iOS apps.
|
|
14
|
+
|
|
15
|
+
The project has three parts:
|
|
16
|
+
|
|
17
|
+
- `haoleme`: a Python package that installs the `hao` command. Put `hao` before a command to record its status, output tail, exit code, and timestamps.
|
|
18
|
+
- `android/`: a native Android app for pairing, device switching, run history, console output, deletion, and finish notifications.
|
|
19
|
+
- `ios/`: a native SwiftUI iOS app that uses the same 好了么 Cloud account, devices, runs, pairing, and console APIs.
|
|
20
|
+
|
|
21
|
+
## Python monitor
|
|
22
|
+
|
|
23
|
+
Install the local package in a virtual environment:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python3 -m venv .venv
|
|
27
|
+
.venv/bin/python -m pip install -e .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or install the built wheel:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
.venv/bin/python -m pip install dist/haoleme-0.1.0-py3-none-any.whl
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Start the status server on the Linux machine:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
hao server --host 0.0.0.0 --port 8765 --token change-this-token
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run commands through 好了么:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
hao sleep 5
|
|
46
|
+
hao run -- bash -lc 'echo hello && sleep 2 && echo done'
|
|
47
|
+
hao status
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The command name is intentionally short: `hao`.
|
|
51
|
+
|
|
52
|
+
## Cloud sync
|
|
53
|
+
|
|
54
|
+
The recommended setup is cloud sync. The Linux machine does not need a public IP, ngrok, or port forwarding. The command runner uploads status to 好了么 Cloud, and the Android app reads the same account from the cloud API.
|
|
55
|
+
|
|
56
|
+
The default cloud relay is:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
http://106.14.246.204
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
After deploying the Docker cloud server on Aliyun or the Cloudflare Worker in `cloudflare/`, log in once on each new machine:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install -U haoleme
|
|
66
|
+
hao login
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The command prints a QR code and a 6-digit pair code. The cloud URL is built in and hidden from the normal UI. Pair codes expire after 5 minutes and are cancelled automatically when `hao login` exits without pairing.
|
|
70
|
+
If the machine is already logged in, `hao login` asks before replacing the login. Press Enter to continue, or type `n` to cancel.
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
847291
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Tap Scan in the Android app to scan the QR code with the built-in camera scanner, or scan it with the phone camera to open 好了么 and pair automatically. If QR scanning is unavailable, enter the 6-digit code; the app pairs automatically when all 6 digits are entered. After pairing, the app saves the cloud account, shows the paired device name, and normal commands sync automatically:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
hao run -- python train.py
|
|
80
|
+
hao run -- sh -c 'for i in $(seq 1 10); do echo tick $i; sleep 1; done'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
New pairings use end-to-end encryption for command text, working directory, and console output. 好了么 Cloud keeps the encrypted payload plus operational metadata such as device id, status, and timestamps, so filtering and online state still work while the sensitive run details are decrypted only in the app.
|
|
84
|
+
|
|
85
|
+
Each computer that runs `hao login` is bound as a device on the same phone account. Use names such as `我的 Mac`, `服务器 A`, or `实验机 B`:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
hao login --device "服务器 A"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The Android app shows an `All` device view plus one button for each paired computer, so you can switch between all runs and a single machine. Select one device and tap Rename, or long-press a device button, to rename it. Tap Revoke to disable that device's upload token without deleting old history.
|
|
92
|
+
|
|
93
|
+
Useful cloud commands:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
hao heartbeat status
|
|
97
|
+
hao heartbeat start
|
|
98
|
+
hao heartbeat stop
|
|
99
|
+
hao cloud-status
|
|
100
|
+
hao cloud-logout
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
After login, `hao` starts a small background heartbeat automatically. The cloud marks a device online when it has been seen in the last 90 seconds; each device sends a heartbeat every 60 seconds with a device-specific 0-59 second startup offset to avoid synchronized traffic spikes.
|
|
104
|
+
|
|
105
|
+
Advanced/manual login is still available:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
hao cloud-login --api-url https://your-haoleme-cloud.workers.dev --account ethan --token <TOKEN>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Cloud sync uses the app's account token as the account key. Anyone with that token can delete that account's run history and read unencrypted legacy records, so treat it like a password.
|
|
112
|
+
|
|
113
|
+
### Deploy 好了么 Cloud with Docker
|
|
114
|
+
|
|
115
|
+
The Docker cloud server exposes the same API as the Cloudflare Worker and stores data in SQLite:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
docker build -f Dockerfile.cloud -t haoleme-cloud .
|
|
119
|
+
docker run -d --name haoleme-cloud --restart unless-stopped \
|
|
120
|
+
-p 80:8000 \
|
|
121
|
+
-v /opt/haoleme-cloud-data:/data \
|
|
122
|
+
haoleme-cloud
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Check it:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
curl http://106.14.246.204/health
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
For production, prefer putting a domain and HTTPS reverse proxy in front of it. Plain HTTP works for quick testing because the Android app allows cleartext traffic, but HTTPS is safer.
|
|
132
|
+
|
|
133
|
+
### Deploy 好了么 Cloud
|
|
134
|
+
|
|
135
|
+
The included Cloudflare Worker is a small relay service. It stores only command metadata and output tails in Cloudflare KV. The Python runner also keeps a local SQLite database at `~/.reminder/reminder.db`, and the Android app caches the latest run list and console output locally so the previous results are visible when the app opens.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
cd cloudflare
|
|
139
|
+
npm create cloudflare@latest
|
|
140
|
+
npx wrangler kv namespace create RUNS
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Copy the returned KV namespace id into `cloudflare/wrangler.toml`, then deploy:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npx wrangler deploy
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Cloudflare Workers can run this kind of small personal relay on the free plan within their free usage limits. For many users, long logs, or heavy polling, use a paid plan or a small VPS.
|
|
150
|
+
|
|
151
|
+
The server exposes:
|
|
152
|
+
|
|
153
|
+
- `GET /health`
|
|
154
|
+
- `GET /api/runs?limit=50`
|
|
155
|
+
- `GET /api/runs/{id}`
|
|
156
|
+
- `GET /api/events?since=<updatedAt>`
|
|
157
|
+
|
|
158
|
+
By default the SQLite database lives at `~/.reminder/reminder.db`. Set `REMINDER_HOME=/path/to/dir` to change that location.
|
|
159
|
+
|
|
160
|
+
## Direct public access
|
|
161
|
+
|
|
162
|
+
Direct public access is still supported for testing and compatibility. If you do not want cloud sync and do not have a public IP, use a Cloudflare quick tunnel:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
hao public
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This starts the local server and runs `cloudflared tunnel --url http://127.0.0.1:8765`. It prints a public `https://*.trycloudflare.com` URL and a token. Newer Android builds default to the built-in cloud pairing flow, so direct server entry is kept only for development and compatibility:
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
Server: https://example.trycloudflare.com
|
|
172
|
+
Token: generated-token
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
If `cloudflared` is missing, install it first:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
brew install cloudflared
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Cloudflare quick tunnel URLs are random. If you need the same URL every time and do not own a domain, use ngrok's free Dev Domain:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
brew install ngrok/ngrok/ngrok
|
|
185
|
+
ngrok config add-authtoken <YOUR_NGROK_AUTHTOKEN>
|
|
186
|
+
hao ngrok --domain <YOUR_DEV_DOMAIN>.ngrok-free.dev
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Older Android builds with manual server entry can use:
|
|
190
|
+
|
|
191
|
+
```text
|
|
192
|
+
Server: https://<YOUR_DEV_DOMAIN>.ngrok-free.dev
|
|
193
|
+
Token: generated-token
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If the Android app needs to connect to a server that already has a public IP or a public domain:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
hao server --host 0.0.0.0 --port 8765 --token a-long-random-token
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Then open TCP port `8765` in the cloud security group or firewall.
|
|
203
|
+
|
|
204
|
+
In the Android app:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
Server: http://<public-ip>:8765
|
|
208
|
+
Token: a-long-random-token
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
For real public use, prefer HTTPS through a reverse proxy or tunnel. Plain `http://<public-ip>:8765` works for testing, but the token can be observed on an untrusted network.
|
|
212
|
+
|
|
213
|
+
## Android app
|
|
214
|
+
|
|
215
|
+
Open the `android/` directory in Android Studio.
|
|
216
|
+
|
|
217
|
+
For an emulator, the default server URL is:
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
http://10.0.2.2:8765
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
For a physical phone, start the server with `--host 0.0.0.0`, put the phone on the same network, then set the app server URL to:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
http://<linux-machine-ip>:8765
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If the server was started with `--token`, enter the same token in the app's Token field.
|
|
230
|
+
|
|
231
|
+
Tap Save to lock the Server and Token fields. Tap Unlock before editing them again.
|
|
232
|
+
|
|
233
|
+
Tap Delete on a run in the history list to delete it from the server.
|
|
234
|
+
|
|
235
|
+
Tap a run, or tap Console, to open the run's terminal output. Use Back to return to the main list.
|
|
236
|
+
|
|
237
|
+
## App updates
|
|
238
|
+
|
|
239
|
+
Sideloaded APKs cannot discover updates by themselves unless the app can read a public version file.
|
|
240
|
+
GitHub is not required. For mainland China, prefer a mirror such as Gitee, Aliyun OSS, Tencent COS, Qiniu, or Upyun, and keep GitHub as a fallback.
|
|
241
|
+
|
|
242
|
+
This app defaults to checking these sources in order:
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
https://gitee.com/hushuguo/reminder/raw/main/update.json
|
|
246
|
+
https://raw.githubusercontent.com/hushuguo/Reminder/main/update.json
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Create a public JSON file like `update.json`:
|
|
250
|
+
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"android": {
|
|
254
|
+
"versionCode": 34,
|
|
255
|
+
"versionName": "0.6.23",
|
|
256
|
+
"apkUrl": "http://106.14.246.204/downloads/Haoleme-0.6.38.apk",
|
|
257
|
+
"apkUrls": [
|
|
258
|
+
"http://106.14.246.204/downloads/Haoleme-0.6.38.apk"
|
|
259
|
+
],
|
|
260
|
+
"notes": "Keeps deleted run records consistent between All, device views, filters, and cached details."
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The update URLs are built into the app and are not shown to users. On startup, the app checks for updates in the background.
|
|
266
|
+
If `versionCode` is higher than the installed APK, the app shows an update label with the new version in the top-right corner. Tap it to download the APK in-app with progress shown in the status area. If download or installation fails, the installed version is left untouched.
|
|
267
|
+
|
|
268
|
+
This prototype polls every 5 seconds while the app process is alive. A later version should move polling into a foreground service or push channel if you want reliable notifications while the app is fully backgrounded.
|
haoleme-0.1.0/README.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# 好了么
|
|
2
|
+
|
|
3
|
+
好了么 is a command monitor for Linux/macOS machines with Android and iOS apps.
|
|
4
|
+
|
|
5
|
+
The project has three parts:
|
|
6
|
+
|
|
7
|
+
- `haoleme`: a Python package that installs the `hao` command. Put `hao` before a command to record its status, output tail, exit code, and timestamps.
|
|
8
|
+
- `android/`: a native Android app for pairing, device switching, run history, console output, deletion, and finish notifications.
|
|
9
|
+
- `ios/`: a native SwiftUI iOS app that uses the same 好了么 Cloud account, devices, runs, pairing, and console APIs.
|
|
10
|
+
|
|
11
|
+
## Python monitor
|
|
12
|
+
|
|
13
|
+
Install the local package in a virtual environment:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python3 -m venv .venv
|
|
17
|
+
.venv/bin/python -m pip install -e .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or install the built wheel:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
.venv/bin/python -m pip install dist/haoleme-0.1.0-py3-none-any.whl
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Start the status server on the Linux machine:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
hao server --host 0.0.0.0 --port 8765 --token change-this-token
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Run commands through 好了么:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
hao sleep 5
|
|
36
|
+
hao run -- bash -lc 'echo hello && sleep 2 && echo done'
|
|
37
|
+
hao status
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The command name is intentionally short: `hao`.
|
|
41
|
+
|
|
42
|
+
## Cloud sync
|
|
43
|
+
|
|
44
|
+
The recommended setup is cloud sync. The Linux machine does not need a public IP, ngrok, or port forwarding. The command runner uploads status to 好了么 Cloud, and the Android app reads the same account from the cloud API.
|
|
45
|
+
|
|
46
|
+
The default cloud relay is:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
http://106.14.246.204
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
After deploying the Docker cloud server on Aliyun or the Cloudflare Worker in `cloudflare/`, log in once on each new machine:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install -U haoleme
|
|
56
|
+
hao login
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The command prints a QR code and a 6-digit pair code. The cloud URL is built in and hidden from the normal UI. Pair codes expire after 5 minutes and are cancelled automatically when `hao login` exits without pairing.
|
|
60
|
+
If the machine is already logged in, `hao login` asks before replacing the login. Press Enter to continue, or type `n` to cancel.
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
847291
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Tap Scan in the Android app to scan the QR code with the built-in camera scanner, or scan it with the phone camera to open 好了么 and pair automatically. If QR scanning is unavailable, enter the 6-digit code; the app pairs automatically when all 6 digits are entered. After pairing, the app saves the cloud account, shows the paired device name, and normal commands sync automatically:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
hao run -- python train.py
|
|
70
|
+
hao run -- sh -c 'for i in $(seq 1 10); do echo tick $i; sleep 1; done'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
New pairings use end-to-end encryption for command text, working directory, and console output. 好了么 Cloud keeps the encrypted payload plus operational metadata such as device id, status, and timestamps, so filtering and online state still work while the sensitive run details are decrypted only in the app.
|
|
74
|
+
|
|
75
|
+
Each computer that runs `hao login` is bound as a device on the same phone account. Use names such as `我的 Mac`, `服务器 A`, or `实验机 B`:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
hao login --device "服务器 A"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The Android app shows an `All` device view plus one button for each paired computer, so you can switch between all runs and a single machine. Select one device and tap Rename, or long-press a device button, to rename it. Tap Revoke to disable that device's upload token without deleting old history.
|
|
82
|
+
|
|
83
|
+
Useful cloud commands:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
hao heartbeat status
|
|
87
|
+
hao heartbeat start
|
|
88
|
+
hao heartbeat stop
|
|
89
|
+
hao cloud-status
|
|
90
|
+
hao cloud-logout
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
After login, `hao` starts a small background heartbeat automatically. The cloud marks a device online when it has been seen in the last 90 seconds; each device sends a heartbeat every 60 seconds with a device-specific 0-59 second startup offset to avoid synchronized traffic spikes.
|
|
94
|
+
|
|
95
|
+
Advanced/manual login is still available:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
hao cloud-login --api-url https://your-haoleme-cloud.workers.dev --account ethan --token <TOKEN>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Cloud sync uses the app's account token as the account key. Anyone with that token can delete that account's run history and read unencrypted legacy records, so treat it like a password.
|
|
102
|
+
|
|
103
|
+
### Deploy 好了么 Cloud with Docker
|
|
104
|
+
|
|
105
|
+
The Docker cloud server exposes the same API as the Cloudflare Worker and stores data in SQLite:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
docker build -f Dockerfile.cloud -t haoleme-cloud .
|
|
109
|
+
docker run -d --name haoleme-cloud --restart unless-stopped \
|
|
110
|
+
-p 80:8000 \
|
|
111
|
+
-v /opt/haoleme-cloud-data:/data \
|
|
112
|
+
haoleme-cloud
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Check it:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
curl http://106.14.246.204/health
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For production, prefer putting a domain and HTTPS reverse proxy in front of it. Plain HTTP works for quick testing because the Android app allows cleartext traffic, but HTTPS is safer.
|
|
122
|
+
|
|
123
|
+
### Deploy 好了么 Cloud
|
|
124
|
+
|
|
125
|
+
The included Cloudflare Worker is a small relay service. It stores only command metadata and output tails in Cloudflare KV. The Python runner also keeps a local SQLite database at `~/.reminder/reminder.db`, and the Android app caches the latest run list and console output locally so the previous results are visible when the app opens.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
cd cloudflare
|
|
129
|
+
npm create cloudflare@latest
|
|
130
|
+
npx wrangler kv namespace create RUNS
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Copy the returned KV namespace id into `cloudflare/wrangler.toml`, then deploy:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx wrangler deploy
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Cloudflare Workers can run this kind of small personal relay on the free plan within their free usage limits. For many users, long logs, or heavy polling, use a paid plan or a small VPS.
|
|
140
|
+
|
|
141
|
+
The server exposes:
|
|
142
|
+
|
|
143
|
+
- `GET /health`
|
|
144
|
+
- `GET /api/runs?limit=50`
|
|
145
|
+
- `GET /api/runs/{id}`
|
|
146
|
+
- `GET /api/events?since=<updatedAt>`
|
|
147
|
+
|
|
148
|
+
By default the SQLite database lives at `~/.reminder/reminder.db`. Set `REMINDER_HOME=/path/to/dir` to change that location.
|
|
149
|
+
|
|
150
|
+
## Direct public access
|
|
151
|
+
|
|
152
|
+
Direct public access is still supported for testing and compatibility. If you do not want cloud sync and do not have a public IP, use a Cloudflare quick tunnel:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
hao public
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
This starts the local server and runs `cloudflared tunnel --url http://127.0.0.1:8765`. It prints a public `https://*.trycloudflare.com` URL and a token. Newer Android builds default to the built-in cloud pairing flow, so direct server entry is kept only for development and compatibility:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
Server: https://example.trycloudflare.com
|
|
162
|
+
Token: generated-token
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If `cloudflared` is missing, install it first:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
brew install cloudflared
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Cloudflare quick tunnel URLs are random. If you need the same URL every time and do not own a domain, use ngrok's free Dev Domain:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
brew install ngrok/ngrok/ngrok
|
|
175
|
+
ngrok config add-authtoken <YOUR_NGROK_AUTHTOKEN>
|
|
176
|
+
hao ngrok --domain <YOUR_DEV_DOMAIN>.ngrok-free.dev
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Older Android builds with manual server entry can use:
|
|
180
|
+
|
|
181
|
+
```text
|
|
182
|
+
Server: https://<YOUR_DEV_DOMAIN>.ngrok-free.dev
|
|
183
|
+
Token: generated-token
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
If the Android app needs to connect to a server that already has a public IP or a public domain:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
hao server --host 0.0.0.0 --port 8765 --token a-long-random-token
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Then open TCP port `8765` in the cloud security group or firewall.
|
|
193
|
+
|
|
194
|
+
In the Android app:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
Server: http://<public-ip>:8765
|
|
198
|
+
Token: a-long-random-token
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
For real public use, prefer HTTPS through a reverse proxy or tunnel. Plain `http://<public-ip>:8765` works for testing, but the token can be observed on an untrusted network.
|
|
202
|
+
|
|
203
|
+
## Android app
|
|
204
|
+
|
|
205
|
+
Open the `android/` directory in Android Studio.
|
|
206
|
+
|
|
207
|
+
For an emulator, the default server URL is:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
http://10.0.2.2:8765
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For a physical phone, start the server with `--host 0.0.0.0`, put the phone on the same network, then set the app server URL to:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
http://<linux-machine-ip>:8765
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If the server was started with `--token`, enter the same token in the app's Token field.
|
|
220
|
+
|
|
221
|
+
Tap Save to lock the Server and Token fields. Tap Unlock before editing them again.
|
|
222
|
+
|
|
223
|
+
Tap Delete on a run in the history list to delete it from the server.
|
|
224
|
+
|
|
225
|
+
Tap a run, or tap Console, to open the run's terminal output. Use Back to return to the main list.
|
|
226
|
+
|
|
227
|
+
## App updates
|
|
228
|
+
|
|
229
|
+
Sideloaded APKs cannot discover updates by themselves unless the app can read a public version file.
|
|
230
|
+
GitHub is not required. For mainland China, prefer a mirror such as Gitee, Aliyun OSS, Tencent COS, Qiniu, or Upyun, and keep GitHub as a fallback.
|
|
231
|
+
|
|
232
|
+
This app defaults to checking these sources in order:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
https://gitee.com/hushuguo/reminder/raw/main/update.json
|
|
236
|
+
https://raw.githubusercontent.com/hushuguo/Reminder/main/update.json
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Create a public JSON file like `update.json`:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"android": {
|
|
244
|
+
"versionCode": 34,
|
|
245
|
+
"versionName": "0.6.23",
|
|
246
|
+
"apkUrl": "http://106.14.246.204/downloads/Haoleme-0.6.38.apk",
|
|
247
|
+
"apkUrls": [
|
|
248
|
+
"http://106.14.246.204/downloads/Haoleme-0.6.38.apk"
|
|
249
|
+
],
|
|
250
|
+
"notes": "Keeps deleted run records consistent between All, device views, filters, and cached details."
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The update URLs are built into the app and are not shown to users. On startup, the app checks for updates in the background.
|
|
256
|
+
If `versionCode` is higher than the installed APK, the app shows an update label with the new version in the top-right corner. Tap it to download the APK in-app with progress shown in the status area. If download or installation fails, the installed version is left untouched.
|
|
257
|
+
|
|
258
|
+
This prototype polls every 5 seconds while the app process is alive. A later version should move polling into a foreground service or push channel if you want reliable notifications while the app is fully backgrounded.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "haoleme"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Run commands with Haoleme monitoring and expose their status to the mobile app."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [{ name = "Haoleme" }]
|
|
12
|
+
dependencies = ["cryptography>=42", "qrcode>=7.4"]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
hao = "haoleme.cli:main"
|
|
16
|
+
haoleme-cloud = "haoleme.cloud_server:main"
|
|
17
|
+
|
|
18
|
+
[tool.setuptools.packages.find]
|
|
19
|
+
where = ["src"]
|
haoleme-0.1.0/setup.cfg
ADDED