LM-Kit OneDocs2026.9.7lm-kit.comEULA
Deployment

Where Data Lives

"Local-first" is only worth something if it is auditable, so this page is the audit: every place this server persists anything, its lifetime, its deletion path, its scope once the server runs as a fleet, and the complete, short list of ways any byte can leave the machine. A reviewer should be able to read this page and know what to write in the data-protection assessment; an operator should be able to read it and know what to back up.


1The state directory#

Everything the server writes resolves under the state directory, decided once at startup by one rule: the executable's own directory when it is writable (services, portable installs, dev builds), otherwise the local application-data folder (LM-Kit/One under it), and LMKIT_STATE_DIR pins it explicitly. The startup log names the directory and which rule applied, and lmkit doctor prints it beside the identity store it resolved. Every fixed location the server writes (the settings file, the keyring, the embedded identity store, the operator history, the forensics, the certificates, the managed tools, the embedded search databases) sits under it, so the directory is the backup set of a single node and the disposal set of a decommissioned one. The fixed locations, as the code that resolves them declares them (the table is generated from the server's state-path registry, so a location added without its row fails the build; section 2 states each one's lifetime and deletion):

Location What it holds Scope on a fleet
appsettings.json The runtime configuration the admin panel reads and writes. Per node
keyring/ The keys every encrypted setting is sealed with; the settings file restores unreadable without it. Per node
admin-identity.db Operator accounts, sessions and API keys when no shared admin database is configured. Per node
apikeys.json API keys minted before the identity store existed, adopted into it once. Per node
logs/ The rotating server log. Per node
audit.db The request audit trail and the operator activity journal. Per node
metrics.db The dashboard's resource-history samples. Per node
telemetry-history.db The per-instrument telemetry time series behind the admin charts. Per node
forensics/running-sentinel.json Heartbeat of the running process; one still present at the next start means the previous run died without cleanup. Per node
forensics/crash-tombstone.json The exception text a dying process leaves for the next start's restart analysis. Per node
forensics/restart-report.json The current restart-cause report, kept until an administrator acknowledges it. Per node
forensics/restart-history.jsonl One line per server start, with the forensic report of every crash recovery. Per node
certificates/ TLS material this node terminates with: the self-signed and the uploaded certificate, the trust-store flags, and the ACME store by default. Per node
certificates/server-cert.pfx The self-signed HTTPS certificate generated on first run and renewed near expiry. Per node
certificates/operator-uploaded.pfx The certificate an administrator uploaded from the TLS panel; used ahead of the self-signed one. Per node
search-embedded/ The embedded search clusters' SQLite databases, one file per cluster that declares no data directory; a fleet configures an external engine instead. Per node
tools/ Server-managed tool installs such as the downloaded ffmpeg, one folder per tool. Per node
legacy-import.json Record of the one-time copy from the per-user folder earlier builds wrote, so it never repeats. Per node

Four things sit outside it, each by design and each named here so the list is complete:

  • The model directory (LMKIT_MODELS_DIR, separate because it is large, replaceable and shared on a fleet): catalog model files with their sidecars, blobs/ holding the artifacts of imported custom models with the blobs/refs markers each registry leaves on the blobs it uses, and training/ with the workbench's datasets, checkpoints and produced models. ModelWorkDirectory moves blobs/ and training/ to a directory of their own, so the model directory can stay read-only with every model pulled beforehand.
  • A relocated upload directory: FileManagement:UploadDirectory defaults to upload/ under the state directory and moves wherever you point it, which a fleet does (a shared volume). The same holds for every directory a setting relocates (Memory:Directory, Skills:Directory, the ACME store): a relative value resolves under the state directory, an absolute one is honored as given.
  • Scratch: request-scoped temporary files (audio conversion, PDF unlock, OCR staging, the uploads archive) under the system temp directory, deleted when the request ends; and the inference hibernation and offload files under cache/ in the state directory (Inference:ContextHibernationDirectory), cleared at every start. Both are strictly transient: a payload only means anything to the process that wrote it.
  • Claude Desktop's own configuration file: connecting the app from the Claude Desktop page writes claude_desktop_config.json where Claude Desktop keeps it on the machine the server runs on (the local application-data folder on Windows, Application Support on macOS). It is the one file the server writes into another application's space, and it is written only on that explicit action.

