Configuration

August 10, 2026 · View on GitHub

Lossless-claw reads plugin configuration from plugins.entries.lossless-claw.config.

Lossless Claw 0.x supports file-backed OpenClaw from 2026.5.28 through 2026.7.1. OpenClaw 2026.7.2 prereleases and later use SQLite-backed session storage and require Lossless Claw 1.0 from the next/1.0 release line. If you cannot move to 1.0, remain on OpenClaw 2026.7.1 or select OpenClaw's legacy context engine. The 2026.5.28 minimum lets the host enforce context-engine runtime capabilities before an agent run starts. Agent runs need a native host that provides the full context-engine lifecycle: session bootstrap, pre-prompt assembly, after-turn ingestion, maintenance, compaction, and runtime LLM completion. Native Codex and Pi embedded runs provide those capabilities; generic CLI harnesses such as claude-cli and codex-cli do not. If you must use a generic CLI harness, either set plugins.slots.contextEngine to legacy or explicitly set hostFallbackMode to capture-only. Capture-only mode lowers the installation-wide agent-run requirement to bootstrap, after-turn ingestion, and maintenance. Generic CLI runs can persist transcripts and use recall tools, but they do not receive Lossless prompt assembly or host-triggered Lossless compaction. Backend-native compaction remains host-owned. Explicit Lossless compaction requires fallbackProviders because generic CLI hosts do not provide runtime LLM completion. Fully capable native hosts still advertise and execute the full lifecycle, and Lossless retains compaction ownership for those runs. Subagent forks continue to require thread-bootstrap-projection.

The optional programmatic status / doctor / rotate control surface requires a host that separately advertises context-engine capabilities/control dispatch. That host contract is not covered by the baseline plugin API version above. As of this documentation update, no stable OpenClaw release includes those gateway endpoints; downstream control planes should probe host capabilities and treat control as unavailable until openclaw/openclaw#98060 or an equivalent stable host contract lands. The plugin's normal context-engine behavior and slash commands continue to work on the baseline supported OpenClaw versions.

Configuration precedence is:

  1. Environment variables
  2. plugins.entries.lossless-claw.config
  3. Built-in defaults from src/db/config.ts

Most installations only need to override a handful of keys. If you want a complete starting point, use the full example below and then delete entries you do not need.

Complete plugins.entries.lossless-claw.config example

{
  "enabled": true,
  "databasePath": "/Users/alice/.openclaw/lcm.db",
  "largeFilesDir": "/Users/alice/.openclaw/lcm-files",
  "ignoreSessionPatterns": [],
  "statelessSessionPatterns": [],
  "skipStatelessSessions": true,
  "hostFallbackMode": "error",
  "contextThreshold": 0.75,
  "contextThresholdOverrides": [
    {
      "name": "large-context-models",
      "match": { "modelContextWindowMin": 900000 },
      "contextThreshold": 0.15,
      "freshTailCount": 16,
      "leafChunkTokens": 12000
    },
    {
      "name": "small-context-models",
      "match": { "modelContextWindowMax": 250000 },
      "contextThreshold": 0.2
    },
    {
      "name": "telegram-sessions",
      "match": { "sessionPattern": "agent:*:telegram:**" },
      "contextThreshold": 0.3
    }
  ],
  "freshTailCount": 64,
  "freshTailMaxTokens": 24000,
  "promptAwareEviction": false,
  "stubLargeToolPayloads": false,
  "newSessionRetainDepth": 2,
  "leafMinFanout": 8,
  "condensedMinFanout": 4,
  "condensedMinFanoutHard": 2,
  "sweepMaxDepth": 1,
  "incrementalMaxDepth": 1,
  "leafChunkTokens": 20000,
  "summaryPrefixTargetTokens": 20000,
  "maxSweepIterations": 12,
  "sweepDeadlineMs": 120000,
  "compactUntilUnderDeadlineMs": 300000,
  "bootstrapMaxTokens": 6000,
  "leafTargetTokens": 2400,
  "condensedTargetTokens": 2000,
  "maxExpandTokens": 4000,
  "largeFileThresholdTokens": 25000,
  "summaryProvider": "",
  "summaryModel": "",
  "largeFileSummaryProvider": "",
  "largeFileSummaryModel": "",
  "expansionProvider": "",
  "expansionModel": "",
  "delegationTimeoutMs": 120000,
  "summaryTimeoutMs": 60000,
  "summaryCallWindowMs": 600000,
  "summaryMaxCallsPerWindow": 24,
  "summarySpendBackoffMs": 1800000,
  "timezone": "America/Los_Angeles",
  "pruneHeartbeatOk": false,
  "transcriptGcEnabled": false,
  "enableSummaryThinking": true,
  "maxAssemblyTokenBudget": 30000,
  "summaryMaxOverageFactor": 3,
  "fallbackMaxTokens": 512,
  "customInstructions": "",
  "circuitBreakerThreshold": 5,
  "circuitBreakerCooldownMs": 1800000,
  "replayFloodThresholdExternal": 3,
  "replayFloodThresholdInternal": 32,
  "fallbackProviders": [],
  "proactiveThresholdCompactionMode": "deferred",
  "autoRotateSessionFiles": {
    "enabled": true,
    "createBackups": false,
    "sizeBytes": 2097152,
    "startup": "rotate",
    "runtime": "rotate"
  },
  "independentLogFile": {
    "enabled": true,
    "file": "/tmp/openclaw/lossless-claw-2026-05-19.log",
    "maxFileBytes": 104857600
  },
  "cacheAwareCompaction": {
    "enabled": true,
    "cacheTTLSeconds": 300,
    "maxColdCacheCatchupPasses": 2,
    "hotCachePressureFactor": 4,
    "hotCacheBudgetHeadroomRatio": 0.2,
    "coldCacheObservationThreshold": 3,
    "criticalBudgetPressureRatio": 0.90
  },
  "dynamicLeafChunkTokens": {
    "enabled": true,
    "max": 40000
  },
  "stripInjectedContextTags": [
    "active_memory_plugin",
    "relevant-memories",
    "relevant_memories",
    "hindsight_memories"
  ]
}

