CLI reference
Lithos has six subcommands. For flag-level detail, run lithos --help
or lithos <subcommand> --help.
All commands accept a positional PROJECT argument. If omitted, Lithos
searches the current directory — see
Configuration → file resolution.
| Command | Purpose |
|---|---|
deploy | Reconcile state with config and apply the diff. |
diff | Print the diff without applying it. |
undo | Restore the last recorded checkpoint for an environment. |
outputs | Print the outputs of the last deploy as JSON, YAML, or importable modules. |
destroy | Remove every resource Lithos manages for an environment. |
import | Adopt an existing experience into a Lithos project. |
deploy
lithos deploy [PROJECT] --environment <label> [flags]deploy is the normal workflow: load config and state, reconcile them
against Roblox, run preflight, show a plan, checkpoint the current graph,
and apply the diff in dependency order.
Live reconciliation
Before diffing, deploy checks that the resources recorded in state still
exist. Each one ends up verified, missing, skipped, or unknown.
missing: drop it from state so the next plan recreates it.unknown: keep it in state so the deploy fails safe on transient API trouble.
Lithos currently verifies experiences, places, game passes, and developer products directly. Sub-resources are inferred from their parent or skipped.
Plan preview and confirmation
Before apply, Lithos prints a structured preview of creates, updates, deletes, noops, and skips. Riskier resources show field-level summaries when possible, and destructive operations are marked explicitly.
Interactive terminals prompt for confirmation. Non-interactive stdout auto-approves after printing a plain summary so existing scripts keep working.
Preflight diagnostics and checkpoints
Preflight catches the common Roblox failures before apply: missing Open
Cloud keys, missing universe-places.write, wrong universe scope,
unsupported access combinations, and oversized place files.
If preflight passes, Lithos records a checkpoint of the current environment
so lithos undo has a baseline.
Useful flags
| Flag | Effect |
|---|---|
--environment <label> / -e | Required. Which environment block to apply. |
--yes / -y | Skip the confirmation prompt and apply immediately. |
--no-preview | Skip the preview entirely. Implies --yes. |
--plain-preview | Render a plain (non-colored) summary. Useful in CI log viewers without ANSI support. |
--allow-purchases | Allow paid-asset operations (developer products, etc.) without an extra confirm. |
Avoid --no-preview unless the pipeline already gives you enough
confidence in the diff.
diff
lithos diff [PROJECT] --environment <label> [--live]diff prints the plan without applying it. By default it is offline and
compares config to persisted state.
Use --live to run the same reconciliation pass as deploy first:
lithos diff --environment dev --liveUse plain diff for config-only review. Use --live when you suspect
drift.
undo
lithos undo [PROJECT] --environment <label> [flags]undo rolls an environment back toward its most recent checkpoint. It does
not read old YAML or Git history. Instead it:
- Loads the baseline snapshot stored before the last deploy or undo.
- Imports the live Roblox experience so rollback plans against reality, not stale state.
- Runs the same preflight diagnostics and plan preview as
deploy. - Applies the diff back toward that snapshot and records the result.
Use the same preview flags as deploy: --yes, --no-preview, and
--plain-preview. --allow-purchases is also supported.
Roblox deploys are not transactional. undo reconciles live state and
then drives it back toward the last checkpoint Lithos recorded.
outputs
lithos outputs [PROJECT] --environment <label> [--output <file>] [--format <format>] [--roblox-ts]outputs prints the last deploy's outputs. Stdout defaults to JSON.
--outputending in.luaor.luauimplies Luau.--formatacceptsjson,yaml,yml,lua, andluau.--roblox-tswrites a.d.tssidecar next to a Luau output.
You can also move those defaults into project config:
outputs:
writeDir: src/shared/generated
outputName: lithosOutputs
format: luau
robloxTs: trueThe codegen alias with snake_case also works:
codegen:
write_dir: src/shared/generated
output_name: lithosOutputs
format: luau
typescript: trueRules to know:
- Use either
pathorwriteDir+outputName, not both. - If
outputNamehas no extension, Lithos adds one fromformat. - If
robloxTs/typescriptis enabled andformatis omitted, Lithos defaults to.luau. - CLI flags override config values.
With either config, this is enough:
lithos outputs --environment devAfter deploying the getting-started example (opens in a new tab), default JSON output looks like:
{
"experience_singleton": {
"experience": {
"assetId": 3296599132,
"startPlaceId": 8667346609
}
},
"place_start": {
"place": { "assetId": 8667346609 }
},
"placeFile_start": {
"placeFile": { "version": 2 }
}
}To require outputs from game code, write a Luau module:
lithos outputs --environment dev --output src/shared/generated/lithosOutputs.luaulocal ReplicatedStorage = game:GetService("ReplicatedStorage")
local outputs = require(ReplicatedStorage.shared.generated.lithosOutputs)
local startPlaceId = outputs.experience_singleton.experience.startPlaceId
local placeVersion = outputs.placeFile_start.placeFile.versionFor roblox-ts, add --roblox-ts so Lithos also writes
lithosOutputs.d.ts beside it:
lithos outputs --environment dev --output src/shared/generated/lithosOutputs.luau --roblox-tsimport outputs from "shared/generated/lithosOutputs";
const startPlaceId = outputs.experience_singleton.experience.startPlaceId;
const placeVersion = outputs.placeFile_start.placeFile.version;destroy
lithos destroy [PROJECT] --environment <label> [--yes]destroy applies a full delete plan for the environment. It uses the same
preview, confirmation, and dependency ordering as deploy.
From Lithos's point of view, destroy is final: state is wiped. Roblox
usually archives the assets instead of hard-deleting them.
import
lithos import [PROJECT] --environment <label> --target-id <experience-id>import adopts an existing Roblox experience into a Lithos project. Use it
when the experience already exists and you want Lithos to manage it.
import is experimental. It does not match every existing resource to a
configured one, so many resources will be re-created on the next deploy.
Test it on staging before you point it at production.
A safer pattern is to mirror production into a staging environment first,
verify that the diff is empty, and only then import production.
Exit codes
| Code | Meaning |
|---|---|
0 | Success. Includes the case "nothing to do." |
1 | A user-facing failure. Bad config, auth failure, apply failure, conflicting state, etc. The error message names the cause. |
2 | The command was cancelled at the preview / confirmation step. |
In CI, treat any non-zero exit as failure.