OpenClaw Sessions CLI Guide: archive, delete, compact --max-lines, cleanup, and the tail Output You Shouldn't Paste
Archive is the verb you want. Delete almost never is.
The pages that rank for openclaw sessions are the official CLI reference, the store maintenance page in the same docs (both long, both accurate), and a course lesson of about 1,200 words on pruning and retention that never mentions delete, compact, or tail. All three explain what cleanup does to old rows. None of them ranks the commands by how much they destroy, and one of them quietly prints tool arguments with no secret masking, which matters the minute someone pastes its output into a GitHub issue. This guide is ordered by blast radius, smallest first.
The list stops at 100 rows
Plain openclaw sessions shows persisted conversation rows, newest first, and returns the newest 100 by default. It is a view of storage. A healthy channel can have no row at all until someone talks to it, which the channels CLI guide covers from the other side.
openclaw sessions --active 60
openclaw sessions --all-agents --limit all --json
openclaw sessions --agent main --limit 20 --jsonThe 100-row cap bites scripts. If you count rows in --json output to decide whether cleanup is due, you will never see more than 100 and the check will lie to you forever. Read totalCount instead, and check hasMore and limitApplied before trusting anything else in the array. --store points at a specific store (a legacy sessions.json selector or a custom SQLite target) and can't be combined with --all-agents.
tail is read-only, and still dangerous
openclaw sessions tail renders recent runtime trajectory events as one-line progress. Without --session-key it asks the Gateway which sessions are running and tails those first, falling back to the most recently active stored session. It prints the last 80 events, then stops unless you pass --follow; --tail 0 starts at the current end.
Prompt text and tool result bodies are left out. Tool calls are not. Each one shows the tool name and its serialized arguments, unmasked, so an exec call that took a token on the command line puts that token on your screen. I treat tail output like a raw log file: fine in my terminal, never in a screenshot.
One scripting note. A key that matches nothing exits non-zero, but no key and no sessions prints No sessions found. and exits 0, even with --follow.
archive first
openclaw sessions archive "agent:main:scratch-1" --dry-run
openclaw sessions archive "agent:main:scratch-1" "agent:main:scratch-2"Archive goes through the same sessions.patch lifecycle operation the Control UI uses. The transcript stays, the row is marked archived, and it disappears from the default active list. --dry-run validates every key before anything changes, which catches the typo in key number seven of a twelve-key batch. It needs a running Gateway. For a cloud-worker session with an active placement, the Gateway also stops the worker and reclaims its environment, so archiving something mid-run is a real interruption.
Archived rows also stop counting toward the maxEntries cap, which is the main reason to archive at all.
compact has one flag you cannot take back
openclaw sessions compact <key> wraps the sessions.compact Gateway RPC and is for a session that has eaten its context window. Without flags, the Gateway LLM-summarizes the transcript. With --max-lines <n>, it permanently truncates the SQLite transcript to the last n lines.
Permanently. That is the documented word, and no other flag on this page gets it. Even delete leaves an archive behind for an ordinary session. If a session is wedged and you are tempted, export it first (below), then truncate. The context budget guide explains why a session gets wedged in the first place.
delete keeps a copy, unless the session was incognito
openclaw sessions delete "agent:main:scratch-1" --dry-run
openclaw sessions delete "agent:main:scratch-1" --yes --jsonDelete runs through the Gateway and removes the live row, transcript generations, session-owned runtime state, bindings, boards, and other lifecycle artifacts. For ordinary sessions the transcript survives as a verified .jsonl.deleted.<timestamp> archive. Incognito transcripts are removed with no archive at all. An interactive terminal asks for confirmation; non-interactive runs and anything with --json refuse without --yes.
That leftover archive is also why delete is a poor privacy tool. If you are trying to make a conversation actually go away, the memory CLI guide walks through the other places its contents can live.
cleanup defaults to enforce
This surprises people. session.maintenance.mode defaults to "enforce", and ordinary writes already arm a background maintenance pass, with a 30-minute recheck while the database connection stays open. Cleanup is happening whether you run the command or not. The defaults:
pruneAfter: "30d"
Eligible durable sessions past this age are archived in place, IDs and transcript generations kept, and reported as archive-age.
maxEntries: 5000
Caps unarchived rows. Eligible overflow is archived as archive-cap. Protected rows still count, so a store full of pinned sessions can sit above the cap indefinitely.
maxDiskBytes: "10gb"
Per agent, with highWaterBytes at 80% of that as the post-cleanup target. Set either to false or 0 to turn the budget off.
Protected sessions include pinned ones, anything with active or admitted work, model-locked sessions, group and thread-scoped conversations, and sessions referenced by checkpoints. Cron, hook, heartbeat, ACP, and sub-agent sessions are the disposable ones. On a busy cron box they pile up fastest, which is fine, and if you rely on reading old cron runs, the cron automation guide is where to capture what you need before 30 days pass.
openclaw sessions cleanup --dry-run --agent main
openclaw sessions cleanup --enforce --agent main --jsonThe dry run prints an action table (Action, Key, Age, Model, Flags) and a summary grouped by session label. JSON reports carry beforeCount, afterCount, pruned, capped, and missing. --enforce only matters if you switched mode to "warn", which reports overage without writing an archive or deleting a single row. --active-key <key> shields one session from the pass.
Offline cleanup against an explicit --store wants exclusive ownership. If a Gateway or another live process holds the state, the command names that owner and refuses. Stop it, run cleanup, start it again. For how resets feed this pile, see the session reset guide.
Getting transcripts in and out
sessions export-trajectory --session-key <key> writes a bundle that always lands inside .openclaw/trajectory-exports/ under the selected workspace, whatever you pass to --output. It is the same path the /export-trajectory slash command uses after the owner approves the exec request. Keys without an agent prefix, like global, go to the default agent, so pass --agent on a multi-agent install with no default set.
sessions import claude <thread-id> (or codex) pulls a transcript from another tool. The copy starts as a draft, visible only to you and Gateway admins, until you publish it through the session sharing controls. Re-importing the same thread appends only new items. One import reads up to 50,000 items and 64 MiB, so a very long Codex thread may need more than one pass.
Final verdict
Read totalCount, never the array length. Archive by default. Delete is for the rare session that genuinely has to stop existing in the Gateway, and I would not run --max-lines without an export sitting next to it. Leave cleanup on enforce; the 30-day and 5,000-row defaults are sane for a single operator, and the protected list already covers the sessions you would be upset to lose. And keep tail output out of Slack.
Ready to build?
Get the OpenClaw Starter Kit — config templates, 5 production-ready skills, deployment checklist. Go from zero to running in under an hour.
$14 $6.99
Get the Starter Kit →Also in the OpenClaw store
Get the free OpenClaw quickstart guide
Step-by-step setup. Plain English. No jargon.