Notes on the example:

  • Values shown are the runtime defaults when a fixed default exists.
  • databasePath shows the expanded default path shape. Use an absolute path in config rather than ~.
  • largeFilesDir shows the expanded default path shape. Both databasePath and largeFilesDir default to paths under OPENCLAW_STATE_DIR (which in turn falls back to ~/.openclaw).
  • timezone has no fixed hardcoded default; at runtime it resolves from TZ first, then the system timezone. The example uses America/Los_Angeles.
  • maxAssemblyTokenBudget has no default. The example uses 30000 as a realistic cap for a 32k-class model.
  • summaryPrefixTargetTokens has no fixed default. The example uses 20000, which matches the derived default for large-context models with the default leafChunkTokens.
  • databasePath is the preferred key. dbPath is an accepted alias.
  • largeFileThresholdTokens is the preferred key. largeFileTokenThreshold is an accepted alias.

Install and enable

Install with OpenClaw's plugin installer:

openclaw plugins install @martian-engineering/lossless-claw@latest

If you are running from a local OpenClaw checkout:

pnpm openclaw plugins install @martian-engineering/lossless-claw@latest

Use exact versions only for rollback or reproducible canary testing. OpenClaw treats an exact install spec such as @martian-engineering/lossless-claw@0.12.0 as pinned, so plugin update sync will not follow newer LCM releases until you return to the moving track:

openclaw plugins update @martian-engineering/lossless-claw@latest

For local plugin development, link a working copy:

openclaw plugins install --link /path/to/lossless-claw

Reference

Programmatic context-engine control

When the OpenClaw host supports context-engine control dispatch, lossless-claw advertises three sanitized operations:

OperationResultNotes
statusactive, messageCountReports current LCM conversation state only. It does not include lastRotatedAt because that timestamp is product/runtime state, not durable LCM state.
doctorok, warnings[]Returns a bounded summary-health warning list without transcript text, paths, or raw provider/debug output.
rotatemessageCount, lastRotatedAtReuses the /lossless rotate implementation and returns the timestamp for the successful rotate operation. Hosts that need durable rotation history should persist this result outside lossless-claw.

The control surface never accepts arbitrary slash commands and never exposes local database paths, transcript paths, backup paths, credentials, or raw shell output.

Core storage and session behavior

