openclaw sessions: Manage and List Stored Conversation Sessions

Reference for listing, archiving, deleting, and maintaining stored sessions via the openclaw CLI. Useful for operators who need to inspect or clean up persisted conversation rows across agents.

Read this when

  • You want to list stored sessions and see recent activity
  • You want to archive or delete sessions from a headless Gateway

openclaw sessions

Show all saved conversation sessions.

A session listing is not the same as a channel or provider health check. It reflects conversation rows that have been persisted by session stores. A Discord, Slack, Telegram, or other channel that has been quiet can reconnect without generating a new session row until a message arrives. For live channel status, turn to openclaw channels status --probe, openclaw status --deep, or openclaw health --verbose.

openclaw sessions
openclaw sessions --agent work
openclaw sessions --all-agents
openclaw sessions --active 120
openclaw sessions --limit 25
openclaw sessions --store ./tmp/sessions.json
openclaw sessions --json

Flags:

FlagDescription
--agent <id>A single configured agent store (mandatory when multiple explicit agents are used).
--all-agentsCombine every configured agent store into one view.
--store <path>Older store selector path (incompatible with --agent or --all-agents).
--active <minutes>Restrict the listing to sessions touched in the last N minutes.
--limit <n|all>Row limit for output (defaults to 100; all removes the cap).
--jsonEmit output for machines.
--verboseTurn on verbose logging.

The documented legacy selector format is accepted by --store, which includes sessions.json and custom selectors without a suffix. OpenClaw maps that selector to its concrete SQLite location, checks that the location exists and is functional, and then reports the actual physical path it read from.

By default, openclaw sessions and the Gateway sessions.list RPC have a cap in place, so large, long-lived stores cannot tie up the CLI process or the Gateway event loop. The newest 100 sessions are returned by the CLI unless you pass --limit <n> to adjust the window up or down, or --limit all when you truly need the entire store. JSON responses carry totalCount, limitApplied, and hasMore so callers can indicate that additional rows are available.

For RPC clients, configuredAgentsOnly: true keeps the wide combined discovery source while limiting results to rows whose agents are present in the current config. That mode is the default for the Control UI, which prevents deleted or disk-only agent stores from showing up again in the Sessions view.

Configured agent stores are read by --all-agents. Gateway and ACP session discovery cast a wider net: they also pick up SQLite stores resolved from configured agent roots or a templated session.store root. Legacy selector paths must stay inside the agent root; symlinks and paths outside that root are ignored.

openclaw sessions --all-agents --json:

{
  "path": null,
  "stores": [
    { "agentId": "main", "path": "/home/user/.openclaw/agents/main/agent/openclaw-agent.sqlite" },
    { "agentId": "work", "path": "/home/user/.openclaw/agents/work/agent/openclaw-agent.sqlite" }
  ],
  "allAgents": true,
  "count": 2,
  "totalCount": 2,
  "limitApplied": 100,
  "hasMore": false,
  "activeMinutes": null,
  "sessions": [
    { "agentId": "main", "key": "agent:main:main", "model": "openai/gpt-5.6-sol" },
    { "agentId": "work", "key": "agent:work:main", "model": "anthropic/claude-sonnet-4-6" }
  ]
}

Archive sessions

Archive sessions through the active Gateway:

openclaw sessions archive "agent:main:scratch-1"
openclaw sessions archive "agent:main:scratch-1" "agent:main:scratch-2"
openclaw sessions archive "agent:work:scratch-1" --agent work
openclaw sessions archive "agent:main:scratch-1" --dry-run
openclaw sessions archive "agent:main:scratch-1" --json

The same sessions.patch lifecycle operation used by the Control UI powers archiving. The transcript is kept, the session is flagged as archived, and it drops out of the default active list. For a cloud-worker session with an active placement, the Gateway stops the worker first, reconciles its workspace, and reclaims the environment. If the placement is still in transition or has failed without proof that its environment is gone, the session stays unarchived; let the placement finish settling and then try again. Agent main sessions stay protected. Archiving an already archived session succeeds without doing anything. Run --dry-run to check every key and see the outcome in advance without altering session state.

Delete sessions

Delete sessions through the active Gateway:

openclaw sessions delete "agent:main:scratch-1"
openclaw sessions delete "agent:main:scratch-1" "agent:main:scratch-2" --yes
openclaw sessions delete "agent:work:scratch-1" --agent work --yes
openclaw sessions delete "agent:main:scratch-1" --dry-run
openclaw sessions delete "agent:main:scratch-1" --yes --json

