toknmtr — self-hostable Claude Code usage & analytics dashboard
Server (SvelteKit + SQLite Docker container) + per-machine agent that parses Claude Code JSONL transcripts. docker-compose one-command deploy; raw transcript view + search gated behind SHOW_TRANSCRIPTS (hidden by default). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
71a60ab054
74 changed files with 15613 additions and 0 deletions
95
ops/install-cron.sh
Executable file
95
ops/install-cron.sh
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
#
|
||||
# ops/install-cron.sh — idempotently install a crontab entry that runs the toknmtr agent in
|
||||
# reconcile mode (`--once`) every ~10 minutes.
|
||||
#
|
||||
# Why this exists alongside the Stop hook (ops/install-hook.sh):
|
||||
# The hook is near-live but best-effort — it's deliberately fail-open (see
|
||||
# agent/hooks/toknmtr-capture.sh), so it silently no-ops if the project dir/config/node
|
||||
# binary is momentarily missing, and it never retries a failed push itself (a failed push
|
||||
# just leaves the file's cursor unmoved, see agent/run.ts). It also only fires on Claude
|
||||
# Code turns, so a transcript that's touched outside a tracked Stop event (or a session
|
||||
# whose final hook fire was the one that raced/failed) won't get its tail captured until
|
||||
# *something* sweeps again. This cron line is that backstop: a periodic, host-crontab-
|
||||
# driven sweep that's independent of any particular Claude Code session being open, so the
|
||||
# data self-heals even if every hook fire that session ever missed/failed.
|
||||
# Push is idempotent (PK = host+session_id+uuid, see CLAUDE.md), so overlapping
|
||||
# hook-triggered and cron-triggered sweeps are always safe to interleave.
|
||||
#
|
||||
# What this script does:
|
||||
# - Adds (or updates, if already present) a single crontab line running
|
||||
# `node --experimental-strip-types agent/run.ts --once` every 10 minutes, sourcing
|
||||
# ~/.toknmtr/env first for TOKNMTR_URL/TOKNMTR_TOKEN, with stdout/stderr appended to a
|
||||
# log file.
|
||||
# - Idempotent: matches by a unique marker comment, so re-running replaces (rather than
|
||||
# duplicating) the line — safe to re-run after changing TOKNMTR_PROJECT_DIR etc.
|
||||
# - Reversible: `ops/install-cron.sh --remove` deletes just the marked line; everything
|
||||
# else in the user's crontab is left untouched.
|
||||
#
|
||||
# Usage:
|
||||
# ops/install-cron.sh # install/update the cron line
|
||||
# ops/install-cron.sh --remove # remove just this cron line
|
||||
#
|
||||
# Override knobs (env, all optional):
|
||||
# TOKNMTR_PROJECT_DIR path to the toknmtr repo checkout (default: ~/claude/projects/toknmtr)
|
||||
# TOKNMTR_ENV_FILE path to the config file (default: ~/.toknmtr/env)
|
||||
# TOKNMTR_LOG_FILE cron sweep log path (default: ~/.toknmtr/cron.log)
|
||||
# TOKNMTR_CRON_SCHEDULE cron schedule expression (default: "*/10 * * * *")
|
||||
|
||||
PROJECT_DIR="${TOKNMTR_PROJECT_DIR:-$HOME/claude/projects/toknmtr}"
|
||||
CONFIG_FILE="${TOKNMTR_ENV_FILE:-$HOME/.toknmtr/env}"
|
||||
LOG_FILE="${TOKNMTR_LOG_FILE:-$HOME/.toknmtr/cron.log}"
|
||||
SCHEDULE="${TOKNMTR_CRON_SCHEDULE:-*/10 * * * *}"
|
||||
|
||||
MARKER="# toknmtr-cron-reconcile"
|
||||
CRON_CMD="cd \"$PROJECT_DIR\" && . \"$CONFIG_FILE\" && node --experimental-strip-types agent/run.ts --once >> \"$LOG_FILE\" 2>&1"
|
||||
CRON_LINE="$SCHEDULE bash -lc '$CRON_CMD' $MARKER"
|
||||
|
||||
current_crontab() {
|
||||
crontab -l 2>/dev/null || true
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "--remove" ]; then
|
||||
existing="$(current_crontab)"
|
||||
if ! printf '%s\n' "$existing" | grep -qF "$MARKER"; then
|
||||
echo "no toknmtr cron line found, nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
printf '%s\n' "$existing" | grep -vF "$MARKER" | crontab -
|
||||
echo "removed toknmtr reconcile cron line"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
command -v crontab >/dev/null 2>&1 || {
|
||||
echo "error: crontab is required (e.g. 'sudo apt install cron') and the cron daemon must be running" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -d "$PROJECT_DIR" ] || {
|
||||
echo "error: $PROJECT_DIR does not exist (set TOKNMTR_PROJECT_DIR?)" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f "$PROJECT_DIR/agent/run.ts" ] || {
|
||||
echo "error: $PROJECT_DIR/agent/run.ts not found — is TOKNMTR_PROJECT_DIR correct?" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
|
||||
# Replace any prior toknmtr line (matched by marker) with the new one; append if absent.
|
||||
existing="$(current_crontab)"
|
||||
filtered="$(printf '%s\n' "$existing" | grep -vF "$MARKER" || true)"
|
||||
{
|
||||
[ -n "$filtered" ] && printf '%s\n' "$filtered"
|
||||
printf '%s\n' "$CRON_LINE"
|
||||
} | crontab -
|
||||
|
||||
echo "installed toknmtr reconcile cron line (schedule: $SCHEDULE):"
|
||||
echo " $CRON_LINE"
|
||||
echo ""
|
||||
echo "config read from: $CONFIG_FILE (must exist with TOKNMTR_URL / TOKNMTR_TOKEN, see ops/README.md)"
|
||||
echo "sweep log: $LOG_FILE"
|
||||
echo ""
|
||||
echo "to remove later:"
|
||||
echo " ops/install-cron.sh --remove"
|
||||
echo " (or run 'crontab -e' and delete the line ending in '$MARKER')"
|
||||
Loading…
Add table
Add a link
Reference in a new issue