KeyTypeDefaultEnv overridePurpose
enabledbooleantrueLCM_ENABLEDEnables or disables lossless-claw without uninstalling it.
databasePathstring${OPENCLAW_STATE_DIR}/lcm.dbLCM_DATABASE_PATHPreferred path for the SQLite database.
dbPathstringalias of databasePathLCM_DATABASE_PATHLegacy alias for databasePath. Prefer databasePath in new config.
largeFilesDirstring${OPENCLAW_STATE_DIR}/lcm-filesLCM_LARGE_FILES_DIRDirectory where externalized large files and inline images are persisted. Automatically follows the active state directory.
ignoreSessionPatternsstring[][]LCM_IGNORE_SESSION_PATTERNSSession-key glob patterns that skip LCM entirely.
statelessSessionPatternsstring[][]LCM_STATELESS_SESSION_PATTERNSSession-key glob patterns that may read from LCM but never write to it.
skipStatelessSessionsbooleantrueLCM_SKIP_STATELESS_SESSIONSEnforces statelessSessionPatterns when enabled.
hostFallbackMode"error" | "capture-only""error"LCM_HOST_FALLBACK_MODEerror requires the full agent-run lifecycle. capture-only accepts bootstrap, after-turn ingestion, and maintenance so generic CLI runs keep transcript capture and recall without Lossless prompt assembly or host-triggered Lossless compaction. Backend-native compaction remains host-owned. Subagent projection requirements remain strict.
newSessionRetainDepthinteger2LCM_NEW_SESSION_RETAIN_DEPTHControls what survives /new. -1 keeps all context, 0 keeps summaries only, higher values keep only deeper summaries.
timezonestringTZ or system timezoneTZIANA timezone used for timestamp rendering in summaries.
pruneHeartbeatOkbooleanfalseLCM_PRUNE_HEARTBEAT_OKRetroactively removes HEARTBEAT_OK turn cycles from persisted storage.
transcriptGcEnabledbooleanfalseLCM_TRANSCRIPT_GC_ENABLEDEnables transcript rewrite GC during maintain(); disabled by default so transcript rewrites stay opt-in.
enableSummaryThinkingbooleantrueLCM_ENABLE_SUMMARY_THINKINGWhen true, requests low reasoning budget from the model during summarization calls. Set to false to disable reasoning and keep summarization output concise.
proactiveThresholdCompactionMode"deferred" | "inline""deferred"LCM_PROACTIVE_THRESHOLD_COMPACTION_MODEControls whether proactive threshold compaction is deferred into maintenance debt by default or run inline for legacy behavior.
autoRotateSessionFiles.enabledbooleantrueLCM_AUTO_ROTATE_SESSION_FILES_ENABLEDEnables automatic rotation for oversized LCM-managed session JSONL files.
autoRotateSessionFiles.createBackupsbooleanfalseLCM_AUTO_ROTATE_SESSION_FILES_CREATE_BACKUPSCreates or replaces the rolling rotate-latest SQLite backup before automatic session-file rotation. Manual /lossless rotate backups are always created.
autoRotateSessionFiles.sizeBytesinteger2097152LCM_AUTO_ROTATE_SESSION_FILES_SIZE_BYTESByte threshold that triggers automatic session-file rotation.
autoRotateSessionFiles.startup"rotate" | "warn" | "off""rotate"LCM_AUTO_ROTATE_SESSION_FILES_STARTUPStartup behavior for oversized indexed OpenClaw session transcripts that also have active LCM bootstrap state.
autoRotateSessionFiles.runtime"rotate" | "warn" | "off""rotate"LCM_AUTO_ROTATE_SESSION_FILES_RUNTIMERuntime behavior after post-turn checks. Runtime rotate logs deferral for active session JSONL rewrites and leaves direct rotation to startup or manual /lossless rotate.
independentLogFile.enabledbooleantrueLCM_LOG_FILE_ENABLEDWrites lossless-claw JSONL logs to an independent plugin-owned file in addition to OpenClaw's runtime logger.
independentLogFile.filestring/tmp/openclaw/lossless-claw-YYYY-MM-DD.logLCM_LOG_FILEOptional log path. A dated lossless-claw-YYYY-MM-DD.log path rolls over daily.
independentLogFile.maxFileBytesinteger104857600LCM_LOG_MAX_FILE_BYTESSize threshold for rotating the active lossless-claw log file to .1.log through .5.log.

Multi-profile note: OPENCLAW_STATE_DIR (set by the host OpenClaw gateway) controls where state is stored. When two gateways run on the same host (e.g. separate bot personas), each gateway sets its own OPENCLAW_STATE_DIR and lossless-claw automatically uses that directory for the database, large-file payloads, auth-profile lookups, and legacy secrets — no per-profile plugin config is needed.

Automatic session-file rotation rewrites only the live session transcript, keeps the active LCM conversation and durable history intact, and refreshes the bootstrap checkpoint. Before manual or startup rewrites, rotation forces leaf-only compaction for raw context outside the preserved tail so trimmed transcript messages are covered by LCM summaries without running unrelated summary-condensation passes. Startup rotation first scans OpenClaw's current indexed session stores for configured agents, then intersects those candidates with active LCM conversations and matching bootstrap file mappings. Runtime rotation checks from afterTurn() and maintain() intentionally do not directly rewrite active session JSONL because embedded prompt-lock fences can still be open while tool-call loops and host background maintenance overlap; runtime rotate logs a deferral until startup, manual /lossless rotate, or a future host-owned full-transcript rewrite primitive is available. Automatic rotation does not create a SQLite backup by default; set autoRotateSessionFiles.createBackups to true to make startup rotation create one pre-rotation LCM database backup for the batch before any transcript is rewritten. Manual /lossless rotate always keeps its backup-backed behavior regardless of this flag. Rotation never runs for ignored sessions, stateless sessions, or sessions without active LCM state. The preserved JSONL tail follows freshTailCount and expands through the newest user when necessary so rotation cannot split its following assistant/tool suffix. Transcript GC uses the host-provided rewriteTranscriptEntries primitive and defers until host-approved background maintenance when transcriptGcEnabled is enabled.