Warning

Deleting is destructive. In an interactive terminal, one confirmation prompt appears before the valid keys are removed. For non-interactive and --json deletion, --yes is mandatory. When scripting a bulk cleanup, run --dry-run first.

The same sessions.delete lifecycle operation as the Control UI is used for deletion, with transcript cleanup switched on. The Gateway removes the live session row, transcript generations, session-owned runtime state, bindings, boards, and other lifecycle artifacts. Ordinary sessions keep their transcript as a verified .jsonl.deleted.<timestamp> archive; incognito transcripts are wiped with no archive left behind. If a managed worktree cannot be removed safely, the command reports the preserved branch and path so cleanup can happen manually.

Both lifecycle commands:

  • handle multiple keys and return one ordered result for each key;
  • rely on --agent <id> to pick the owning agent, which is required for a global key that belongs to a non-default agent;
  • accept --url, --token, --password, and --timeout <ms> Gateway connection overrides;
  • exit non-zero when any key is unknown or any operation fails, while still processing the other valid keys;
  • produce one stable JSON envelope with ok, operation, dryRun, and results when --json is enabled.

Example JSON with mixed results:

{
  "ok": false,
  "operation": "archive",
  "dryRun": false,
  "results": [
    { "key": "agent:main:scratch-1", "ok": true, "status": "archived" },
    {
      "key": "agent:main:missing",
      "ok": false,
      "status": "not_found",
      "error": "Session not found. Run openclaw sessions list --json to choose a valid key."
    }
  ]
}

Tail trajectory progress

openclaw sessions tail
openclaw sessions tail --follow
openclaw sessions tail --session-key "agent:main:telegram:direct:123" --tail 25
openclaw sessions --agent work tail --follow
openclaw sessions --all-agents tail --follow

openclaw sessions tail displays recent runtime trajectory events as condensed progress lines. When --session-key is absent, it first follows active sessions, then the most recently stored one. The number of existing events shown before follow mode begins is governed by --tail <count>; the default is 80, while 0 begins at the current end. Watching continues on the chosen SQLite-backed session or an explicit legacy trajectory file via --follow.

The progress view keeps things minimal on purpose: prompt text, tool arguments, and tool result bodies stay hidden. Tool invocations appear with the tool name using {...redacted...}; results show statuses like ok, error, or done; model completion lines display provider/model and terminal status.

Export a trajectory bundle

openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:123" --workspace .
openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:123" --output bug-123 --json

This command path is what the /export-trajectory slash command triggers after the owner gives approval for the exec request. The output directory always resolves within .openclaw/trajectory-exports/ under the selected workspace.

Cleanup maintenance

Trigger maintenance immediately rather than waiting for the next write cycle:

openclaw sessions cleanup --dry-run
openclaw sessions cleanup --agent work --dry-run
openclaw sessions cleanup --all-agents --dry-run
openclaw sessions cleanup --enforce
openclaw sessions cleanup --enforce --active-key "agent:main:telegram:direct:123"
openclaw sessions cleanup --dry-run --fix-dm-scope
openclaw sessions cleanup --json

openclaw sessions cleanup pulls session.maintenance settings from configuration (Configuration reference):

  • Scope note: session stores, transcripts, trajectory rows, and legacy trajectory sidecars are managed by openclaw sessions cleanup. Cron run history is not pruned. Task maintenance keeps terminal cron history for 7 days (lost rows for 24 hours) and caps at the newest 2000 rows per job and history class as an extra limit (Task maintenance, Cron configuration).
  • Cleanup also removes unreferenced legacy/archive transcript artifacts, compaction checkpoints, and trajectory sidecars older than session.maintenance.pruneAfter; artifacts still referenced by SQLite session rows stay intact.
  • Short-lived Gateway model-run probe cleanup is reported separately as modelRunPruned. This matches only strict explicit keys shaped like agent:*:explicit:model-run-<uuid>. Retention is a fixed 24h and is pressure-gated: stale probe rows are removed only when session-entry maintenance/cap pressure is hit. When triggered, model-run cleanup precedes global stale cleanup and capping.
  • The total live session row count is capped by maxEntries. Protected rows are reported as keep and count toward the cap, but they are never auto-evicted. If protected rows block reaching the cap, the store stays above it. --enforce does not lift that protection; unarchive, unpin, wait for active work to finish, or explicitly delete sessions you no longer need.