Earlier builds kept the request trail, the operator history, the forensics, the certificates, the managed tools and the embedded search databases in a per-user folder instead (LM-Kit/Server under the local application data). The first start of this build copies that folder's content into the state directory once, keyed on the legacy folder so a second folder (another account's) is copied too, records the copy in legacy-import.json, logs it, and never deletes or moves the folder; remove it yourself once the log or lmkit doctor confirms the copy. Two older credential sidecars are adopted the same way: apikeys.json (keys minted before the identity store existed) and admin-2fa.json (the door-global second factor) each move into the identity store once.

2The inventory#

The fourth column is what changes once several nodes run behind one balancer: shared database means the item lives in the admin identity database every node points at; shared volume means it is correct only when every node mounts the same directory; per node means each node keeps its own copy, lost with the node and never visible to its siblings; ephemeral means nothing to back up, mount or share.

Store Where Lifetime and deletion Scope on a fleet
Settings appsettings.json under the state directory The runtime configuration the admin panel reads and writes; readable text an operator can review line by line. Secret values are encrypted in place against the keyring below. Per node. Under LMKIT_MANAGED_CONFIG the manifest owns it and every write refuses; on an unmanaged node a panel edit changes that node alone.
Settings keyring keyring/ under the state directory The keys every encrypted setting is sealed with. A settings file copied without its keyring restores with those values unreadable. Per node. Secrets travel between nodes as environment variables or a secret mount, never as encrypted settings.
Operator identity, embedded admin-identity.db under the state directory Operator accounts, sessions, second factors, lockout state, the security trail, API keys (stored as SHA-256 hashes; the plaintext exists only at creation, shown once), stored responses, this node's own heartbeat row, the domain documents with their per-kind revisions and the leases of single-runner work, when no shared database is configured. Sessions expire on their own; accounts and keys delete from Access; stored responses delete through the Responses API or roll off at its retention cap. Per node: one node's accounts and keys. A fleet configures the shared database in the next row instead.
The identity domain, shared The Admin:Identity database (PostgreSQL, MySQL or SQL Server) you operate Operators, sessions, second factors, lockout budgets, in-flight SSO challenges, the security trail, API keys with their usage counters, stored responses, the token signing secret, the node roster (one heartbeat row per node, swept a day after its last beat), the shared domain documents with their per-kind revisions, and the leases that give single-runner work one runner. Retention follows the same rules as the embedded store; backup and deletion follow your database practice. Shared database: one admin domain for every node on the connection string.
Legacy credential sidecars apikeys.json and admin-2fa.json under the state directory Adopted into the identity store once, at the first start that finds them (section 1). Per node; absent on a fresh install.
Uploaded files upload/ under the state directory by default (FileManagement:UploadDirectory) Swept automatically after MaxFileRetention (default 30 minutes, live-configurable); DELETE /lmkit/v1/files/{id} removes one immediately; a retain-all switch exists for workflows that manage deletion themselves. Shared volume: a file id resolves on every node only when every node mounts the same directory. Left at the default path it is per node.
Request audit trail audit.db under the state directory, bounded by RequestHistoryCapacity (oldest records roll off) Body and response captures are LEADING BYTES only, bounded by the preview settings, and 0 disables capture entirely; textual content only, so uploads are never mirrored into the trail. The operator activity journal shares the file. Per node. Security entries of the journal also land in the shared identity database on a shared store, which is where the domain-wide security trail is read from.
Operator history metrics.db (dashboard resource history) and telemetry-history.db (per-instrument time series) under the state directory Bounded ring stores of process facts, never user content. Per node: each node's own charts. Fleet-wide series are the export path (Observability).
Restart forensics forensics/ under the state directory: running-sentinel.json (heartbeat of the running process), crash-tombstone.json (the exception a dying process leaves), restart-report.json (the current report, kept until acknowledged) and restart-history.jsonl (one line per start) Process facts only, kept until acknowledged or rolled off. Per node.
Certificates certificates/ under the state directory: server-cert.pfx (self-signed, generated on first run and renewed near expiry), operator-uploaded.pfx (uploaded from the TLS panel, used ahead of the self-signed one), the trust-store flags and, by default, the ACME store under acme/. Readable by the server account alone off Windows. Delete a file to regenerate or revert on the next start. Per node: each node terminates with its own material. A fleet terminates TLS at the balancer or mounts one certificate through Https:CertificatePath.
Managed tools tools/ under the state directory Binaries downloaded from the admin panel (ffmpeg); content, not user data, re-downloadable at will. Per node.
Logs logs/server.log under the state directory The capture level is the write floor: entries below it are never recorded, not recorded-then-hidden. Per node.
Agent memory The admin identity database, as the memory-facts shared objects: one document per store and memory id, holding the serialized memory with the embedding model it was written under; the memories/ files earlier builds wrote under the state directory seed an empty domain once and are inert afterwards Facts persist until deleted: per-fact deletion and consolidation from the admin surface, which is the data-subject-request path and removes the fact for every node. Shared database: a fact remembered through one node is recalled through every node from the next exchange on. The legacy files are ephemeral.
Skills The admin identity database, as the skills-content shared objects (one document per skill, holding its files); skills/ under the state directory (Skills:Directory) is this node's materialized copy, the revision each folder holds recorded beside it Plain folders you can read and edit like files, because they are files; every edit is published to the shared document. Shared database: a skill authored on any node serves on every node within the sync period; the folder is a per-node cache (Agent Skills).
Custom-model registry The records live in the admin identity database as the custom-models shared objects; models-registry.id under the state directory is the identity this node marks its blobs with, and models-registry.json is the file earlier builds wrote, read once as the seed of an empty domain and inert afterwards The records of imported models (name, artifact, profile, provenance) with artifact paths stored relative to the model directory; a record deletes from the Models section, which reclaims only blobs nothing references any more. Shared database: an import on any node resolves on every node. The identity sidecar is per node; the legacy file is ephemeral.
Setup state setup-state.json under the state directory Which setup paths completed on this installation, and nothing more; never a secret or a setting. Per node.
Search indexes Embedded per-cluster SQLite databases under search-embedded/ in the state directory (the default cluster included) or under the cluster's own data directory when one is configured, or an EXTERNAL database you operate (PostgreSQL and friends) Deletion is first-class: collections and tenants delete through the Search API; external databases follow your own operational policy. Embedded: per node, one node's file. External: your engine, reached by every node with the same connection string; a node carrying a fleet signal never provisions an embedded cluster (Storage Engines and Deployment).
Models The model directory (LMKIT_MODELS_DIR overrides), which must stay writable: models download into it on the first request that needs them, and a read-only mount refuses those requests with model_store_read_only Downloaded model files; delete from the admin Models section. Content, not user data. Shared volume: models download once for the fleet under a cross-process lock, and a deletion affects every node.
Training artifacts training/ under the work directory (the model directory unless ModelWorkDirectory names another) Datasets you provided, checkpoints and the models you produced, journaled per job; yours to keep or delete. Shared volume for the files; the job registry that reports on them is per node (see the in-memory row).
Inference state cache/ under the state directory (Inference:ContextHibernationDirectory) Strictly transient: a payload only means anything to the engine that wrote it, and the directory is cleared at start. Ephemeral.
Request scratch The system temp directory Working copies of media and documents during one request, deleted when it ends. Ephemeral.
Legacy import marker legacy-import.json under the state directory Record of the one-time copy from the per-user folder earlier builds wrote, so it never repeats. Per node.
Node-bound in-memory surfaces Memory only, never disk Chat-with-document sessions and the Playground document chat (expire after the configured idle time), the MCP event streams (progress reaches the stream open on the node running the call), the results of async jobs too large for their record (held one hour after completion), and the training job registry. All gone on restart. Per node, never shared: a session id is answered only by the node that minted it, and so is an oversized job result (Scaling Out says how to route for that).
PII detection areas Beside the file in the upload directory (<file id>_<stamp>.pii-areas in the owner's bucket), for thirty minutes The positioned areas document_detect_pii found, read back by document_redact and the review card; removed with the file, hidden from the upload listings. Shared volume: a redaction after detection works on any node (MCP Server).
Grounded chat sessions The admin identity database, as the search-chat-sessions shared objects: one record per session (scope, defaults, activity and the serialized conversation history), swept when idle The session contract in Grounded Answers; nothing to manage. Shared database: a turn on any node rebuilds the conversation from the recorded history; the idle timeout counts the whole farm.
Search control-plane generation The admin identity database, as the search-control-plane shared objects: one counter per search cluster, advanced by every control-plane write (a tenant setting, a collection created, configured or deleted) Bookkeeping for the caches each node keeps of a cluster's tenants and collections; nothing to manage. Shared database: a write on one node drops the other nodes' cached entries for that cluster within the sync period, and every entry expires within thirty seconds regardless (Storage Engines and Deployment).
Search maintenance signals The admin identity database, as the search-deletions, search-partition-resets and search-preemptions shared objects: one per search cluster and tenant, holding the deletions the orphan sweep still has to reconcile, a partition rebuild in flight with its wipe generation, and the deletions in progress that preempt the re-embed worker Bookkeeping of the Search maintenance; nothing to manage. Shared database: whichever node runs a cluster's sweep drains what every node deleted, a deletion on any node preempts the tenant's re-embed wherever it runs, and a rebuild in flight parks the tenant on every node (Storage Engines and Deployment).
MCP file ingest roots The directories Mcp:FileIngestRoots names, wherever they point The folders file_ingest may read by path; open exactly the folders you work from (MCP Server). Per node unless every node mounts one shared volume at the same path; the security audit flags a root under the state directory or a relative one.
MCP sessions The admin identity database, as the mcp-sessions shared objects: one record per session (owner, client, protocol version, activity), swept when idle The session contract in MCP Server; nothing to manage. Shared database: any node serves a session another node initialized; the cap and the idle timeout count the whole farm.
Async job records The admin identity database, as the jobs shared objects: one record per job (owner, operation, status, progress, outcome and the result up to 4 MiB), removed an hour after the job ended The job contract in Errors, Retries, and Jobs; nothing to manage. Shared database: any node polls and cancels a job, and a restart of the running node closes its jobs as lost instead of losing them silently.

Two general rules ride across every row. Retention settings are read LIVE, so tightening a policy applies on the next sweep without a restart. And nothing above is hidden state: every store is a file or folder an operator can inspect with ordinary tools, or a database you already know how to open.

On a load-balanced fleet the map shifts, and only partly: operator identity, API keys and stored responses move into the shared admin database (Admin:Identity), uploads and models onto shared volumes, and search onto external engines, so that part of the truth lives where your database and storage practice already governs it. What each node's state directory keeps is more than its operator history: the settings file and the keyring it is sealed with, its TLS material, skills/ (this node's materialized copy of the shared skills), the registry identity its blob markers carry (models-registry.id) and setup-state.json, beside the request trail, the metrics and telemetry history, the forensics and the logs. The identity database holds the rest, the custom-model records, the agent memories and the skills included, and the shared volumes hold the model bytes. Scaling Out owns what that means for routing, setup and the environment every node needs.

