Getting started
This walks one repo from having no Lattice config to a task that runs once and
comes back from cache on the next run. It assumes lattice is already on your
PATH — see Installation if it isn’t.
Scaffold a config
In the root of your repo, run:
lattice init
On a terminal, init opens a short interactive wizard: it asks whether you
need a build tool, a toolchain manager, or both, then walks you through adding
workspaces (name, path, whether to auto-detect the engine and tasks) and, for
the toolchain half, which well-known engines to pin and what version
constraint to use. Answer n to auto-detection for a workspace and it asks you
to pick an engine and constraint for that workspace directly. Piped output or a
non-interactive shell skips all of that.
To skip the prompts on a terminal too, pass -y:
lattice init -y
✓ wrote lattice.json
✓ wrote .lattice/schema.json
✓ updated .gitignore
next: lattice run build
Three things landed:
lattice.json— the config, with zero workspaces and one starter task..lattice/schema.json— a committed JSON Schema so your editor can validatelattice.jsonas you type. It’s written once and left alone after that; delete it and the next command rewrites it..gitignore— three lines appended (existing content is untouched):.lattice/cache/,.lattice/toolchains/,.lattice/bin/. Everything under.lattice/other thanschema.jsonis a per-machine artifact.
Running init again refuses to touch an existing lattice.json unless you add
--force.
Read what it wrote
{
"$schema": ".lattice/schema.json",
"latticeVersion": "1.0.0-beta-2",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
},
"workspaces": []
}
$schemapoints at the committed schema file, for editor validation.latticeVersionpins the config to the Lattice release that scaffolded it. See Upgrading for what happens when the installed binary and this field disagree.workspacesis empty. A workspace is a project directory declared by a literal path — no globs — and it’s the unit Lattice runs and caches tasks in. See Workspaces.tasks.buildis a starter task definition:dependsOn: ["^build"]means “run this workspace’s dependencies’buildfirst”;outputs: ["dist/**"]tells the cache which files to capture. There’s no workspace to run it in yet, so it does nothing until you add one.
Confirm that by running it as-is:
lattice run build
lattice: no workspaces declared. Add them to the `workspaces` array in
lattice.json to run `build`.
Exit code 0 — an empty repo isn’t a failure, just nothing to do yet.
Add a workspace and a task
Add a directory with something to build, and declare it as a workspace:
mkdir -p app/src
echo hello > app/src/index.txt
Edit lattice.json:
{
"$schema": ".lattice/schema.json",
"latticeVersion": "1.0.0-beta-2",
"workspaces": [
{
"name": "app",
"path": "app",
"auto": false,
"scripts": { "build": "mkdir -p dist && cp src/index.txt dist/index.txt" }
}
],
"tasks": {
"build": {
"inputs": ["src/**/*"],
"outputs": ["dist/**"]
}
}
}
auto: false opts this workspace out of driver detection: instead of Lattice
reading a lockfile or manifest to infer a command, scripts.build is the exact
command that runs. This is the fastest way to see a real run without a
language toolchain in the picture — see
Driver detection for how auto (the default) infers
commands from evidence already in the directory instead. The task’s inputs
list is new too: it’s what the cache hashes to decide whether app’s build
needs to run again.
Provision and install
lattice setup
❖ lattice setup
❖ setup complete
setup provisions any pinned toolchains this repo’s engines declare (none,
in this example) and installs each workspace’s native dependencies before you
run anything. It’s safe to run again — a workspace whose lockfile hasn’t
changed is skipped unless you pass --force. See
Engines and provisioning for what happens once an
engine constraint is declared.
Run the task
lattice run build -l
lattice: running `build` across 1 workspace(s)
lattice: app:build: hash 8aecd62e96682197
lattice: app:build: cache miss
app:build: running
app:build: done (0.01s)
lattice: 1 tasks, 0 cached, 0 failed, 0.01s
app/dist/index.txt now exists. -l (--loquacious) prints this plain,
line-by-line log; on a terminal without it you get a live interactive display
instead, both driven from the same events — see
Output and logging.
Run it again
Nothing changed under app/src, so the second run doesn’t execute the command
at all:
lattice run build -l
lattice: running `build` across 1 workspace(s)
lattice: app:build: hash 8aecd62e96682197
app:build: cache hit [8aecd62e]
lattice: 1 tasks, 1 cached, 0 failed, 0.00s
Same hash as the cold run, so Lattice restores app/dist from
.lattice/cache/ instead of re-running scripts.build. Delete app/dist and
run again — it comes back from the same cache entry without rebuilding.
Edit app/src/index.txt and the hash changes, so the next run is a miss
again. That hash is computed over the task’s command, its inputs, its
resolved environment, and more; see Caching for
exactly what goes in and what makes a cached result valid on restore.
Next
- Workspaces — what a workspace is and how
discovery,
path, anddependsOnwork. - Task graph — how tasks expand across
workspaces,
^taskvs.task, and parallelism. - Caching — the full model behind the cache hit you just saw.