Flags:

FlagDescription
--dry-runSee how many entries would be pruned/capped without writing. In text mode, a per-session action table (Action, Key, Age, Model, Flags) plus a summary grouped by session label is printed.
--enforceRun maintenance even when session.maintenance.mode is warn.
--fix-missingDrop legacy entries with missing or header-only/empty archived transcript artifacts, even if they would not normally age/count out yet.
--fix-dm-scopeWhen session.dmScope is main, retire stale peer-keyed direct-DM rows left behind by earlier per-peer, per-channel-peer, or per-account-channel-peer routing. Use --dry-run first; applying removes those rows from SQLite and keeps their legacy transcript artifacts as deleted archives.
--active-key <key>Shield a specific active key from automatic maintenance. It still counts toward maxEntries. Durable external conversation pointers, such as group sessions and thread-scoped chat sessions, are also retained by age/count/disk-budget maintenance.
--agent <id>Clean up one configured agent store.
--all-agentsClean up all configured agent stores.
--store <path>Target a specific legacy store selector path.
--jsonOutput a JSON summary. With --all-agents, the output includes one summary per store.

When a Gateway is reachable, non-dry-run cleanup for configured agent stores goes through the Gateway so it shares the same session-store writer as runtime traffic. For explicit offline repair of a legacy store selector, use --store <path>.

Offline cleanup loads trusted, permitted harness plugins so their session-owned resources are reclaimed with the deleted rows, even if the agent now uses a different model. Explicitly disabled or untrusted plugins are skipped. If their resources may remain, cleanup prints a warning on stderr without altering the JSON result. Dry runs do not load harness plugins.

openclaw sessions cleanup --all-agents --dry-run --json:

{
  "allAgents": true,
  "mode": "warn",
  "dryRun": true,
  "stores": [
    {
      "agentId": "main",
      "storePath": "/home/user/.openclaw/agents/main/sessions/sessions.json",
      "beforeCount": 120,
      "afterCount": 80,
      "missing": 0,
      "dmScopeRetired": 0,
      "pruned": 40,
      "capped": 0
    },
    {
      "agentId": "work",
      "storePath": "/home/user/.openclaw/agents/work/sessions/sessions.json",
      "beforeCount": 18,
      "afterCount": 18,
      "missing": 0,
      "dmScopeRetired": 0,
      "pruned": 0,
      "capped": 0
    }
  ]
}

Compact a session

Free up context budget for a wedged or oversized session. openclaw sessions compact <key> is the primary wrapper around the sessions.compact Gateway RPC and needs a running Gateway.

openclaw sessions compact "agent:main:main"
openclaw sessions compact "agent:main:main" --max-lines 200
openclaw sessions compact "agent:work:main" --agent work --json
  • In the absence of --max-lines, the Gateway performs LLM-based summarization of the transcript. No client-side deadline is set by the CLI by default; the Gateway takes charge of the configured compaction lifecycle.
  • When --max-lines <n> is used, the SQLite transcript gets permanently cut down to the last n lines. No backup archive is generated along this route.
  • --agent <id>: the agent that owns the session; mandatory when global keys are involved.
  • --url / --token / --password: overrides for the Gateway connection.
  • --timeout <ms>: an optional RPC timeout on the client side, expressed in milliseconds.
  • --json: outputs the raw RPC payload.

A non-zero exit code is returned if the Gateway reports a failed compaction or cannot be reached, ensuring that crons and scripts never treat a silent no-op as a success.

Note

openclaw agent --message '/compact ...' does not qualify as a compaction path. The authorized-sender check rejects slash commands coming from the CLI; that call exits non-zero with instructions pointing here rather than quietly doing nothing.

sessions.compact RPC

openclaw gateway call sessions.compact --params '<json>' supports the following:

FieldTypeRequiredDescription
keystringyesSession key to compact (for example agent:main:main).
agentIdstringnoAgent id that owns the session (for global keys).
maxLinesinteger ≥ 1noTruncate to the last N lines instead of LLM summarization.

Sample response from LLM summarization:

{
  "ok": true,
  "key": "agent:main:main",
  "compacted": true,
  "result": { "tokensBefore": 243868, "tokensAfter": 34941 }
}

Sample response from truncation (--max-lines 200):

{
  "ok": true,
  "key": "agent:main:main",
  "compacted": true,
  "kept": 200
}
2,071 words · updated Aug 28, 2026