3What can leave the machine, exhaustively#

By default: nothing. Prompts, documents, extractions, memory facts, and search content are processed and stored locally, full stop. Bytes leave only through channels an operator explicitly configures, and each is individually controllable:

  1. Model downloads: pulling a model from the catalog fetches it from its hosting repository. Air-gapped deployments pre-place files in the model directory instead.
  2. Web-reaching tools: web search and HTTP tools run under the egress policy: a mode plus an allowlist, so "the agent can reach the web" is a decision with a scope, not a default.
  3. MCP connectors: tool calls to the external MCP servers you attach carry whatever arguments the exchange produces; attach only endpoints you trust with that.
  4. Telemetry export: metrics flow to YOUR OTLP or Prometheus endpoints only when telemetry export is enabled; the admin panel's own view works without any export.
  5. SSO: when admin SSO is enabled, the OIDC exchange talks to your identity provider, and to nothing else.

There is no sixth channel: no usage phoning home, no license pings carrying content, no background "improvement" uploads. If the machine's firewall blocks everything outbound, the server still serves everything local.

4The disposal story#

Decommissioning a server or answering "forget this person" is mechanical because every store has a named path: delete the memory facts (per fact or per memory id), delete the tenant's search collections, delete uploaded files (or wait out retention), let job records expire, and finally remove the state directory itself. On a fleet the same steps have a reach to state: a memory forget runs on every node, because each node's memories/ holds the facts it extracted, while the tenant's search collections delete once in the external engine every node reaches, and the shared identity database and volumes are disposed of through the practice that governs them. The security model covers who is allowed to do each of these.

5Stated plainly#

  • The state directory holds everything this node writes, with the model directory, a relocated upload directory, scratch files and Claude Desktop's own configuration file as the named exceptions; back it up to keep the node, wipe it to dispose of the node.
  • Every store has a stated lifetime and a deletion path; the shortest-lived data (uploads) cleans itself up in minutes by default.
  • On a fleet the identity database and the shared volumes hold the shared truth, and each node's directory still keeps its settings, keyring, TLS material, memories, skills, custom-model registry, setup state and operator history.
  • Exactly five channels can send bytes out, all opt-in, all scoped; a default install sends nothing anywhere.