1# tools 2 3| Script | What | 4|---|---| 5| `make-cat.py` | Writes the ginger cat's twelve SVGs from the SVG set it is given. | 6| `make-sounds.py` | Synthesises the poke and dizzy sound effects as WAV files. | 7| `install-android.sh` | Installs the debug APK on a connected device; configured by environment variables, see its header. | 8| `release-apks.sh` | Builds the three release APKs of one calendar version into `~/whiskers-release/<version>/` (see its header). | 9| `run-whiskersd.sh`, `preflight.sh` | Start the service and check everything the app talks to; both take their addresses from the environment or an argument. | 10| `android-sdk.sh`, `android-gradle.sh` | Install the SDK packages at the levels in `mise.toml`; run Gradle in `android/` with the optional `-Pwhiskers.*` taken from `WHISKERS_*` variables. Neither assumes mise or nix: they read `ANDROID_HOME` and `ANDROID_NDK_HOME` and say what is missing. | 11| `with-secrets.sh` | Runs a command under `fnox exec` when fnox is set up, plainly otherwise. | 12| `check-versions.sh` | Fails when a version written outside `mise.toml` (the wasm-bindgen pins, the Gradle build's SDK levels, hk.pkl) differs from it. | 13| `check-private.sh` | Fails if a term from your gitignored `.private-terms` appears in a tracked file. `--message FILE` checks a commit message; `--push` checks every commit that is on no remote yet (files, names, messages), because the whole history is public. | 14| `build-core.sh` | Builds the Rust core for both Android ABIs, generates the Kotlin bindings and writes the grey cat's drawing (`gen-kotlin`); Gradle runs it before every build. | 15 16## Keeping the repository free of private details 17 18Copy nothing personal into a tracked file. To make that checkable, put the terms that must never 19appear (a child's or family member's name, a hostname, an IP address, a device serial, a user 20name, a personal path) one per line in `.private-terms` at the repository root. That file is 21gitignored and must stay out of git: the terms are exactly what the repository must not contain. 22`tools/check-private.sh` greps every tracked file for them (case-insensitive, fixed strings; blank 23lines and `#` comments are ignored) and prints `file:line` for each hit, exiting non-zero. Without 24the file it says so and passes, because there is nothing to check against; `WHISKERS_REQUIRE_PRIVATE_TERMS=1` 25makes a missing file an error. `tools/preflight.sh` runs it, and so does a Rust test 26(`whiskers-core`'s `tests/private_terms.rs`), so `cargo test` catches a regression. It skips the vendored `third-party/pixel-icons` and the icon allowlist, which have to name upstream's icons (a short term matches inside ordinary words there). 27 28## Running them 29 30Every script has a mise task; `mise tasks` lists them, `mise run <task>` runs one, and `mise run <task> -- <arguments>` passes arguments on. The scripts themselves take everything from the environment and work in any shell that has the tools of `mise.toml` on PATH, so they also work inside `nix develop` or a toolchain you installed yourself. 31 32| Task | Script or command | 33|---|---| 34| `core` | `build-core.sh` | 35| `android:debug`, `android:lite`, `android:test`, `android:record-goldens`, `android:verify-goldens` | `android-gradle.sh` with the Gradle task | 36| `android:install`, `android:inspect`, `android:fetch-voices`, `release:apks` | `install-android.sh`, `inspect-apk.sh`, the two `fetch-*.sh`, `release-apks.sh` | 37| `android:sdk` | `android-sdk.sh` | 38| `whiskersd`, `whiskersd:service`, `preflight` | `cargo run`, `run-whiskersd.sh`, `preflight.sh` | 39| `check`, `check-private`, `check-versions`, `check-wasm`, `clippy`, `test` | the fast gates | 40| `dev` | the dev daemons (whiskersd and the website) | 41 42## Git hooks (hk) 43 44`mise run hooks:install` installs the hooks in `hk.pkl`: before a commit `check-private.sh` and `cargo clippy` (warnings are shown, an error-level lint stops it), on the commit message `check-private.sh --message`, before a push `check-private.sh --push` (every unpushed commit, not just the tip) and the website's tests. The tree is not formatted by rustfmt, so formatting is not checked. 45 46## Dev daemons (pitchfork, through mise) 47 48`[daemons]` in `mise.toml` declares whiskersd and the website's `wrangler dev`; mise starts them under pitchfork. `mise run dev` starts both and waits until they answer; `mise daemons status`, `mise daemons logs` and `mise daemons stop` manage them. whiskersd listens on `WHISKERS_ADDR` (default `127.0.0.1:47900`) and needs `WHISKERS_MODEL_URL`. 49 50## Secrets (fnox, optional) 51 52`fnox.toml` declares `TYPESAFE_API_KEY`, `ELEVENLABS_API_KEY`, `ELEVENLABS_VOICE_ID` and `WHISKERS_MODEL_URL` with no value and no provider. Without fnox, export them in the environment before `mise run whiskersd`. To use fnox, put a provider of your own, and the secrets it should resolve, in `fnox.local.toml` (gitignored; a secret defined there replaces the declaration in `fnox.toml`) or in `~/.config/fnox/config.toml`. With 1Password the values stay in the vault and the file holds references: 53 54 [providers.op] 55 type = "1password" 56 vault = "<your vault>" 57 58 [secrets.TYPESAFE_API_KEY] 59 provider = "op" 60 value = "<item>/<field>" 61 62With age the values are stored encrypted for your public key (`age-keygen` makes the pair): 63 64 [providers.age] 65 type = "age" 66 recipients = ["age1..."] 67 68 # then: fnox set TYPESAFE_API_KEY --provider age 69 70`tools/with-secrets.sh` runs the task's command under `fnox exec` when `fnox check` passes, and plainly otherwise (set `WHISKERS_NO_FNOX=1` to force plain). The provider fields are at https://fnox.jdx.dev. 71 72## With nix (optional) 73 74`nix develop` gives a shell with mise and the native tools a downloaded toolchain needs (compiler, pkg-config, OpenSSL, curl, unzip, bzip2); it puts what `mise install` has installed on PATH. The shells `web`, `backend`, `android` and `android-emu` are the same shell. Downloaded programs (the NDK, build tools) are ordinary dynamically linked binaries: NixOS with nix-ld runs them as they are; without nix-ld use `nix develop .#fhs`. The flake also builds the service (`packages.whiskersd`, `whiskersd-static`) and `celld`; it holds no tool version.