Lossless-claw writes routine operational JSONL logs by default at /tmp/openclaw/lossless-claw-YYYY-MM-DD.log, beside OpenClaw's /tmp/openclaw/openclaw-YYYY-MM-DD.log. Routine info and debug lines go to the independent file instead of the shared OpenClaw log. Startup banners and warning/error lines still go through OpenClaw's runtime logger so gateway-level startup and failure diagnostics remain visible. The independent file follows the same practical rotation model as OpenClaw: a dated filename rolls over when the local date changes, stale dated files are pruned after 3 days, and an oversized active file is rotated through .1.log to .5.log.

Every automatic decision emits grep-able log lines prefixed with [lcm] auto-rotate:. Startup emits one compact summary line with phase=startup, action=summary, scanned, eligible, rotated, warned, skipped, durationMs, bytesRemoved, and backup fields when a batch backup was created; quiet skips such as missing files, missing bootstrap mappings, and below-threshold files are counted there instead of producing one line per candidate. Rotation detail lines include phase, action, sessionId, sessionKey, sessionFile, sizeBytes, thresholdBytes, durationMs, backupPath, bytesRemoved, preservedTailMessageCount, and checkpointSize; real warning lines include the same available context plus reason or error.

Compaction thresholds and summary sizing

KeyTypeDefaultEnv overridePurpose
contextThresholdnumber0.75LCM_CONTEXT_THRESHOLDFraction of the active model context window that triggers compaction.
contextThresholdOverridesArray<{ name?: string; match: object; contextThreshold: number; freshTailCount?: integer; leafChunkTokens?: integer }>[]noneOptional ordered rules that override contextThreshold and, optionally, freshTailCount and leafChunkTokens by model id, model context-window range, or session glob pattern.
freshTailCountinteger64LCM_FRESH_TAIL_COUNTNumber of newest messages always kept raw. If this count would split the newest user turn, the protected tail expands to include that user and its following assistant/tool suffix.
freshTailMaxTokensintegerunsetLCM_FRESH_TAIL_MAX_TOKENSOptional token cap for the protected fresh tail. The newest user message and its following assistant/tool suffix are always preserved even if they exceed the cap.
promptAwareEvictionbooleanfalseLCM_PROMPT_AWARE_EVICTION_ENABLEDWhen enabled, budget-constrained assembly keeps older evictable items by prompt relevance instead of pure chronology. This improves retrieval under tight budgets, but it can reduce prompt-cache hit rates because the preserved prefix changes as prompts change.
stubLargeToolPayloadsbooleanfalseLCM_STUB_LARGE_TOOL_PAYLOADSWhen enabled, evictable tool-result rows backfilled with messages.large_content are assembled as [LCM Tool Output: file_xxx ...] stubs while the fresh tail stays inline. Requires scripts/lcm-blob-migrate.mjs, which defaults to the same large-files root as runtime LCM (LCM_LARGE_FILES_DIR or ${OPENCLAW_STATE_DIR}/lcm-files).
leafMinFanoutinteger8LCM_LEAF_MIN_FANOUTMinimum number of raw messages required before a leaf pass runs.
condensedMinFanoutinteger4LCM_CONDENSED_MIN_FANOUTNumber of same-depth summaries needed before condensation is attempted.
condensedMinFanoutHardinteger2LCM_CONDENSED_MIN_FANOUT_HARDHard floor for condensation grouping during maintenance and repair flows.
sweepMaxDepthinteger1LCM_SWEEP_MAX_DEPTHPreferred maximum condensation source depth during routine threshold sweeps. Use 0 for leaf-only and -1 for unlimited depth. Pressure sweeps may go deeper when summarized context remains above target.
incrementalMaxDepthintegeralias of sweepMaxDepthLCM_INCREMENTAL_MAX_DEPTHDeprecated alias for sweepMaxDepth. Kept so existing configs continue to load.
leafChunkTokensinteger20000LCM_LEAF_CHUNK_TOKENSMaximum source-token budget for a leaf compaction chunk. Larger chunks reduce sweep frequency at the cost of slower individual summary calls.
summaryPrefixTargetTokensintegerderivedLCM_SUMMARY_PREFIX_TARGET_TOKENSOptional target for summarized-prefix tokens after a full sweep. If unset, Lossless derives max(condensedTargetTokens, min(leafChunkTokens, floor(contextThreshold * tokenBudget * 0.5))).
maxSweepIterationsinteger12LCM_MAX_SWEEP_ITERATIONSHard cap on summarizer passes within a single full sweep. On hitting the cap the sweep stops cleanly and returns the partial result; bounds how long a sweep can run on the turn-critical path.
sweepDeadlineMsinteger120000LCM_SWEEP_DEADLINE_MSWall-clock budget for a single full sweep, in milliseconds. When exceeded the sweep stops before starting another pass, so a slow or rate-limited summarizer cannot hang the agent turn.
compactUntilUnderDeadlineMsinteger300000LCM_COMPACT_UNTIL_UNDER_DEADLINE_MSWall-clock budget for a whole compactUntilUnder operation, in milliseconds. compactUntilUnder runs up to maxRounds sweeps; without this the worst case is maxRounds × sweepDeadlineMs (~20 min at the defaults). The deadline is shared into each round's sweep and checked before the next round.
bootstrapMaxTokensintegermax(6000, floor(leafChunkTokens * 0.3))LCM_BOOTSTRAP_MAX_TOKENSMaximum parent-history tokens imported when a new LCM conversation bootstraps.
leafTargetTokensinteger2400LCM_LEAF_TARGET_TOKENSPrompt target for leaf summary size.
condensedTargetTokensinteger2000LCM_CONDENSED_TARGET_TOKENSPrompt target for condensed summary size.
summaryMaxOverageFactornumber3LCM_SUMMARY_MAX_OVERAGE_FACTORHard ceiling multiplier before oversized summaries are deterministically truncated.
fallbackMaxTokensinteger512LCM_FALLBACK_MAX_TOKENSMaximum token budget for deterministic fallback summaries when the LLM summarizer is unavailable. Values below 64 are ignored.
largeFileThresholdTokensinteger25000LCM_LARGE_FILE_TOKEN_THRESHOLDPreferred key for the token threshold that routes text attachments into large-file summarization.
largeFileTokenThresholdintegeralias of largeFileThresholdTokensLCM_LARGE_FILE_TOKEN_THRESHOLDLegacy alias accepted by the runtime. Prefer largeFileThresholdTokens in new config.
maxAssemblyTokenBudgetintegerunsetLCM_MAX_ASSEMBLY_TOKEN_BUDGETOptional hard cap for assembly and threshold evaluation, useful with smaller-context models.
maxExpandTokensinteger4000LCM_MAX_EXPAND_TOKENSDefault token cap for lcm_expand_query responses.

