Metadata-Version: 2.4
Name: remindrun
Version: 0.8.4
Summary: Run commands with Reminder monitoring and expose their status to the Android app.
Author: Reminder
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: qrcode>=7.4

# Reminder

Reminder is a minimal prototype for monitoring Linux command runs from an Android app.

The first version has two parts:

- `remindrun`: a Python command wrapper. Put `remindrun` before a command to record its status, output tail, exit code, and timestamps.
- Android app: a small native app that polls the `remindrun` HTTP API, lists runs, and posts a local notification when a run changes from running to finished.

## Python monitor

Install the local package in a virtual environment:

```bash
python3 -m venv .venv
.venv/bin/python -m pip install -e .
```

Or install the built wheel:

```bash
.venv/bin/python -m pip install dist/remindrun-0.8.1-py3-none-any.whl
```

Start the status server on the Linux machine:

```bash
remindrun server --host 0.0.0.0 --port 8765 --token change-this-token
```

Run commands through Reminder:

```bash
remindrun sleep 5
remindrun run -- bash -lc 'echo hello && sleep 2 && echo done'
remindrun status
```

You can use the shorter `rrun` command for the same actions:

```bash
rrun sleep 5
rrun ngrok --domain <YOUR_DEV_DOMAIN>.ngrok-free.dev
```

## Cloud sync

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 Reminder Cloud, and the Android app reads the same account from the cloud API.

After deploying the Cloudflare Worker in `cloudflare/`, log in once on each new machine:

```bash
pip install -U remindrun
rrun login
```

The command prints a QR code and a 6-digit pair code:

```text
847-291
```

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 Reminder and pair automatically. If QR scanning is unavailable, enter the 6-digit code in Pair code, then tap Pair. After pairing, normal commands sync automatically:

```bash
rrun run -- python train.py
rrun run -- sh -c 'for i in $(seq 1 10); do echo tick $i; sleep 1; done'
```

Useful cloud commands:

```bash
rrun cloud-status
rrun cloud-logout
```

Advanced/manual login is still available:

```bash
rrun cloud-login --api-url https://your-reminder-cloud.workers.dev --account ethan --token <TOKEN>
```

Cloud sync uses the app's account token as the account key. Anyone with that token can see and delete that account's run history, so treat it like a password.

### Deploy Reminder Cloud

The included Cloudflare Worker is a small relay service. It stores only command metadata and output tails.

```bash
cd cloudflare
npm create cloudflare@latest
npx wrangler kv namespace create RUNS
```

Copy the returned KV namespace id into `cloudflare/wrangler.toml`, then deploy:

```bash
npx wrangler deploy
```

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.

The server exposes:

- `GET /health`
- `GET /api/runs?limit=50`
- `GET /api/runs/{id}`
- `GET /api/events?since=<updatedAt>`

By default the SQLite database lives at `~/.reminder/reminder.db`. Set `REMINDER_HOME=/path/to/dir` to change that location.

## Direct public access

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:

```bash
remindrun public
```

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. Enter both in the Android app:

```text
Server: https://example.trycloudflare.com
Token:  generated-token
```

If `cloudflared` is missing, install it first:

```bash
brew install cloudflared
```

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:

```bash
brew install ngrok/ngrok/ngrok
ngrok config add-authtoken <YOUR_NGROK_AUTHTOKEN>
remindrun ngrok --domain <YOUR_DEV_DOMAIN>.ngrok-free.dev
```

In the Android app:

```text
Server: https://<YOUR_DEV_DOMAIN>.ngrok-free.dev
Token:  generated-token
```

If the Android app needs to connect to a server that already has a public IP or a public domain:

```bash
remindrun server --host 0.0.0.0 --port 8765 --token a-long-random-token
```

Then open TCP port `8765` in the cloud security group or firewall.

In the Android app:

```text
Server: http://<public-ip>:8765
Token:  a-long-random-token
```

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.

## Android app

Open the `android/` directory in Android Studio.

For an emulator, the default server URL is:

```text
http://10.0.2.2:8765
```

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:

```text
http://<linux-machine-ip>:8765
```

If the server was started with `--token`, enter the same token in the app's Token field.

Tap Save to lock the Server and Token fields. Tap Unlock before editing them again.

Tap Delete on a run in the history list to delete it from the server.

Tap a run, or tap Console, to open the run's terminal output. Use Back to return to the main list.

## App updates

Sideloaded APKs cannot discover updates by themselves unless the app can read a public version file.
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.

This app defaults to checking these sources in order:

```text
https://gitee.com/hushuguo/reminder/raw/main/update.json
https://raw.githubusercontent.com/hushuguo/Reminder/main/update.json
```

Create a public JSON file like `update.json`:

```json
{
  "android": {
    "versionCode": 18,
    "versionName": "0.6.7",
    "apkUrl": "https://github.com/hushuguo/Reminder/releases/download/android-v0.6.7/Reminder.apk",
    "apkUrls": [
      "https://gitee.com/hushuguo/reminder/raw/main/releases/android-v0.6.7/Reminder.apk",
      "https://github.com/hushuguo/Reminder/releases/download/android-v0.6.7/Reminder.apk"
    ],
    "notes": "Fixes terminal QR proportions and camera preview stretching."
  }
}
```

The update URLs are built into the app and are not shown to users. On startup, the app checks for updates in the background.
If `versionCode` is higher than the installed APK, the app shows an Update button in the top-right corner. Installing the downloaded APK updates the existing app in place as long as the package name and signing key are unchanged.

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.
