Session Janitor
by @halfdeadcat
Automated transcript trimming, LLM memory extraction, and session hygiene for OpenClaw gateways. Keeps transcripts from bloating, extracts structured memorie...
Edit config.json after setup to tune thresholds:
| Key | Default | Description |
|-----|---------|-------------|
| trimMaxKB | 250 | Trim transcripts larger than this. Trim always fires when exceeded β there is no minimum pair count. |
| keepPairs | 10 | Number of recent user/assistant pairs to keep after trim. If fewer pairs exist than this, all are kept (no skip). |
| keepFullPairs | 2 | Most recent N assistant turns that keep full toolResult bodies (older turns are collapsed to summary lines) |
| minArchivePairs | 5 | Informational only β no longer blocks trim. Sessions exceeding trimMaxKB are always trimmed. |
| trimFullThresholdPct | 50 | Two-stage aggressive reduction when trimmed output still exceeds this % of trimMaxKB: (1) strip all assistant turns (tool args + thinking removed); (2) if still over threshold, drop all toolResult entries entirely. Set to 100 to disable. |
| archiveRetentionDays | 7 | Delete old archives after this many days (applies to .reset.*, .deleted.*, .pre-trim.*, .bak-*, .purged.*, .emergency-*) |
| keepPreTrimFiles | 3 | Max .pre-trim.* files to keep per session (oldest deleted immediately, regardless of retention period) |
| orphanGraceMinutes | 30 | Wait before archiving orphan transcripts |
| staleSubagentHours | 24 | Prune subagent session entries older than this |
| staleCronSessionHours | 24 | Prune cron session entries older than this |
| llmExtraction.enabled | true | Use LLM to extract memories from trimmed content |
| llmExtraction.model | openclaw | Model identifier to use for extraction calls |
| llmExtraction.maxInputChars | 20000 | Max characters of archived content sent to LLM |
| llmExtraction.timeoutSecs | 60 | LLM API call timeout in seconds |
| llmExtraction.maxMemories | 15 | Max memories to accept from a single LLM extraction |
| llmExtraction.minArchived | 3 | Minimum archived messages required before running LLM extraction |
| llmExtraction.maxPerRun | 1 | Max LLM extractions per cron cycle (cost control) |
| memCli.enabled | false | Store extracted memories via mem CLI (requires mem) |
| cronSchedule | */15 * * * * | How often to run |
| sidecar.enabled | true | Offload large toolResult entries to .toolcache/ files |
| sidecar.minEntryBytes | 5120 | Minimum toolResult content size (bytes) to trigger offload |
| extractOnTrim.enabled | false | Fire async LLM memory extraction after each watcher-triggered trim |
| extractOnTrim.minArchivedPairs | 3 | Minimum archived message pairs required before running extraction |
| extractOnTrim.scene | auto | Memory scene tag to use (auto lets the LLM infer from context) |
| extractOnTrim.salience | 0.5 | Default salience for extracted memories (0.1β1.0) |
| watchdog.enabled | false | Run hung-session detector after each janitor pass |
| watchdog.staleMinutes | 5 | Session updatedAt age threshold to consider stuck |
| watchdog.alertSlack | true | Send Slack DM when a stuck session is detected |
| watchdog.slackTarget | β | Slack user ID or channel to notify |
| watchdog.autoRestart | false | Auto-trigger safe-restart script on detection (use with caution) |
| watchdog.restartScriptSlack | ~/bin/safe-slack-restart.sh | Safe restart script path for Slack gateway |
| watchdog.restartScriptDiscord | ~/bin/safe-gateway-restart.sh | Safe restart script path for Discord gateway |
clawhub install session-janitor