Forked child transcripts are also bounded by bootstrapMaxTokens when a host copies a raw parent JSONL branch into the child file. This protects the LCM database from importing unbounded parent history, but the host must still honor the thread-bootstrap-projection context-engine capability for subagent or thread forks so the model starts from the LCM-assembled compact view instead of the raw copied transcript.

Model selection, execution, and prompts

KeyTypeDefaultEnv overridePurpose
summaryModelstring""LCM_SUMMARY_MODELSummarizer model override. Bare model names reuse the chosen provider; provider/model strings force a specific provider.
summaryProviderstring""LCM_SUMMARY_PROVIDERProvider hint used only when summaryModel is a bare model name.
largeFileSummaryModelstring""LCM_LARGE_FILE_SUMMARY_MODELLarge-file summarizer model override.
largeFileSummaryProviderstring""LCM_LARGE_FILE_SUMMARY_PROVIDERLarge-file summarizer provider hint for bare model names.
expansionModelstring""LCM_EXPANSION_MODELlcm_expand_query sub-agent model override.
expansionProviderstring""LCM_EXPANSION_PROVIDERlcm_expand_query sub-agent provider hint for bare model names.
delegationTimeoutMsinteger120000LCM_DELEGATION_TIMEOUT_MSMaximum wall-clock budget for delegated expansion work across one lcm_expand_query call. Cross-conversation buckets share this deadline. The dynamic tool advertises a timeoutMs default with 30 seconds of extra RPC headroom for cancellation, cleanup, and result delivery.
summaryTimeoutMsinteger60000LCM_SUMMARY_TIMEOUT_MSMaximum time to wait for one model-backed summarizer call.
summaryCallWindowMsinteger600000LCM_SUMMARY_CALL_WINDOW_MSRolling window for the per-session summarization spend guard.
summaryMaxCallsPerWindowinteger24LCM_SUMMARY_MAX_CALLS_PER_WINDOWMaximum model-backed summarization calls per session/window before Lossless opens a non-auth spend backoff.
summarySpendBackoffMsinteger1800000LCM_SUMMARY_SPEND_BACKOFF_MSCooldown after the summarization spend guard opens.
customInstructionsstring""LCM_CUSTOM_INSTRUCTIONSExtra natural-language instructions injected into every summarization prompt.

Summary calls are executed through OpenClaw's api.runtime.llm.complete capability. If you configure an explicit Lossless summary model (summaryModel, largeFileSummaryModel, or fallbackProviders), OpenClaw must allow that runtime LLM override under plugins.entries.lossless-claw.llm.allowModelOverride and plugins.entries.lossless-claw.llm.allowedModels. openclaw doctor --fix can add the minimal policy entries for configured Lossless summary models. Delegated expansion calls use OpenClaw's runtime sub-agent layer; explicit expansionModel values require plugins.entries.lossless-claw.subagent.allowModelOverride and a matching subagent.allowedModels entry, or "*" if you intentionally trust any expansion target. openclaw doctor --fix can add the minimal subagent policy, and lcm_expand_query retries once without the override if the host rejects it.

