Lock Files¶
The installer maintains two complementary lock files in every project to record exactly what was deployed and which versions are in use. Together they make project setups fully reproducible.
Overview¶
File |
Location |
Owned by |
Purpose |
|---|---|---|---|
Cube project lock |
|
|
Records every bundle reference — context bundles and their tool dependencies — with exact resolved versions |
Services lock |
|
Installer |
Records deployed context service state, deployment target, ownership, paths, and hashes for managed files |
The two files are separate by design: bundle version resolution is the cube bundle manager’s
responsibility (.settings/bundles-lock.store.json, at the project top folder), while service
selection is the installer’s (services-lock.json).
Cube project lock¶
The Cube project lock is created and updated by the cube bundle manager every time you run a
command that adds a context to a project (project-add, project-deploy,
project-deploy-installed). You never edit it directly. It lives at the project top folder
(<project>/.settings/), the same location any other Cube-aware tool (such as an IDE) uses, so a
project only ever has one Cube bundle lock.
It records:
Every context bundle added to the project, with the exact resolved version, except the bundles excluded from the Cube project lock (see below).
Every tool bundle installed as a transitive dependency of a context, with the exact resolved version and platform.
This is the file that drives reproducible replay: when you run project-deploy --preset with
a lock exported by project-lock-show, the installer uses the exact version list
from the lock to restore the environment on a new machine or project folder.
Bundles excluded from the Cube project lock¶
cube runs a command with the bundle version recorded in the Cube project lock of the current
folder. If the installer bundle (cube-agentic-ai-installer) were recorded there, every
cube agentic-ai ... started inside the project would keep running that old installer, even after
cube bundle update cube-agentic-ai-installer reports “Everything is up to date.”
The installer therefore never records the bundles listed in its cube-project-lock-exclusions.json
data file in the Cube project lock. Today the list contains only cube-agentic-ai-installer.
These bundles are still deployed normally and are tracked only in services-lock.json, with the
installed version used for the deployment.
project-addreportscubeProjectLockStatusin its JSON output:RECORDEDorEXCLUDED.project-lock-showlists an excluded bundle as aconnectorwith its services-lock version and raises noCONNECTOR_MISSING_FROM_RESOLVED_LOCKwarning for it.A project with only excluded bundles deployed has no
.settings/Cube lock.
Projects with a legacy Cube lock¶
Projects deployed by an older installer version may still have their own Cube bundle lock under
<project>/.cube-ai/.settings/bundles.store.json. This legacy layout is no longer supported:
project-add, project-remove, and project-lock-show fail fast with
LEGACY_CUBE_PROJECT_LOCK_UNSUPPORTED instead of silently reconciling it with the shared
.settings/ lock. Reconcile the bundle references into <project>/.settings/bundles.store.json
(or remove the legacy folder once its references are reflected there) before re-running the
command.
Services lock (services-lock.json)¶
The services lock is created by the installer on the first project-add or project-deploy
invocation and updated on every subsequent deployment. It is a JSON file.
It records, for each deployed context bundle:
The exact bundle version that was deployed (taken from the Cube project lock, or the installed version for bundles excluded from it).
The service IDs that were selected for deployment.
The
selectedServiceProvenanceentry for each service, tagged with|requiredor|optionalaccording to the bundle manifest.The effective deployment target (
ide,agenticSystem,fileFamily) at the time of deployment.The per-service managed artifact records, including identity, destination, version, and hash (used by
project-removeand collision preflight).The logical owner, source, destination, kind, and SHA-256 content hash of each managed artifact.
MCP server ownership records, including the project manifest path, server-map key path, server name, and whether the installer introduced the key.
The timestamp of the last deployment.
The recorded tag is used during partial project-remove operations. If a requested removal
includes a |required service and leaves another service from the same context deployed, the
user must explicitly confirm because the remaining services may be impeded. Full bundle removal,
or removal of all deployed services, does not require confirmation. This tag is not a dependency
graph and does not identify which remaining service might be affected. For backward compatibility,
an untagged legacy provenance entry is treated as |optional (required: false).
Service merge behavior:
The services lock stores the current selected-services set per bundle.
If you run
project-addorproject-deploymultiple times for the same bundle with different service selections, newly selected services are merged with the existing entry.project-lock-showtherefore reflects the current merged deployment status for each context bundle.
Managed artifact replay and conflicts¶
When a deployment encounters an existing destination, the installer consults
services-lock.json before reporting a conflict:
An unchanged artifact owned by the same logical context service and artifact may be replaced. The installer logs an informational update and considers the artifact deployed.
A destination owned by another context is rejected with
ARTIFACT_CROSS_CONNECTOR_CONFLICT.A destination claimed by another incoming artifact is rejected with
ARTIFACT_DUPLICATE_DESTINATION.A destination not present in the services lock is rejected with
ARTIFACT_USER_OWNED_CONFLICT.A destination owned by another service or artifact in the same context is rejected with
ARTIFACT_CONNECTOR_SERVICE_CONFLICT.An installer-managed file whose current contents differ from its recorded hash is rejected with
ARTIFACT_CONTENT_HASH_MISMATCHonly when the incoming service version is the same as the recorded version. A different version of the same logical service is treated as an intentional upgrade and may replace the previous artifact.
This makes preset replay idempotent for unchanged installer-managed artifacts while protecting user files and context boundaries. The lock records the hash and writing version of the bytes last written by the installer. It does not claim ownership of manually created files.
Ownership-aware replay requires services-lock schema 1.1.0. Older or unknown lock schemas must be
replaced through a clean deployment before replay. The installer does not infer ownership or hashes
from legacy path-only records.
project-remove behavior with lock authority:
project-removeusesservices-lock.jsonas the project source of truth to determine which services are currently deployed for a context.The command removes installer-managed deployment artifacts derived from that lock state.
MCP keys are removed from recorded manifests only when the lock marks them installer-owned and no remaining service or bundle owns the same key. The source bundle is not required to be installed for this cleanup.
Legacy locks without MCP ownership records leave MCP keys unchanged.
Manually added services/files that were not deployed through installer commands are outside lock tracking and are not removed automatically.
The command does not perform a consistency audit between
services-lock.jsonand bundle manifest files before removal.Removal is project-scoped: machine-installed bundles remain installed. Use
cube bundle removeonly for machine-level uninstall operations.
The services lock is the commit marker: its presence and currency signals that deployment completed successfully. A missing or stale entry indicates an interrupted deployment.
Tainted services-lock concept¶
In rare remove-time I/O failures with partial deletion, the installer can mark
services-lock.jsonas tainted (integrity.state = UNRELIABLE).The installer can also set this marker when lock-source drift is detected (for example context version mismatch between
services-lock.jsonand the Cube resolved lock view).A tainted services lock means project state may be unstable and requires extra care for subsequent mutating commands.
Mutating commands still run, but emit warning information indicating the unreliable lock state.
Inspecting the services lock¶
Use project-lock-show to display the full project lock state as preset-compatible
machine-readable JSON:
cube agentic-ai project-lock-show <project_top_folder>
The output includes both context entries and tool dependency entries. For multi-service contexts, selected services are explicitly listed.
Reproducing a project environment¶
Committing lock files to source control (recommended)¶
The simplest and most reliable way to reproduce a project environment is to commit both lock files to your source control repository:
.settings/bundles-lock.store.json ← Cube bundle versions (project top folder)
.cube-ai/services-lock.json ← Service selections + deployment target + managed artifact ownership
On a new machine or after a fresh clone, if you also commit the deployed service artifacts (skills, agents, instructions, prompts, MCP config, routing catalog), only the machine-level bundle installs need restoring:
# Restore bundle installs on the machine (reads the Cube project lock)
cube --cwd <project_top_folder> bundle install --project
# Install what the contexts need on this machine (Python packages, tool bundles)
cube agentic-ai doctor <project_top_folder> --fix
The project files are already present from the clone, and the Cube wrapper re-installs the exact
bundle versions recorded in the lock. The requirements that contexts declare are not in either lock:
doctor --fix resolves them for this machine and lists the rest, such as VS Code extensions.
Do not commit .cube-ai/esw-python/: it records the Python chosen on one machine, which can be an
absolute path that another machine does not have. Without it, doctor --fix applies the default
choice (auto). setup does not run in a cloned project, which is already deployed.
Bundles excluded from the Cube project lock, including the installer, are not restored by that command. Install them separately when needed. Their deployed project files remain in the clone.
If the deployed artifacts are not committed (e.g. they are gitignored), add a second step to redeploy them:
# Export a preset from the source project, then replay it
cube agentic-ai project-lock-show <project_top_folder> > my-preset.json
cube agentic-ai project-deploy <project_top_folder> --preset my-preset.json
Default preset replay reconciles a context’s selected services to its preset bundle version. Add
--preset-no-reconcile to preserve mixed-version service provenance exactly. Replay is additive:
services already present in the destination but absent from the preset are not removed automatically.
services-lock.json contains the context bundle versions, service selections, deployment
target, and managed artifact ownership. However, it does not match the preset file
schema and does not record tool dependency versions — those are captured only in the Cube
project lock. Use project-lock-show output as the preset source for project-deploy --preset.
When to use project-lock-show exported preset instead¶
If your team works across different operating systems or if a context declares a version range for one of its tool dependencies (rather than an exact version), re-resolving on a different machine could theoretically pick a different tool version.
In that case, export an explicit preset that locks tool versions verbatim:
# On the source machine
cube agentic-ai project-lock-show <project_top_folder> > my-preset.json
# On the target machine
cube agentic-ai project-deploy <new_project_folder> --preset my-preset.json
The exported preset adds explicit "kind": "tool-dependency" entries with exact versions, so
the Cube wrapper installs those specific versions rather than re-resolving from the network.
Preset target fields and deploy behavior:
If the exported preset contains unambiguous top-level
ide,agentic-system, andcanonical,project-deploy --presetuses them when no explicit target flags are passed.If those target fields are missing or ambiguous in the preset, pass explicit target flags (
--ide,--agentic-system, and optionally--canonical).If target flags are not passed and preset target fields are absent, deployment continues with normal target resolution (
--autodetect-targets enforcecan apply detected values; otherwise ST defaults are used).
For most teams on the same platform, committing both lock files and using cube bundle install --project to restore the Cube project lock is the simplest and most reliable path. The
exported preset is the right choice when you need a single portable file to share across
machines, platforms, or Cube versions.
Key rules¶
Never edit lock files manually. All mutations go through installer commands.
Commit both lock files to source control so every team member and CI pipeline can reproduce the environment without re-running interactive prompts.
Absence of
services-lock.jsonin a project means no installer deployment has completed yet. Runproject-addorproject-deployto initialise it.