* feat(bash): native bash port of all z-scripts for Linux/macOS/WSL Full port: zhelpers.sh library (jq config, ssh, http/tcp, archive builder, build-version, motd, port-kill), all commands (zstart/zkill/zrestart/zstop, zdeploy with 5 kind handlers, zec2/zec2online/zrepair, zbackup/zbackup_ec2/ zsync/zbackup_and_sync, zstart_docker, zsetup_mail, setup_backup_schedule via cron), Unix-path zconfig.example.json, and a bash/README.md. Verified: bash -n clean on all scripts; archive exclusions, config semantics, and zec2 tested against the real config and live server from Git Bash. Needs a Linux/macOS/WSL shakedown for lsof/rsync/nohup paths before merging. * chore: pin line endings (.gitattributes) - bash LF, powershell CRLF * docs(readme): point Linux/macOS/WSL users at the bash port * fix(bash): don't run the Windows venv python.exe on WSL/Linux/macOS zstart's venv detection fell back to .venv/Scripts/python.exe (a Windows binary) whenever it existed. On a Windows-built project accessed from WSL that file sits on the mount and looks executable, so it got picked and failed with 'exec format error' instead of falling through to python3. Guard that branch to Windows-family shells (msys/cygwin), where a .exe can actually run. Verified on WSL: zstart --detached now backgrounds a stdlib app via python3, serves HTTP 200, logs to /tmp/zstart-<key>.log, and zkill terminates it and frees the port. * feat(bash): add token-usage tracking to the bash port (#6) Adds z_track_start/z_track_stop + z_record to zhelpers.sh and wires z_track_start into every command script. Each run now captures its own output volume (FIFO+tee, ANSI stripped), prints the '--- N lines / N chars / ~N tokens est. (Claude Code) ---' footer, and appends one JSONL row per top-level run in the same shape as the PowerShell tokens.jsonl. A nested-run guard keeps zrestart from double-counting its zkill/zstart children. Data dir precedence: $ZTOKENS_DATA, config ztokens.dataDir, sibling ../../ztokens/data, else ~/.ztokens/data. Docs + example config updated. Verified on WSL (isolated data dir): single run records correctly; nested zrestart produces one combined record, not three; est = round(chars/3.5).
3.5 KiB
Token Savers — bash port (Linux / macOS / WSL)
Native bash versions of the z-scripts. Same commands, same zconfig.json schema,
same behavior — no PowerShell required.
Requirements
- bash 4+,
jq,curl,zip, OpenSSH (ssh/scp) lsof(forzkill/zrestart),rsync(forzsync <project>mirror mode)- Docker + docker compose on the remote host for the deploy scripts
Debian/Ubuntu: sudo apt install jq curl zip lsof rsync
macOS: brew install jq (the rest ships with the OS)
Install
git clone https://github.com/kellymichels/zscripts-token-savers.git ~/zscripts
cd ~/zscripts/bash
cp zconfig.example.json zconfig.json # then fill in your values
chmod +x z* setup_backup_schedule
echo 'export PATH="$HOME/zscripts/bash:$PATH"' >> ~/.bashrc && source ~/.bashrc
Commands
Same set as the PowerShell versions — the project key in zconfig.json IS the
command argument:
| Command | What it does |
|---|---|
zstart <p> [--detached] |
start local dev server (python/vite/nextjs) |
zkill <p> |
free the project's dev port |
zrestart <p> [--detached] |
kill + start in one command |
zstop <p> |
stop the project's compose stack on the server |
zdeploy <p> [--note "msg"] |
zip → scp → docker compose build/up → verify build version |
zec2 [<p>] |
TCP + HTTP + live-version reachability check |
zec2online [<p>] |
deep health check; auto-starts downed stacks |
zrepair <p> |
audit/repair container + proxy routing, smoke test |
zbackup [<p>] [--tag t] |
local source zip (+ pg_dump when .env has DATABASE_URL) |
zbackup_ec2 [<p>] |
pull db dump + data dirs down from the server |
zsync |
copy new backup files offsite (never overwrites) |
zbackup_and_sync |
both of the above; cron-friendly |
setup_backup_schedule --install |
daily backup cron job |
zsetup_mail --domain d |
provision docker-mailserver mailboxes + print DNS records |
zstart_docker |
bring up the local compose stack in bash/docker/ |
Flags use GNU style (--port 3000, --detached) instead of PowerShell style
(-Port, -Detached). Detached dev servers log to /tmp/zstart-<project>.log.
Usage tracking
Every run prints a footer with its own output volume:
--- 1,048 lines / 69,009 chars / ~19,717 tokens est. (Claude Code) ---
and (when jq is available) appends one JSON line per run to tokens.jsonl,
so you can see how much infrastructure output you keep out of an AI agent's
context over time. Fields: ts, script, projects, lines, chars, est, model
(est ≈ chars / 3.5). Nested runs (the zkill/zstart inside zrestart)
are counted once, not double.
Where it's written, first match wins:
$ZTOKENS_DATAztokens.dataDirinzconfig.json- the sibling
../ztokens/datadirectory, if present ~/.ztokens/data(created on first run)
Set ZTOKENS_MODEL to tag records with a specific model; it defaults to
est. chars/3.5.
Differences from the PowerShell versions
zsync <viteproject>mirrorsdist/withrsync -a --delete(robocopy /MIR equivalent).- Scheduling uses cron (
setup_backup_schedule) instead of Windows Task Scheduler. - The MOTD banner picks a random
motd/*.txtinstead of tracking a shuffle rotation. - Windows-only helpers (
.cmdlaunchers) don't exist — scripts are directly executable.