Fallbacks, circuit breaking, and safety rails

KeyTypeDefaultEnv overridePurpose
fallbackProvidersArray<{ provider: string; model: string }>[]LCM_FALLBACK_PROVIDERSExplicit provider/model fallback chain for compaction summarization. Format for env vars is provider/model,provider/model.
circuitBreakerThresholdinteger5LCM_CIRCUIT_BREAKER_THRESHOLDConsecutive auth failures before the summarization circuit breaker trips.
circuitBreakerCooldownMsinteger1800000LCM_CIRCUIT_BREAKER_COOLDOWN_MSCooldown before the summarization circuit breaker resets automatically.
stripInjectedContextTagsstring[]["active_memory_plugin", "relevant-memories", "relevant_memories", "hindsight_memories"]LCM_STRIP_INJECTED_CONTEXT_TAGSXML tag names whose blocks are stripped from message content before compaction summarization. Memory/context plugins inject these via prependContext; stripping prevents ephemeral retrieval context from polluting compacted summaries. Env var format is comma-separated tag names. Set to [] (or empty env string) to disable.
replayFloodThresholdExternalinteger3LCM_REPLAY_FLOOD_THRESHOLD_EXTERNALMax replay-like messages allowed in a single SQLite-second for role=user before assertNoReplayTimestampFlood refuses the batch. Defaults to 3 to preserve replay defense for third-partyly-rebroadcastable input.
replayFloodThresholdInternalinteger32LCM_REPLAY_FLOOD_THRESHOLD_INTERNALMax identical messages allowed in a single SQLite-second for role=tool/assistant/system before the anti-replay guard refuses the batch. Defaults to 32 to absorb legitimate idempotent sub-agent bursts (same-second tool returns like {"status":"ok"}).

Nested objects

cacheAwareCompaction

KeyTypeDefaultEnv overridePurpose
cacheAwareCompaction.enabledbooleantrueLCM_CACHE_AWARE_COMPACTION_ENABLEDDeprecated. Accepted for config compatibility but no longer used for automatic compaction decisions.
cacheAwareCompaction.cacheTTLSecondsinteger300LCM_CACHE_TTL_SECONDSDeprecated. Accepted for config compatibility; threshold debt no longer waits for cache TTL.
cacheAwareCompaction.maxColdCacheCatchupPassesinteger2LCM_MAX_COLD_CACHE_CATCHUP_PASSESDeprecated. Automatic cold-cache catch-up passes were removed.
cacheAwareCompaction.hotCachePressureFactornumber4LCM_HOT_CACHE_PRESSURE_FACTORDeprecated. Hot-cache raw-history pressure no longer drives automatic compaction.
cacheAwareCompaction.hotCacheBudgetHeadroomRationumber0.2LCM_HOT_CACHE_BUDGET_HEADROOM_RATIODeprecated. Hot-cache budget headroom no longer defers automatic threshold compaction.
cacheAwareCompaction.coldCacheObservationThresholdinteger3LCM_COLD_CACHE_OBSERVATION_THRESHOLDDeprecated. Cold-cache streaks remain observable telemetry only.
cacheAwareCompaction.criticalBudgetPressureRationumber0.90LCM_CRITICAL_BUDGET_PRESSURE_RATIODeprecated. contextThreshold is the only automatic compaction threshold.

dynamicLeafChunkTokens

KeyTypeDefaultEnv overridePurpose
dynamicLeafChunkTokens.enabledbooleantrueLCM_DYNAMIC_LEAF_CHUNK_TOKENS_ENABLEDDeprecated. Accepted for config compatibility but no longer used by automatic compaction.
dynamicLeafChunkTokens.maxintegermax(leafChunkTokens, floor(leafChunkTokens * 2))LCM_DYNAMIC_LEAF_CHUNK_TOKENS_MAXDeprecated. With the default leafChunkTokens=20000, this resolves to 40000, but automatic compaction uses leafChunkTokens.

Threshold full-sweep compaction

Automatic compaction is threshold-only:

  • afterTurn() evaluates the resolved context threshold against the active token budget
  • below threshold, no automatic compaction runs and no leaf debt is recorded
  • at or above threshold, inline mode runs a threshold full sweep immediately
  • deferred mode records one coalesced "threshold" maintenance row and normally drains it in the background or host-approved maintain()
  • pre-assembly drain is reserved as an emergency safeguard when the live prompt is already over the active token budget

Lossless still records prompt-cache telemetry for status and diagnostics, but cache hotness no longer delays threshold debt. Legacy cacheAwareCompaction.* and dynamicLeafChunkTokens.* settings remain accepted so existing OpenClaw config continues to load, but they do not change automatic compaction behavior.

