LCM uses its own help renderer so every command has consistent usage, options, and examples.
Use lcm --help for the complete command list and
lcm <command> --help for command-specific help. Commands grouped under
daemon, config, machine, project, events, and connectors use the parent command's
help page:
lcm daemon start --help
lcm config set --help
lcm machine recover --help
lcm project link --help
lcm connectors install --helpStorage-backed commands use the backend selected in the authenticated LCM
configuration. SQLite remains the default. With storage.backend set to
postgresql, reads, writes, native session import, compaction, and promoted
knowledge transfer use that PostgreSQL database. Each selected project must
already be linked to a registered remote project and the local machine must
be registered. Missing bindings or database failures stop the operation;
commands never fall back to a local SQLite database. Backend selection applies
to the configured home and daemon, rather than individual projects.
lcm export --all, lcm promote --all, and lcm compact --all enumerate authenticated locally known
project paths and bindings, including bindings that have no SQLite database or
meta.json. Aliases of the same selected project are processed once. This does
not enumerate every project hosted by the PostgreSQL server. An unbound local
project requires lcm project create or lcm project link <project-id> before
it can be selected with PostgreSQL.
lcm promote --all processes the canonical paths from those bindings even when
no local meta.json exists. --verbose reports each project's counts and
--dry-run previews the same selected projects. Progress and summaries go to
stderr. A failed project request is reported and makes the command exit with
status 1; other admitted projects may still complete. Identity or publication
refusals stop the command, and no successful empty-result message hides a failed
scan.
Unbound-project errors explain how to run lcm project create or
lcm project link <project-id>. Missing local storage errors direct you to
lcm import or lcm import-knowledge <file> in the intended project. CLI
remedies for these known failures are fixed messages; database diagnostics,
connection strings, and mutable exception text are not printed. Unknown
failures retain a generic diagnostic and exit with status 1.
lcm export without --output writes only the version-1 promoted-knowledge
JSON document to stdout. Progress and status messages go to stderr. With
--all, one file is written per project using a path-derived unique suffix;
--all --output <file> is rejected because one file cannot represent multiple
project exports. Any project failure makes the command exit with status 1,
including partial exports; files already completed remain available. Successful
commands exit with status 0. Native session import also exits with status 1
when any session fails.
lcm sensitive purge currently refuses PostgreSQL explicitly before deleting
local data. Statistics, status and doctor use the configured backend through
read-only diagnostic snapshots; observing them does not bootstrap or migrate
storage, prune local events, or fall back to a different backend.
Connector installation manages one complete transport bundle per agent:
lcm connectors install <agent> [--transport cli|mcp] [--global]
lcm connectors remove <agent> [--global]An explicit transport wins over stored
connectors.transports.<agent-id>, which wins over the registry default;
implicit defaults are not persisted. Claude Code, Qwen Code, and Zed default
to MCP. Codex and every other agent default to CLI, while Cline and Augment
are CLI-only until verifiable MCP adapters exist. CLI bundles use skill
guidance or rules fallback plus native hooks where implemented. MCP bundles use
MCP-only guidance plus native hooks where implemented; guidance never falls
back between transports. Removal is whole-bundle. The former component
selection option is removed.
Nested help is resolved before command execution. A help request therefore
never starts the daemon, changes a machine or project identity, installs or removes
a connector, or performs another command action. For known commands, this
preflight happens before required-argument validation, so lcm store --help
and other incomplete command forms still show the relevant help page.
The store command accepts one tag per occurrence using either long spelling; the aliases can be mixed and retain command-line order:
lcm store 'Use ensureDaemon before background promote' --tag type:solution --tag scope:project --tag project:lcm --tag 'source:<actual-thread-uuid>'In lcm store, --tag and --tags are repeatable single-tag aliases. This is
different from lcm export --tags, which remains a comma-separated filter,
for example lcm export --tags decision,architecture.
When SQLite is selected, the stored text must not contain an embedded NUL
character (U+0000). The store operation rejects that input before writing;
JSON-escaped NUL characters in tags remain supported. A selected legacy
promoted row containing an embedded NUL fails closed instead of returning a
truncated value. See Privacy & Data Handling
for the read-only diagnostic and deliberate replacement procedure.
lcm export writes JSON by default. The optional --format value accepts
only json; unsupported values are rejected before export work or output
writes begin.
lcm connectors list writes text by default. Its optional --format value
accepts text or json; unsupported values are rejected before connector
inventory is read or output is written.
An unknown command writes an error and the complete command list to the terminal, completes both outputs, and then exits with status 1.
The following daemon reads use a migration-free preflight when the managed daemon is healthy. The shared preflight acquires an authenticated daemon client for each read:
| Command | Operation performed by the daemon |
|---|---|
lcm search <query> |
Search episodic and promoted memory |
lcm grep <query> |
Search messages and summaries by exact text or regular expression; optional inclusive --since accepts `YYYY-MM-DDTHH:mm:ss[.S{1,3}](Z |
lcm describe <nodeId> |
Read summary or stored-memory metadata |
lcm expand <nodeId> |
Expand a summary into source detail |
When --since is supplied, its value is forwarded to the daemon exactly as
provided. An empty or whitespace-only value is therefore invalid and returns
HTTP 400; omit the option when no lower-bound filter is wanted.
The local inspection commands machine show, project list, project show,
config get, events status, events validate,
events quarantine, sensitive list, sensitive test, and export also
complete the authenticated legacy-home migration gate. When a healthy managed
daemon is the owner of a private publication lock, the gate and the selected
read preparation retry only the lock-acquisition callback. Output, exit status,
and export file writes happen once after the callback succeeds. Mutation and
lifecycle commands keep their existing admission and migration behavior.
When version 1 knowledge export/import or compaction discovery opens project storage, its selected backend stays protected until the storage work and connection cleanup finish. Backend publication must wait or report contention during that interval. Automatic publication retries stop once project preparation begins; an error from opening storage, performing the operation, cleanup, or final publication validation is reported without replaying the operation. A failed command may already have committed storage changes, so inspect its result before retrying.
If home or legacy-entry authentication fails and closing its already-open descriptor also fails, LCM preserves both errors in order: the authentication or validation failure remains the primary cause, and the close failure remains available as cleanup evidence. An entry absent before it is opened is still treated as absent. Correct the primary trust failure before retrying; the cleanup evidence may also indicate a filesystem or descriptor problem that needs attention.
Atomic private-file writers preserve an earlier write or setup failure if closing the temporary descriptor also fails. The ordinary replacement writer also retains temporary-file cleanup errors. Durable writes retain subsequent cleanup errors in descriptor, temporary-file, and parent-directory order. These diagnostics help distinguish the original failure from cleanup trouble.
Exclusive creation has distinct outcomes. The non-durable
atomicWritePrivateFileExclusive helper preserves pre-publication failures
alongside temporary-file cleanup errors, and still reports success when a
completed publication only fails to remove its extra temporary hard link.
The published file remains usable, although that temporary link may remain.
The durable exclusive writer instead reports failed post-link cleanup because
durability has not completed. The retained-parent atomicWritePrivateFile
exclusive branch keeps its existing best-effort temporary cleanup behavior;
its temporary unlink failures are not added to the primary error. The separate
writePrivateFileExclusive helper also keeps its existing best-effort cleanup
behavior and is outside this diagnostic change.
The first authenticated health probe used to identify a retryable daemon can
take up to two seconds. After the first qualifying contention, retries share a
single two-second monotonic elapsed deadline and poll at most every 50
milliseconds; time spent in process-birth and health checks counts against that
deadline. Wall-clock corrections do not extend or shorten this retry duration.
Bootstrap migration attempts have their own existing bounds. Worktree
reconciliation lock acquisition uses a five-second monotonic retry window and
polls at most every 50 milliseconds; wall-clock corrections do not extend or
shorten that window. Ordinary command I/O plus an in-flight attempt can extend
total command time. Missing, foreign, malformed, stale, or unhealthy
publication evidence still fails closed and exits with status 1. Before the
retry deadline's expiry is recognized, a refusal reports the current typed
contention; after recognized expiry, the first contention for the current
lock-acquisition callback is preserved only if that callback admitted at least
one retry; otherwise, the current contention is reported. Exhausted or
rejected export admission exits unsuccessfully, including with --output or
--all. An --all export may have already written earlier projects when a
later project fails; those outputs remain, and the command exits with status 1.
The process-local catalogue discovery cache uses a monotonic elapsed-time TTL capped at 1,000 milliseconds; wall-clock corrections do not extend or shorten it, and identity and state guards still invalidate stale entries.
lcm search <query> --limit <n> accepts a positive integer from 1 through
1000 and defaults to 5. The limit is a maximum applied independently to each
selected layer. Episodic candidate recall grows to at least 50 records per
store before the final maximum is applied. Episodic results concatenate
messages first and then summaries, so messages can fill the maximum before a
summary appears. --tag <tag> filters promoted entries by all supplied tags;
episodic history remains unfiltered. Use --layer promoted for tag-only
recall. All required promoted tags are applied before the caller's result
maximum, so the maximum counts eligible records. Omitted or empty tags do not
filter either layer. Values outside this
range or that are not integers are rejected by the daemon with HTTP 400
(invalid limit).
lcm expand <nodeId> --depth <n> accepts any positive integer and defaults to
1; no upper bound is imposed. Malformed explicit depths are rejected by the
daemon with HTTP 400 (invalid depth) before project admission. The direct
daemon request body must be a JSON object; top-level null, arrays, and other
JSON primitives receive HTTP 400 (invalid request body) before project
admission. Malformed JSON syntax keeps the existing server error behavior.
Before using this route, LCM reads a bounded, no-follow configuration snapshot
without taking the private mutation/publication lock. If config.json is
absent, the snapshot uses validated defaults and records an absent witness;
absence alone is not a reason to fall back. For an existing file, the snapshot
must be readable, well-formed, within the size limit, a regular non-symlink
file, and otherwise valid. LCM then requires a present daemon token and an
authenticated healthy health response from the current
LCM version with both private identity markers—a matching packaged entrypoint
and authenticated matching packaged runtimeDigest. If the invoking CLI cannot
resolve or hash its local packaged entrypoint, it falls back to the locked
lifecycle path rather than treating either missing identity as a wildcard. The
health response must also report a matching storage backend, and the
configuration witness must remain unchanged.
This lets ordinary reads continue while a publication consumer holds the
exclusive lock without reusing a stale packaged daemon after a rebuild.
Authenticated daemon read responses are buffered until request-time admission
is repeated after the handler finishes. LCM compares both the configuration
witness and terminal publication-journal checksum before releasing up to 10 MiB
of buffered output. If publication begins, completes, aborts, or changes
evidence during the handler, the buffered result is discarded and the request
returns a blocked response instead of leaking a stale or mixed-backend result.
An existing publication directory without a journal, including an empty
directory, is incomplete evidence, not the legacy SQLite no-evidence case.
Removal or inode rebinding during admission is unsafe storage. This response
buffering applies to read routes; lcm store remains a mutation.
lcm store <text> first completes legacy-home bootstrap admission through the
same locked migration gate, then reuses the authenticated healthy daemon client
without redundant lifecycle discovery. The daemon still revalidates backend,
configuration, and publication state and performs the write through
operation-scoped publication admission. If the client preflight cannot prove
identity, health, or a stable configuration, lcm store returns to the
existing daemon-lifecycle path without rerunning the completed legacy gate.
The route is fail closed. An unreadable, malformed, oversized, symlinked, or
otherwise invalid configuration, missing token, failed or ambiguous health
check, backend mismatch, or configuration change between the two snapshot
reads returns to the existing authenticated migration and daemon-lifecycle
path. Daemon request admission independently rejects an unsafe or replaced
private root before reading storage and revalidates it before releasing the
buffered response. LCM never treats an uncertain snapshot as
permission to bypass migration, signal an unknown process, or mutate state.
Other mutation-requiring commands retain their existing migration and locking
behavior; pure exits and explicit read exceptions such as help, diagnose,
usage-only parent actions, connectors list, and connectors doctor remain
exempt according to the command-routing policy. When connector inspection is
unavailable, connectors doctor reads its stored transport hint through the
same bounded, stable, lock-free configuration admission.
The configuration read used by lcm doctor and by connector transport
resolution is also lock-free and authenticated: two descriptor-bound snapshots
of config.json and two reads of the terminal publication journal must agree
before the bytes are trusted. Each journal admission retains the authenticated
publication-directory identity through journal reading and evidence
enumeration, and rejects removal or rebinding. When a private canonical .lcm
root is present, both readers open it without following a symlink and retain
that directory descriptor across both snapshots and both publication
admissions, rejecting a root replacement or unsafe publication root. A legacy
SQLite installation with an absent root, or a non-private root without
publication evidence, remains read-compatible without a retained descriptor;
every boundary rechecks for a new admissible root or publication evidence and
fails closed if either becomes unsafe. Any subsequent configuration write,
including an explicit transport
preference, still takes the normal authenticated mutation lock and remains fail
closed if that lock is held by another operation.
Doctor's map validation and worktree inspection are observational. It reports
invalid or ambiguous mappings without normalization, duplicate removal, or
reconciliation writes. Existing-daemon identity observation is bounded and
authenticated; it does not probe active storage readiness. Missing installed
version or packaged runtime digest, mismatched identity, and unreadable
credentials leave managed-daemon identity unverified. Run doctor from the installed lcm.mjs
artifact; reinstall LCM if that artifact is unreadable or damaged.
Doctor does not acquire publication mutation locks, wait for a lock holder to
repair state, or retry lifecycle stages. Use lcm daemon restart for an
explicit lifecycle repair, lcm install for Claude Code settings/hooks/managed
guidance, or lcm connectors install <agent> for another connector. Review and
resolve project mapping findings explicitly, then rerun doctor. There is no
automatic-repair mode.
lcm install uses bounded publication admission for its preflight
migration and each installer lock-taking stage, including daemon lifecycle
publication assertions. A retry re-attempts only a lock-acquisition callback;
the callback body has not run when contention is raised, so prompts, settings
writes, skill installation, and daemon startup are not repeated. The shared
window is armed at the first qualifying contention, lasts up to two seconds of
monotonic elapsed time, and polls every 50 milliseconds. Wall-clock corrections
do not extend or shorten this publication retry duration. Bootstrap-lock retries
remain unchanged and
may add a bounded overshoot of up to one second when both locks contend.
Identity, token, process-birth, health, entrypoint, version, backend, or
runtime-digest mismatches still fail closed and exit with status 1. Before the
retry deadline's expiry is recognized, a refusal reports the current typed
contention; after recognized expiry, the first contention for the current
lock-acquisition callback is preserved only if that callback admitted at least
one retry; otherwise, the current contention is reported.
Lock-free configuration preparation also rejects a configuration or
publication journal that changes between its two authenticated snapshots. Once
the active publication has settled, rerun lcm install manually. This drift
refusal is not retried automatically, and rerunning the installer does not imply
that unrelated installation failures have resolved.
The refusal is reported as a stable diagnostic so you can rerun once concurrent publication activity has settled.
Before lcm install reuses a healthy daemon identity for those retries, it
revalidates the complete configuration snapshot and terminal publication
journal after the authenticated health response and its JSON body have been
read. A private canonical .lcm root is retained across that exchange and its
exact directory entry is checked again around the final reads. If any of that
evidence changes, the captured identity is discarded; rerun lcm install once
publication settles if lock contention remains. A legacy non-private SQLite
root without publication evidence keeps its existing read compatibility.
lcm stats, lcm stats --pool, lcm status, and lcm doctor inspect the
selected SQLite or PostgreSQL backend without starting or restarting the
daemon. They skip legacy-home bootstrap migration and publication-convergence
retries. These commands do not register machines or projects, repair settings
or identity maps, migrate schema, prune orphan event sidecars, or create
missing project databases. Repairs remain explicit operator actions.
The CLI, local MCP lcm_stats, and daemon /stats, /stats/pool, and /status
surfaces use the same sanitized backend diagnostic snapshot. It includes the
selected backend, publication admission, verified TLS readiness where
applicable, schema/migration and extension readiness, safe project and machine
identifiers, pool observations, and local outbox counts when available.
Configuration alone never proves readiness. Unobserved subfacts are
unverified, failed observations are unavailable, and facts that do not apply
to the selected backend are not-applicable; verified facts are ready.
Text output shows these readiness fields even when statistics are unavailable, including search readiness, pool origin and counts, project scope, machine identity, local outbox delivery counts, and a fixed next action. It never renders a database error or arbitrary configuration value as guidance.
The project snapshot field distinguishes aggregate observations from a
selected project. A ready selection includes its admitted PostgreSQL UUID
or SQLite project hash and, when available, the associated local hash used
for outbox counts. No project paths are printed. An unknown selection is
reported as unavailable and never falls back to aggregating all projects.
A selected remote UUID without an observed local binding leaves the local
outbox unverified. Failures retain the requested scope but discard identifiers
when their observation cannot be trusted.
SQLite does not require machine registration: an absent machine identity is
not-applicable. If a machine UUID is present and validated, it is shown as
an identity observed in this configured home. PostgreSQL still requires its
machine identity to be verified. Aggregate project scope means no individual
project ID was selected; an absent ID is not evidence of a missing project.
| Snapshot state | Meaning and next action |
|---|---|
healthy |
All required readiness observations verified. |
degraded |
Readiness verified, but the observed pool still reports a recovery failure condition. Inspect the backend service and repeat the diagnostic after recovery. |
unavailable |
Storage could not be safely read or a required observation could not be verified. Check configuration, service readiness, and the fixed guidance in the output. |
permission-denied |
A trusted local or database permission failure prevented observation. Restore the intended access or runtime grants, then retry. |
timeout |
Collection reached its deadline or the caller cancelled it. Check service responsiveness and retry. |
stale-publication |
Publication evidence is unresolved or inconsistent, or authenticated evidence changed during collection. Preserve the evidence and follow the publication recovery guidance. |
Backend snapshot collection has a default deadline of 2000 milliseconds and
honors caller cancellation. SQLite project and event-sidecar reads share one
owned child process for the complete snapshot, so additional projects do not
incur a new process launch for every database. All discovered sidecars are
considered within that same deadline. A timeout is reported even if a probe stalls;
cleanup does not replace the primary failure classification. A diagnostic
probe owns and closes its own resources, while a daemon's shared pool stays
open. lcm stats --pool reports safe pool counts and whether they came from
the daemon, a local SQLite process, or a diagnostic probe. SQLite total and
idle counts are captured before project and outbox reads. They may remain
available when either read times out, provided the publication and configuration
still authenticate; the timed-out project, schema, and outbox facts remain
unverified. PostgreSQL observations include configured
maximum, total, idle, and waiting connections and the observed failure latch.
Daemon pool counts are observed independently before the remote probe starts.
They may remain available when that probe times out or fails, provided the
publication and configuration still authenticate. A ready pool observation
means its counts were available; it does not establish remote backend health.
The snapshot retains its failure classification and recovery action.
Unavailable counts are omitted rather than reported as zero.
Unexpected failures at the daemon statistics routes retain the configured backend name when it is known. Their snapshots contain only the standard classification and fixed recovery action; raw errors and partial metrics are discarded.
Numeric statistics such as token totals, compression, recall counters, and
local outbox counts are included only when observed. Partial or unavailable
remote metrics do not become empty-project totals. Diagnostic output contains
no recalled-text previews (topRecalled), transcript or memory payloads, raw
errors, SQL values, connection URLs, role names, CA paths, or arbitrary local
paths. Verbose output follows the same boundary.
Publication and configuration are authenticated before and after asynchronous
probes. If their witnesses differ, the result is stale-publication and the
collected metrics are discarded. This is an optimistic observation of matching
evidence; it is not a transaction-wide authority or consistency guarantee.
The snapshot takes no publication mutation lock and writes no authority,
configuration, or witness files.
SQLite statistics open existing databases read-only after authenticating the
LCM root, project directories, and database leaves. The root and project
directories must be owner-held with exact mode 0700. Missing databases remain
missing. An old or unreadable schema is reported without migration. Reads
include committed data in the live WAL; SQLite may create necessary -wal or
-shm read-coordination artifacts. This engine bookkeeping does not authorize
checkpointing, journal-mode changes, repair, or sidecar deletion. If a safe
read requires durable content changes, the diagnostic reports unavailable.
For aggregate SQLite diagnostics, Projects counts only initialized project
databases that exist and pass admission at the time of observation. Admitted
project directories without a db.sqlite file, including metadata-only
registrations, remain unchanged and are omitted from aggregate numeric totals.
If every admitted project directory is uninitialized, the aggregate can be
healthy with Projects: 0; this does not establish the health of the skipped
registrations. Selecting an uninitialized project remains unavailable.
The SQLite pathname API still leaves a narrow same-account swap-and-restore race between identity checks. Authentication checks surround opening and reading, but do not provide isolation from another process with the same filesystem authority. Event scans likewise preserve existing sidecars and report skipped or failed observations without pruning them.
lcm status reports verified daemon details, available numeric project counts,
and the same backend diagnostic snapshot. If authenticated daemon identity is
verified but its status request fails, the daemon remains reported as up and
the command performs a fresh local diagnostic observation. The output identifies
that fallback; backend readiness can change between the two observations.
It omits the former lastIngest,
lastCompact, and lastPromote fields: project metadata values are not part of
the diagnostic allowlist. A missing or unreadable project has no numeric
project object, so an unavailable observation cannot be confused with an
observed empty database.
lcm status, lcm stats --pool, and lcm doctor authenticate an existing
daemon through the internal GET /health/observe endpoint. It reports process
identity with observation: "identity-only" and storage.status: "unverified";
it never opens project storage or runs the active readiness probe. Diagnostics
require the exact installed version, backend, entrypoint, runtime digest, and
unchanged configuration witness. An old daemon without this endpoint, malformed
response, missing credentials, or mismatched identity refuses observation;
there is no retry through active /health or automatic lifecycle repair.
Status and pool statistics retain their local diagnostic fallback. Status JSON
identifies its source with diagnosticSource: "daemon" or "local".
Doctor reports verified daemon identity separately from its backend diagnostic snapshot. That snapshot describes observed read availability and schema state; it cannot establish write readiness. Even if both checks pass, active storage readiness remains unprobed. A pending passive queue warns that queue draining is unverified, preserving backlog counts and remediation guidance. Use the explicit managed lifecycle commands when active readiness or restart is needed.
lcm doctor limits the complete daemon identity observation exchange to two seconds. The
deadline covers both the HTTP response and parsing its JSON body, so an
unresponsive or partially responding local daemon cannot hold up the remaining
diagnostics.
Authenticated daemon health includes a startup-captured SHA-256 digest of the
packaged lcm.mjs entrypoint. LCM reuses a running daemon only when its version,
storage backend, entrypoint, and runtime digest all match the invoking CLI. This
also replaces a daemon left running across a same-version rebuild. A missing or
mismatched digest makes the running daemon ineligible for reuse. When the
daemon is responsive, lcm daemon restart uses the authenticated lifecycle and
the owning systemd/launchd service to apply the replacement; the digest check
does not grant PID, pathname, or token authority for offline recovery. A
no-response or ambiguous service remains untouched and fails closed.
After lcm compact creates summaries, automatic promotion normally uses the
same verified daemon connection. If that connection fails at the transport
layer, LCM runs the managed-daemon recovery check, creates a fresh client, and
retries promotion for that project once. It does not rerun compaction.
Application-level promotion errors are not retried, and each later project gets
its own independent recovery opportunity.
Automatic promotion records its most recent timestamp in project metadata on a
best-effort basis. Metadata is bounded to 1 MiB and published atomically with
0600 permissions, including when tightening a legacy file that was more
permissive. Invalid, unreadable, or untrusted metadata is left unchanged and
does not undo promoted memories; promotion counts and results are independent
of this metadata update. If reopening the authenticated metadata parent fails
directly because the process or system file-descriptor limit is exhausted
(EMFILE or ENFILE), or because the target filesystem has no space
(ENOSPC), LCM skips the metadata update and returns the completed promotion
result. Parent absence, symlink loops, non-directory components, ownership or
mode rejection, and other topology failures remain fail-closed and return an
error. --dry-run never writes metadata. On platforms with a POSIX UID, the
existing metadata file must be owned by the current UID; where UIDs are
unavailable, that ownership check is skipped.
lcm compact --all reports each selected project that it cannot open, prepare, or
scan as a failure in the Compact phase while continuing with readable projects.
These failures produce a nonzero exit status and are not reported as “Nothing to
compact.” A failed scan does not mark any session as processed. Back up the
reported project database, resolve its storage or schema error, and rerun the
command; the still-eligible sessions will be discovered again.
lcm compact --all discovers projects from authenticated project bindings.
It does not read meta.json to select projects or trust unbound metadata
directories. Missing or unsafe discovery metadata therefore does not override
a valid binding or become a separate metadata-scan failure. Storage and schema
failures for selected projects are still reported as described above.
Use the public commands for daemon recovery:
lcm doctor
lcm daemon restartlcm doctor observes the daemon, hooks, connector registration, static MCP
setup, and summarizer configuration. Its MCP protocol capability check is
reported as not probed: doctor does not spawn an MCP server or perform a live
handshake. It never starts, stops, or repairs a daemon. lcm daemon restart
validates the effective configuration, asks the host service manager to replace
the exact LCM service, and waits for authenticated health before returning.
After changing configuration, run the restart command once; do not start a
second daemon to work around a health failure.
When a failed start or restart reports a newly created daemon temporary directory with clipped owner permissions, the CLI retains the mapped recovery command and the trusted lifecycle guidance on one line:
lcm daemon unavailable (startup-failure); run 'lcm daemon restart' or 'lcm doctor'. newly created daemon temp directory lacked required owner permissions, was removed, and retry should use an owner-preserving umask such as 0077
Follow the managed-daemon temporary-storage recovery
steps before retrying under an owner-preserving umask such as 0077.
Linux uses the current user's systemd --user manager and macOS uses the
current user's launchd agent. Both integrations are deliberately one-shot:
LCM does not request automatic restart (Restart=) or a launchd KeepAlive
policy. If a daemon reaches its idle timeout and exits normally, the next LCM
request recreates the registered service. This keeps idle terminals quiet while
retaining a single, authenticated service owner.
On Linux, managed-daemon admission also proves that the configured
127.0.0.1 listener belongs to the authenticated systemd service. LCM first
uses direct process-descriptor evidence when the caller can read it. If a
PrivateTmp-isolated user unit runs in a sibling user namespace that hides
those descriptor links, LCM
uses the operating system's fixed ss socket-diagnostic command to compare
the listener's kernel cgroup with systemd's exact ControlGroup for the
registered service. Missing tools, malformed output, mixed ownership, or a
cgroup mismatch remain fail-closed; health plus a matching PID is never enough
to authorize reuse or replacement.
Health observation has three outcomes. An HTTP response (including an error status, malformed body, or a body timeout after headers) stays on the normal authenticated path. A transport failure or deadline before any response is a no-response outcome and may be handed to the service manager only when the exact managed service is still identifiable. An unknown or ambiguous outcome is refused. LCM never turns an uncertain result into permission to signal a numeric PID or delete state files.
Detached and foreground launches are compatibility/debug modes, not managed
recovery authorities. Windows, containers without a user service manager, and
any unsupported or ambiguous launch are refused rather than force-recovered.
Run lcm doctor, restore the host service manager, and retry lcm daemon restart.
There is no detached offline force-recovery option. A service-manager identity
is an ownership authority for LCM, not a same-UID filesystem security boundary:
another process running as the same operating-system user can still read or
modify that user's files and runtime state. When recovery is refused, inspect
the host with lcm doctor, restore the manager, and retry one explicit
lcm daemon restart.
On Linux, a normal host-context lcm install records an owner-only,
checksummed witness that the canonical HOME parent was observed as host UID 0.
A PrivateTmp user namespace may use that direct-host-root-observed,
integrity-checked historical evidence only when its parent appears as the
kernel overflow UID and /proc/self/uid_map proves host UID 0 is unmapped.
The canonical HOME and parent paths, device/inode identities, parent mode, and
parent ctime must still match. Missing, malformed, unsafe, stale, or changed
evidence fails closed.
When the witness is genuinely absent (no file at all), a constrained
namespace can bootstrap it without a host-context install. LCM asks the
per-user service manager, through the fixed /usr/bin/systemd-run --user --wait --collect --pipe --quiet launcher with no mount, PID, or system-scope
properties, to run a bounded same-UID Node helper that opens the canonical
HOME parent without following symlinks and reports its owner, identity, mode,
ctime, and its own /proc/self/uid_map. The helper's TMPDIR is the
authenticated HOME, never host /tmp. LCM accepts that evidence only when
the helper's namespace maps UID 0 to host UID 0, the parent owner is UID 0,
and the device, inode, mode, and ctime equal the caller's retained
observation; it then records the witness under the normal publication locks.
A missing user manager, timeout, signal, nonzero exit, any stderr output,
malformed or non-canonical output, a non-root helper namespace, a non-root or
overflow owner, or a topology mismatch fails closed. An existing witness that
is malformed, unsafe, stale, or unreadable is never replaced through this
helper; remove it deliberately or rerun lcm install from a normal host
context.
This witness is not a secret, MAC, or cryptographically unforgeable root
credential. Same-UID processes remain outside the filesystem security boundary
and can edit or delete the witness along with other runtime state.
If a connector was removed or its installed paths are stale after an upgrade, repair it through the connector manager and then re-run doctor:
lcm connectors install <agent>
lcm connectors doctor <agent>
lcm doctorDo not edit hook files or use process-kill commands as a recovery procedure. See Managed daemon recovery for the platform boundaries and the user-facing failure cases.
lcm compact accepts a bounded worker-pool setting for manual batch work:
lcm compact --all --max-concurrency 4
lcm compact --all --replay # always sequential
lcm compact --all --dry-run # validate and preview onlyThe persistent setting is llm.maxConcurrency in ~/.lcm/config.json (default
1, valid range 1..32):
lcm config set llm.maxConcurrency 4 --json
lcm config get llm.maxConcurrency --effective--max-concurrency overrides the stored value for one invocation and does not
write the configuration file. It must be canonical unsigned decimal text and
is rejected outside 1..32. --replay always uses one worker so each summary
sees the previous summary's context; a stored value is clamped to 1, while an
explicit value above 1 is rejected. The limit counts only in-flight /compact
requests. Discovery and rendering are outside the limit, and promotion remains
sequential. Compacted projects are promoted in deterministic discovery order.
--dry-run validates configuration and discovery, but does not start the
daemon, register an invocation lease, dispatch compact/provider work, write
summaries, or promote anything. SQLite preview discovery opens only existing
authenticated database files and does not run schema migrations or change
PRAGMA user_version. A missing database is not created. A schema that cannot
be read is reported as a discovery failure. Unresolved legacy worktree identities
with a separate database are refused explicitly; preview never merges or
removes that data. Resolve the normal worktree reconciliation first, or use the
recovery/migration owner when native archive facts require it.
Every non-hook manual compact is bound to an authenticated daemon invocation. The lease is refreshed while work runs. A heartbeat failure, transport disconnect, lease expiry, or signal begins a drain: no new work is admitted, queued and active local work settles, and invocation-owned promotion is cancelled. An atomic pass admitted before cancellation may finish, but later passes cannot acquire a durable-write permit.
Ctrl+C (SIGINT) returns 130; SIGTERM returns 143. Both statuses are
returned only after the drain proves zero daemon-owned and local work. Repeated
signals keep waiting and print a diagnostic instead of interrupting settlement.
Provider work already accepted by a remote service may continue remotely; the
local guarantee covers LCM-owned queued/active requests, SDK retries, provider
processes/groups, locks, and invocation-scoped promotion only.
If cancellation cannot prove that the managed daemon and its owned provider work disappeared, LCM does not signal an unknown process or claim success. It stays in draining state, reports the missing proof, and fails closed. This also applies when a managed restart cannot prove old-instance disappearance and replacement identity. Replacement proof requires the packaged runtime digest of the invoking CLI to exactly match the new daemon. When that digest is unavailable, including source-style CLI execution without packaged build metadata, the drain remains unproved and reports the missing identity proof.