contextThresholdOverrides are optional and never replace the global fallback. Each rule's match object can include model, modelContextWindowMin, modelContextWindowMax, and sessionPattern; all fields in a rule must match. If several rules match, Lossless picks the highest-specificity rule, then the earliest rule in the array for ties. Exact model matches have higher specificity than sessionPattern matches, and session-pattern matches have higher specificity than context-window range matches. A matching rule may also set freshTailCount, which overrides the global fresh-tail count for assembly and threshold compaction, and leafChunkTokens, which overrides the global leaf chunk size for matching threshold sweeps. Threshold selection logs include the chosen threshold, source, rule index/name, token budget, threshold tokens, fresh-tail count, leaf chunk size, model, context-window value, and match reason.

Context-window matchers only apply when the OpenClaw host reports explicit model context-window metadata to Lossless. Lossless does not infer modelContextWindowMin or modelContextWindowMax matches from the active token budget. If an override must affect assemble-time freshTailCount on all currently supported OpenClaw hosts, prefer an exact model or sessionPattern matcher.

Full sweeps first run leaf passes until there are no more eligible raw-message chunks outside the fresh tail. Condensation is then driven by summarized-prefix pressure: the routine condensation phase obeys sweepMaxDepth, and if the summarized prefix still exceeds summaryPrefixTargetTokens, a pressure phase may use condensedMinFanoutHard and condense deeper. Total context pressure starts the sweep, but does not by itself force deeper condensation once the raw prefix has been summarized.

A single sweep is bounded by both maxSweepIterations (a hard cap on summarizer passes) and sweepDeadlineMs (a wall-clock budget). When either limit is reached the sweep stops before starting another pass and returns the consistent partial result built so far, logging a compactFullSweep stopped at … warning. This keeps a slow or rate-limited summarizer from hanging the agent turn — remaining context pressure is picked up by the next sweep.

Overflow recovery (compactUntilUnder) runs up to maxRounds sweeps to drive context under a target. Because every sweep re-arms its own sweepDeadlineMs, the whole operation is separately bounded by compactUntilUnderDeadlineMs (default 300000): the operation deadline is shared into each round's sweep — a sweep stops at whichever deadline is sooner — and is also checked before starting the next round. On hitting it, compactUntilUnder returns the consistent partial result and logs a compactUntilUnder stopped at … warning, so the worst case is the operation budget rather than maxRounds × sweepDeadlineMs.

Prompt-aware eviction

When promptAwareEviction is enabled:

  • the protected fresh tail is still preserved exactly as usual
  • only the older evictable prefix is affected
  • if the evictable prefix does not fit and the current prompt has searchable terms, lossless-claw keeps the most relevant older items instead of just the newest older items

Tradeoff:

  • this can improve retrieval quality when the prompt is asking about an older topic and the assembled context is tight
  • it also makes the assembled prefix less stable for providers with prefix-based prompt caching, because different prompts can keep different older items

If Anthropic prompt-cache stability matters more than topical recall under pressure, set promptAwareEviction: false.

Behavior notes

Summary model resolution

Compaction summarization resolves candidates in this order:

  1. LCM_SUMMARY_MODEL and LCM_SUMMARY_PROVIDER
  2. plugins.entries.lossless-claw.config.summaryModel and summaryProvider
  3. OpenClaw's default compaction model
  4. Runtime/session provider and model hints from OpenClaw
  5. fallbackProviders

If summaryModel already contains a provider prefix such as anthropic/claude-sonnet-4-20250514, summaryProvider is ignored for that candidate.

Lossless does not resolve provider credentials directly for compaction summaries. OpenClaw's runtime LLM layer owns provider/model preparation, auth profiles, OAuth refresh, base URLs, and dispatch. Lossless only selects the requested summary target and passes it to the host runtime, where model override policy is enforced.

A practical starting point for cost-sensitive setups is:

LCM_SUMMARY_MODEL=openai/gpt-5.4-mini
LCM_EXPANSION_MODEL=openai/gpt-5.4-mini

Session pattern matching

ignoreSessionPatterns and statelessSessionPatterns use full session keys.

  • * matches any characters except :
  • ** matches anything, including :

Cron scheduler keys (agent:<agent>:cron:<job>...) are isolated automatically when a new runtime sessionId reuses the same sessionKey. Configure ignoreSessionPatterns for cron only when the run should bypass LCM entirely; leave cron sessions included when they need in-run compaction. When OpenClaw exposes its runtime compaction delegate, /compact and overflow recovery for ignored sessions fall back to OpenClaw's built-in compaction path instead of LCM's summary DAG. Older hosts that do not expose that delegate keep the previous safe skip behavior.

These examples are storage exclusions, not compaction preferences. Matching sessions do not create LCM conversation rows or store messages in LCM. The agent:*:**:active-memory:** pattern is intentionally broad because ** spans colon-separated session-key segments, including nested prefixes before active-memory. The agent:*:dreaming-narrative-** example matches OpenClaw memory-core keys built with the dreaming-narrative- prefix (source).

Example:

{
  "ignoreSessionPatterns": [
    "agent:*:cron:**",
    "agent:*:**:active-memory:**",
    "agent:*:dreaming-narrative-**"
  ],
  "statelessSessionPatterns": [
    "agent:*:subagent:**",
    "agent:ops:subagent:**"
  ],
  "skipStatelessSessions": true
}

/new and /reset

Lossless-claw treats OpenClaw reset commands differently:

  • /new keeps the active LCM conversation and prunes active context according to newSessionRetainDepth
  • /reset archives the active conversation row and creates a fresh active row for the same stable sessionKey

This keeps long-term history available while still giving users a real clean-slate reset.

Deferred proactive compaction

Lossless-claw now defaults proactiveThresholdCompactionMode to deferred.

  • deferred mode records a single coalesced maintenance debt row per conversation
  • new deferred compaction debt is only created for contextThreshold pressure and uses reason "threshold"
  • maintain() consumes threshold debt when the host explicitly opts in to deferred execution
  • assemble() leaves pending threshold debt for after-turn background drain or host-approved maintain() while the live prompt is still within budget
  • assemble() only consumes pending threshold debt synchronously as an emergency safeguard when the live prompt estimate is already over the active token budget
  • old non-threshold debt from earlier builds is revalidated; if the conversation is no longer over threshold, it is cleared as a no-op
  • /lossless status (/lcm status alias) shows the current maintenance state, including pending/running/last-failure details
  • status output also surfaces the latest API/cache telemetry as diagnostics, not as a deferral gate
  • set proactiveThresholdCompactionMode to inline only if you need the legacy inline proactive compaction behavior for compatibility

/lossless rotate

/lossless rotate exists for a different use case than /new or /reset:

  • /new keeps the same active LCM conversation row and only prunes context.
  • /reset changes OpenClaw session flow, which is sometimes more disruptive than users want.
  • /lossless rotate keeps the live OpenClaw session identity and the same active LCM conversation row, but rewrites the backing transcript into a compact preserved-tail form.

Before rotating, Lossless-claw replaces one rolling rotate-latest SQLite backup. It then rewrites the current session transcript and checkpoints the same conversation at the new transcript frontier so bootstrap does not replay the dropped transcript history. Existing summaries, context items, and conversation identity stay in place. If you want additional timestamped snapshots, run /lossless backup explicitly before /lossless rotate.

Environment-only knobs outside plugin config

These settings are not part of plugins.entries.lossless-claw.config, but they still affect the system:

Env varDefaultPurpose
OPENCLAW_STATE_DIR~/.openclawActive state directory for the OpenClaw gateway. When set, all path defaults (database, large files, auth profiles, secrets) resolve relative to this directory instead of ~/.openclaw. Set automatically by OpenClaw for non-default profiles.
LCM_OPENCLAW_DIRunsetLossless shell CLI override for the OpenClaw state directory. Takes precedence over OPENCLAW_STATE_DIR for lcm commands only.
LCM_TUI_CONVERSATION_WINDOW_SIZE200Number of messages lcm-tui loads per keyset-paged conversation window.

Database operations

The SQLite database lives at databasePath or LCM_DATABASE_PATH. The default path is ${OPENCLAW_STATE_DIR}/lcm.db (resolves to ~/.openclaw/lcm.db when OPENCLAW_STATE_DIR is not set).

Inspect it with:

sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db"

SELECT COUNT(*) FROM conversations;
SELECT * FROM context_items WHERE conversation_id = 1 ORDER BY ordinal;
SELECT depth, COUNT(*) FROM summaries GROUP BY depth;
SELECT summary_id, depth, token_count FROM summaries ORDER BY token_count DESC LIMIT 10;

Back it up with:

cp "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"
sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" ".backup ${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"

Or from a supported OpenClaw chat/native command surface:

/lossless backup

Disabling lossless-claw

To disable the plugin but keep it installed:

{
  "plugins": {
    "entries": {
      "lossless-claw": {
        "enabled": false
      }
    }
  }
}

To switch back to OpenClaw's legacy context engine instead:

{
  "plugins": {
    "slots": {
      "contextEngine": "legacy"
    }
  }
}

Stable event identity deduplication

Lossless-claw persists a stable_event_key on messages that carry a responseId or tool call id. This prevents duplicate ingestion when the same semantic event arrives in two different content representations (typical case: the JSONL transcript is redacted by logging.redactPatterns while the live afterTurn batch is not). The key is derived from the message as follows, in order:

  1. assistant messages with responseId (or response_id): assistant-response:<responseId>.
  2. tool / toolResult messages that represent exactly one tool call id: tool-result:<toolCallId>.
  3. Otherwise, including aggregate tool-result messages: no key is persisted, and the row falls back to the existing content-based deduplication.

A partial unique index on (conversation_id, stable_event_key) ensures that two rows in the same conversation can never share a key. The mechanism is independent of logging.redactPatterns and requires no user configuration.