@lizard-build/cli 4.0.45 → 4.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/add.js +2 -7
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/agents.js +21 -2
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/domain.js +32 -2
- package/dist/commands/domain.js.map +1 -1
- package/dist/commands/init.js +15 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/metrics.js +11 -2
- package/dist/commands/metrics.js.map +1 -1
- package/dist/commands/redeploy.js +1 -1
- package/dist/commands/redeploy.js.map +1 -1
- package/dist/commands/s3.d.ts +15 -0
- package/dist/commands/s3.js +59 -0
- package/dist/commands/s3.js.map +1 -1
- package/dist/commands/sandbox.js +13 -5
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/up.js +23 -6
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/upgrade.js +20 -5
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/volume.js +38 -4
- package/dist/commands/volume.js.map +1 -1
- package/dist/commands/workspace.js +4 -7
- package/dist/commands/workspace.js.map +1 -1
- package/dist/lib/api.js +21 -6
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +10 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/default-project.js +7 -2
- package/dist/lib/default-project.js.map +1 -1
- package/dist/lib/skills-data.generated.js +4 -4
- package/dist/lib/skills-data.generated.js.map +1 -1
- package/dist/lib/updater.d.ts +1 -1
- package/dist/lib/updater.js +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +98 -74
- package/skill-data/core/references/deploys.md +41 -30
- package/skill-data/core/references/sandboxes.md +43 -18
- package/skill-data/core/references/sdk.md +33 -21
- package/src/commands/add.ts +2 -6
- package/src/commands/agents.ts +20 -4
- package/src/commands/domain.ts +36 -2
- package/src/commands/init.ts +18 -0
- package/src/commands/metrics.ts +11 -2
- package/src/commands/redeploy.ts +1 -1
- package/src/commands/s3.ts +65 -0
- package/src/commands/sandbox.ts +15 -5
- package/src/commands/up.ts +20 -6
- package/src/commands/upgrade.ts +17 -4
- package/src/commands/volume.ts +35 -4
- package/src/commands/workspace.ts +4 -9
- package/src/lib/api.ts +21 -6
- package/src/lib/config.ts +11 -1
- package/src/lib/default-project.ts +5 -2
- package/src/lib/updater.ts +1 -1
- package/test/unit/default-project.test.ts +8 -2
- package/test/unit/s3-presign.test.ts +32 -0
- package/test/unit/sandbox-transport.test.ts +5 -1
- package/test/unit/sandbox.test.ts +1 -0
package/skill-data/core/SKILL.md
CHANGED
|
@@ -19,15 +19,16 @@ If `$ARGUMENTS` is non-empty, treat it as the user's request and act on it. If e
|
|
|
19
19
|
|
|
20
20
|
## Execution rules
|
|
21
21
|
|
|
22
|
-
1. Prefer the `lizard` CLI.
|
|
22
|
+
1. Prefer the `lizard` CLI. Don't call the Lizard HTTP API yourself; for something the CLI does not expose, ask the user. Using a database, S3 or a deployed app through its own URL and credentials is fine.
|
|
23
23
|
2. Always pass `--json` on non-interactive calls. The CLI also switches to JSON by itself when stdout isn't a TTY.
|
|
24
24
|
3. For an unfamiliar command, run `lizard <cmd> --help --json` first: never guess flag shapes. See [Discovery](#discovery).
|
|
25
|
-
4. Resolve context before any change: `lizard status` shows
|
|
26
|
-
5.
|
|
25
|
+
4. Resolve context before any change: `lizard status --json` shows whether this exact folder is linked. `linked: false` means commands go to the [default project](#default-project); pass `--project` when it matters. Confirm the project, service or sandbox you target.
|
|
26
|
+
5. A network error (`fetch failed`, `UND_ERR_SOCKET`, `ECONNRESET`) is not an answer: run the command again. Before repeating a create, check with `list` / `ps` that the first attempt did not land.
|
|
27
|
+
6. For destructive actions (delete a service, sandbox, volume or project, drop an addon, overwrite a project-wide secret, restart production), confirm with the user first. Without a terminal the CLI never asks: `sandbox rm`, `volume delete`, `keys delete` and `workspace rm` delete at once; `service`, `project`, `secrets` and `domain` deletes and billing changes refuse until you add `-y`. Add `-y` only after the user agrees.
|
|
27
28
|
|
|
28
29
|
## Deploy command output
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
`lizard up --json` (without `--detach`) prints one JSON event per line: `{ event: "log", line }` while it builds, then `{ event: "done" }`, or `{ event: "error", message }` and exit `1`. When the service runs, it ends with `{ event: "deployed", status: "running", url }`. No `deployed` event and exit `0` means the build finished but the service is not running: read `lizard logs --restart latest --json` and `lizard up status <appId> --json` (`status`, `deployStatus`). `lizard up --detach --json` prints `{ appId, status: "deploying" }` once. A brand-new URL can answer `404` (a plain nginx page) or fail with `curl: (16) Error in the HTTP2 framing layer` for up to a minute while its route is set up: wait and retry before you debug the app. `lizard logs --json` is **not** a stream: it returns the last 200 lines (override with `--tail N`, max 1000) and exits — do not wait on it expecting more. Need a specific incident? Use `--restart latest` or `--restart <id>`. Only stream logs without `--json` if the user actively wants a live tail.
|
|
31
32
|
|
|
32
33
|
## Mental model
|
|
33
34
|
|
|
@@ -39,13 +40,13 @@ workspace → project → services, sandboxes, managed addons, volumes
|
|
|
39
40
|
- Project — group of related services and sandboxes in one workspace. The cwd gets linked to a project (config at `~/.lizard/config.json`).
|
|
40
41
|
- Service — a deployable unit. Source is either a git repo (`sourceType=github`) or an uploaded tarball (`sourceType=upload`).
|
|
41
42
|
- Sandbox — a short-lived Linux machine (Firecracker microVM) for running code and agents. See [Sandboxes](#sandboxes).
|
|
42
|
-
- Volume — persistent disk for sandboxes, mounted at `/
|
|
43
|
+
- Volume — persistent disk: for sandboxes (mounted at `/workspace`), or one per service (`lizard volume create <name> --service <svc>`, mounted at `/data` by default).
|
|
43
44
|
- Managed addons — `postgres`, `redis`, `s3`. Provisioned with `lizard add <type>`; `s3` ships with a private bucket named `default`. See [Databases and storage](#databases-and-storage) for the env vars each type exposes.
|
|
44
|
-
- Cross-resource refs — `${{<name>.<KEY>}}` resolves at deploy time against the target's merged env. A ref to a missing target or key resolves to an empty string and does NOT fail the deploy (only circular refs throw). After wiring refs, deploy and check `lizard logs --build --service <svc>`: the build log warns about every reference that came back empty. `lizard secrets list --service <svc> --
|
|
45
|
+
- Cross-resource refs — `${{<name>.<KEY>}}` resolves at deploy time against the target's merged env. A ref to a missing target or key resolves to an empty string and does NOT fail the deploy (only circular refs throw). After wiring refs, deploy and check `lizard logs --build --service <svc>`: the build log warns about every reference that came back empty. `lizard secrets list --ref --service <svc> --json` lists the references that resolve. Refs match the target's current name, so renaming the target breaks them: update them after a rename.
|
|
45
46
|
|
|
46
47
|
## Discovery
|
|
47
48
|
|
|
48
|
-
The CLI has
|
|
49
|
+
The CLI has about 37 commands. Discover at runtime:
|
|
49
50
|
|
|
50
51
|
```
|
|
51
52
|
lizard --help --json # root + all commands + global flags + exit codes
|
|
@@ -53,33 +54,38 @@ lizard <cmd> --help --json # specific command schema
|
|
|
53
54
|
lizard <cmd> <sub> --help --json # nested (e.g. `lizard service set --help --json`)
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
Returns `{ cli, version, command: { arguments, options, subcommands }, globalOptions, exitCodes }`.
|
|
57
|
+
Returns `{ cli, version, agents, command: { arguments, options, subcommands }, globalOptions, exitCodes }`.
|
|
57
58
|
|
|
58
59
|
## Sign-in
|
|
59
60
|
|
|
60
61
|
Every command that needs an account checks the sign-in first. Without one, in JSON mode it fails with exit code `2` and `error.code: "NOT_AUTHENTICATED"`, and `error.body.login` holds what you need to get the user signed in. `lizard login --json` prints the same object at the top level. It never waits and never opens a browser:
|
|
61
62
|
|
|
62
63
|
- `status: "pending"`: `authUrls` holds one link per sign-in method (`github`, `google`), and `authUrl` the one to use when only one applies. Ask the user how they sign in to Lizard and give them that link as a clickable URL. Someone with an account must use the same method as before: another method opens a second, empty account unless both share a verified email. Once they say the browser shows "CLI authorized", run the same command again (`nextCommand` when present); it picks the sign-in up. A link lasts 5 minutes; the next run prints a new one. Follow `instruction`.
|
|
63
|
-
- `status: "complete"` (from `lizard login` only): `username`, `email`, `source` (`browser`, `saved`, or `env` for `LIZARD_TOKEN` / `LIZARD_API_KEY`), `account` with the plan's `state` (`trial_available`, `subscription_required`, `trialing`, `active`, `past_due`, `credits`, `enterprise`, `
|
|
64
|
+
- `status: "complete"` (from `lizard login` only): `username`, `email`, `source` (`browser`, `saved`, or `env` for `LIZARD_TOKEN` / `LIZARD_API_KEY`), `account` with the plan's `state` (`trial_available`, `subscription_required`, `trialing`, `active`, `past_due`, `credits`, `enterprise`, `checkout_unavailable`, `unknown`), `billingUrl`, `payUrl` when a payment failed, and an `instruction` that says what to offer and what not to touch, plus `next` commands.
|
|
64
65
|
|
|
65
66
|
Never start a plan (`lizard billing start`) unless the user agrees. `lizard login` is safe to re-run: a signed-in machine skips straight to the plan. In CI nothing can be opened, so set `LIZARD_TOKEN` or `LIZARD_API_KEY`, or save a token on the machine with `printf '%s' "$TOKEN" | lizard login --token-stdin`. `lizard login --token <token>` works too, but the token lands in the process list and the shell history.
|
|
66
67
|
|
|
67
68
|
## Exit codes
|
|
68
69
|
|
|
69
|
-
- `0` success — continue
|
|
70
|
-
- `1`
|
|
71
|
-
- `2`
|
|
72
|
-
- `
|
|
73
|
-
-
|
|
74
|
-
- `
|
|
70
|
+
- `0` success — continue.
|
|
71
|
+
- `1` error — read `error.message` and show it to the user. A project, service or volume name that doesn't exist exits `1` (`… not found`); so does a `--wait` that runs out (`status: "timeout"`).
|
|
72
|
+
- `2` not allowed.
|
|
73
|
+
- `error.code: "NOT_AUTHENTICATED"` (HTTP 401): not signed in. Give the user the link from `error.body.login` and run the command again once they have signed in (see [Sign-in](#sign-in)). No links in the body (CI, or the platform could not be reached)? Run `lizard login --json`, or ask for `LIZARD_TOKEN`.
|
|
74
|
+
- HTTP 403: signed in, but this key or account may not do it (a key limited to other projects, not a member of the workspace, owner-only data, an account on hold). Signing in again does not help: show `message`.
|
|
75
|
+
- `LIZARD_TOKEN` / `LIZARD_API_KEY` wins over the saved login; a 401 while one is set means that token is bad.
|
|
76
|
+
- `3` not found on the server (HTTP 404), or an unknown command in `--help --json`. Check names with `lizard project list` / `lizard ps`.
|
|
77
|
+
- `4` network or gateway timeout — retry once, then report.
|
|
78
|
+
- `5` cancelled by user — stop.
|
|
79
|
+
|
|
80
|
+
`lizard sandbox exec`, `lizard ssh … -- <cmd>` and `lizard run` exit with the code of the command they ran (`127`: command not found), so the numbers above do not apply to them.
|
|
75
81
|
|
|
76
82
|
## Default project
|
|
77
83
|
|
|
78
|
-
A command that works on a project takes it from `--project`, then from the folder's link, then falls back to the account's **default project**: the oldest live project in the personal workspace
|
|
84
|
+
A command that works on a project takes it from `--project`, then from the folder's link, then falls back to the account's **default project**: the oldest live project in the personal workspace (for a key limited to some projects or workspaces, the oldest one it can reach). So `lizard sandbox create`, `lizard up`, `lizard logs` and the rest work in a folder that was never linked. In a terminal they say so on stderr (`Project: <name> (your default)`); `--json` output does not, except `sandbox create`, whose JSON carries `projectId`, `projectName` and `projectDefaulted: true`. When the project matters, pass `--project`.
|
|
79
85
|
|
|
80
|
-
- `lizard
|
|
81
|
-
- `lizard up
|
|
82
|
-
- No default project (every project deleted
|
|
86
|
+
- `lizard up` links the unlinked folder to the default project first, then creates a service named after `package.json` `name` (else the folder), so the next `up` from that folder updates the same service. The link belongs to that exact folder: `up` from a subfolder creates another service. `lizard init --force --name <project>` relinks the folder, and creates that project when none has the name.
|
|
87
|
+
- `lizard up --project <name>` in an unlinked folder also creates the project when no name matches: check the spelling first.
|
|
88
|
+
- No default project (every project deleted, or the personal workspace on a billing hold): `No project linked…`, and `up` asks for `lizard init --name <project>`. Run `lizard billing --json` to rule out a hold.
|
|
83
89
|
|
|
84
90
|
## Sandboxes
|
|
85
91
|
|
|
@@ -91,42 +97,54 @@ A sandbox is a Linux machine for running code and agents: a Firecracker microVM
|
|
|
91
97
|
```
|
|
92
98
|
lizard sandbox create --json # base template, medium size, 5-minute lifetime; the JSON has the id
|
|
93
99
|
lizard sandbox exec <id> -- python3 -c 'print(2 ** 10)' # exits with the command's exit code
|
|
100
|
+
lizard sandbox exec <id> -- sh -c 'cd /workspace && ls' # a shell line goes inside sh -c
|
|
94
101
|
lizard sandbox files put <id> ./app.py /workspace/app.py
|
|
95
102
|
lizard sandbox exec <id> -- python3 /workspace/app.py
|
|
96
103
|
lizard sandbox expose <id> 8000 --json # an HTTPS URL for a port in the sandbox
|
|
97
104
|
lizard sandbox timeout <id> 3600000 # keep it for an hour from now
|
|
98
|
-
lizard sandbox rm <id>
|
|
105
|
+
lizard sandbox rm <id> # delete it now: no prompt without a terminal
|
|
99
106
|
```
|
|
100
107
|
|
|
101
108
|
`lizard sandbox list --json` shows the project's sandboxes; `--all` shows every one you have.
|
|
102
109
|
|
|
103
|
-
- **Templates:** `base` (default, Python 3.11 on Alpine Linux), `interpreter` (Python
|
|
110
|
+
- **Templates:** `base` (default, Python 3.11 on Alpine Linux), `interpreter` (Python with numpy, pandas, matplotlib and scipy, plus Node 22), `codex`, `claude`, `opencode`, `pi`, `prime` (one coding agent each), `desktop` (graphical desktop with Chromium).
|
|
104
111
|
- **Sizes:** `-s small|medium|large`, $0.0162 / $0.0324 (default) / $0.0648 per hour, billed per second while it runs. A paused sandbox costs nothing.
|
|
105
112
|
- **Lifetime:** 5 minutes by default, then the sandbox is deleted with its files. `--timeout 0` at create means no limit; `lizard sandbox timeout <id> <ms>` sets a new lifetime from now. Commands do not reset it.
|
|
106
|
-
- **Commands:** `exec`
|
|
107
|
-
- **Ports:** `lizard sandbox expose <id> <port
|
|
108
|
-
- **Keeping work:** files outlive a sandbox
|
|
113
|
+
- **Commands:** `exec <id> -- <cmd> [args…]` passes each argument as one word, so a whole shell line in one quoted string fails with `not found`: wrap it, `-- sh -c 'cd /workspace && npm test'`. Each call is a new process that starts in `/root`, gives up after 150 seconds (exit `4`, `EXEC_TIMEOUT`; the command may still be running) and keeps at most 512 KB of output. Run longer jobs in the background and poll a log: `-- sh -c 'cd /workspace && nohup npm run build > build.log 2>&1 &'`, then `-- tail -n 50 /workspace/build.log`. `ssh` needs a real terminal: from an agent, use `exec`.
|
|
114
|
+
- **Ports:** `lizard sandbox expose <id> <port> --json` gives `url` with `?lizard_token=…`, which works in a browser: it swaps the token for a cookie and redirects. `curl -L` without a cookie jar gets `401`; from a script send the token as a header instead: `curl -H "X-Lizard-Access-Token: <accessToken>" https://<hostname>/`. The token opens every port of that sandbox: treat the URL like a password. Start the server in the background (as above) so `exec` returns.
|
|
115
|
+
- **Keeping work:** files outlive a sandbox on a volume (`--volume <name>`) or in a snapshot; `pause` keeps memory and processes and stops billing.
|
|
116
|
+
- **Network:** outbound internet works (mail ports are blocked), but Lizard's own hosts answer only on ports 80 and 443, so a managed Postgres or Redis URL cannot be reached from a sandbox. Work with those databases from a deployed service, or from the user's machine with `lizard run --service postgres -- <cmd>`.
|
|
117
|
+
- **Agents in a sandbox:** `lizard sandbox create -t codex --timeout 3600000`, then `lizard sandbox prompt <id> "task" --json`. Give it a real lifetime: at 5 minutes the sandbox and the agent are deleted mid-task.
|
|
109
118
|
|
|
110
119
|
Everything else (files, coding agents, desktop, volumes, snapshots): `lizard skills get core --ref sandboxes --json`. From your own code: `--ref sdk`.
|
|
111
120
|
|
|
112
121
|
## Deploys
|
|
113
122
|
|
|
114
|
-
When the user wants to deploy or set up something new, work out the right action from
|
|
123
|
+
When the user wants to deploy or set up something new, work out the right action from the folder before running anything:
|
|
124
|
+
|
|
125
|
+
1. `lizard status --json` in the folder, then `lizard ps --json` for what the project already runs.
|
|
126
|
+
2. The folder is linked to a service (`service` in the status), or the project already runs this code → update that service: `lizard up --service <svc>` for an upload, `lizard redeploy --service <svc>` or a push for git. Don't add a second one.
|
|
127
|
+
3. Linked to a project, no service for this code → `lizard add -r owner/repo -n <svc>` (git) or `lizard up` (upload). Do not create a new project unless the user explicitly says so.
|
|
128
|
+
4. A subfolder of a linked folder (a link covers one exact folder) → a monorepo sub-app. In the subfolder run `lizard link --project <parent's project>`, then `lizard up` from there; for git, `lizard add -r owner/repo -n <svc> --no-deploy`, `lizard service set <svc> --set rootDirectory=<subpath>`, `lizard redeploy --service <svc>`.
|
|
129
|
+
5. Not linked → `lizard project list --json` for a project matching the folder or repo name. Match → `lizard link --project <name>`. No match → `lizard up` deploys into the [default project](#default-project); run `lizard init --name <name>` first only when the user wants a separate project.
|
|
130
|
+
|
|
131
|
+
**Names.** A service's name is its key. `lizard add -r` or `add -s` with a name that exists overwrites that service and redeploys it; `lizard up` from an unlinked folder deploys into the service named like `package.json` `name` (else the folder), so two folders whose `package.json` names match land on one service. Name each service yourself: `lizard add -r owner/repo -n <svc>`, or `lizard up --service <svc>`, which deploys to that service and creates it when no service has the name. Use lowercase letters, digits and dashes.
|
|
132
|
+
|
|
133
|
+
**Git or upload.** Check `git remote get-url origin` first. A GitHub remote → `lizard add -r owner/repo -n <svc> --json`. It tracks `main`; for another branch add `--no-deploy`, then `lizard service set <svc> --set branch=<b>` and `lizard redeploy --service <svc>`. Pushes redeploy only when the Lizard GitHub App covers the repo (`lizard git status --json`). `Repository not found` (exit `3`) means Lizard cannot read the repo: `lizard git connect --json` returns an `installUrl` for the user to open. No remote, not GitHub, or not a git repo → `lizard up --json`. `lizard up` always switches a service to `sourceType=upload`: don't use it on a git-backed service.
|
|
115
134
|
|
|
116
|
-
|
|
117
|
-
2. Linked to a project? → add a service in that project: `lizard add -r owner/repo` (git source) or `lizard add -s <name>` (empty). Do not create a new project unless the user explicitly says so.
|
|
118
|
-
3. Not linked but parent dir is linked? → likely a monorepo sub-app. Add a service in the parent's project and set `rootDirectory` to the cwd subpath via `service set`.
|
|
119
|
-
4. Neither linked? → check `lizard project list --json` for one matching the directory or repo name. Match → `lizard link --project <name> [--workspace <ws>]` (pass `--workspace` to disambiguate same-named projects across workspaces). No match → `lizard up` deploys into the [default project](#default-project); run `lizard init --name <name>` first only when the user wants a separate project.
|
|
135
|
+
**Builds** run on the platform's build nodes; no local Docker needed. lizardpack detects Hugo, Go, Node, Python, Rust, Ruby, PHP, Java and static sites (first match wins). A root `Dockerfile` is used as is (on git builds, unless it only copies prebuilt output such as `COPY dist ...` with no install or build `RUN`). Read a failed build with `lizard logs --build --service <svc> --json`.
|
|
120
136
|
|
|
121
|
-
|
|
137
|
+
**Ports.** The app must listen on `$PORT`. `lizard up` fixes a new service's port from `--port`, else the folder's Dockerfile `EXPOSE`, else 3000; pass `--port` when the app listens elsewhere (Python servers often use 8000 or 8080). A wrong port shows as `the new version had not reported ready` and a crashed first deploy: make the app read `$PORT`, or run `lizard port <n> --service <svc>` and then `lizard redeploy --service <svc>`.
|
|
122
138
|
|
|
123
|
-
**
|
|
139
|
+
**Rebuilds.** On a running service, `service set` on a build field (`repoUrl`, `branch`, `sourceType`, `buildCommand`, `dockerfilePath`, `rootDirectory`) and setting a `VITE_*` or `NEXT_PUBLIC_*` variable rebuild on their own: don't chain `lizard redeploy`. A service that never came up, crashed or stopped does not rebuild by itself: run `lizard redeploy --service <svc> --wait --json`. Runtime-only fields (`startCommand`, `preDeployCommand`, `containerPort`) always need `lizard redeploy`.
|
|
124
140
|
|
|
125
|
-
**
|
|
141
|
+
**A service that never came up has no URL.** After you fix why its first deploy failed (a secret, a port, the code), run `lizard redeploy --service <svc> --wait --json`: the domain is issued by the first deploy that succeeds, not by a restart. Then open the URL to confirm.
|
|
126
142
|
|
|
127
|
-
**
|
|
143
|
+
**Workers** without an HTTP listener: `containerPort=0` (`lizard up --port 0`, or `lizard port 0 --service <svc>` and then `lizard redeploy`). A worker has no readiness check, and each deploy stops the old copy before starting the new one.
|
|
128
144
|
|
|
129
|
-
**
|
|
145
|
+
**Files that must survive** restarts and redeploys (SQLite, uploads) go on a volume: `lizard volume create data --service <svc> [--mount-path /data] [--size <gb>]`. One volume per service; the service restarts with it mounted. Without one, the container's disk is wiped on every deploy. Use Postgres instead only when the user wants a database.
|
|
146
|
+
|
|
147
|
+
**Rolling back.** There is no rollback command: deploy the previous code again. For an upload, check out the earlier version (`git checkout <commit> -- .` or the user's copy) and run `lizard up --service <svc>`; for a git service, push a revert and let it redeploy (or `lizard redeploy --service <svc>`). `lizard events --service <svc> --json` shows the deploy history.
|
|
130
148
|
|
|
131
149
|
Details (build order, service fields, worker mode, recipes): `lizard skills get core --ref deploys --json`.
|
|
132
150
|
|
|
@@ -138,9 +156,11 @@ lizard add postgres # or one at a time
|
|
|
138
156
|
```
|
|
139
157
|
|
|
140
158
|
- The first addon of each type is named after it (`postgres`, `redis`, `s3`); later ones get names like `postgres-autumn-bear`. References use the real name: `${{postgres.DATABASE_PRIVATE_URL}}`.
|
|
141
|
-
- Every running Postgres and Redis reaches every service
|
|
159
|
+
- Connect a service explicitly: `lizard secrets set DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' --service <svc>` (Redis: `REDIS_URL='${{redis.REDIS_PRIVATE_URL}}'`). Every running Postgres and Redis also reaches every service as `DATABASE_URL` / `REDIS_URL` (public URL), but only from that service's next deploy, and with two of a type either may win.
|
|
160
|
+
- Private URLs resolve only in the addon's region: `lizard add` defaults to `us-east-1`, so pass the service's `--region` if it runs elsewhere.
|
|
142
161
|
- A reference to a missing addon or key becomes an empty string and does not fail the deploy; renaming an addon breaks its references.
|
|
143
|
-
-
|
|
162
|
+
- `lizard ps --json` and `lizard add <db> --json` print database passwords and S3 keys in plain text: don't repeat them to the user.
|
|
163
|
+
- S3 comes with a private bucket named `default`, up to 16 GiB per S3 addon. `lizard s3 upload <file>`, `lizard s3 list` and `lizard s3 url <key> --expires <seconds>` (a temporary download link that needs no credentials) work without an AWS SDK; AWS SDKs need `forcePathStyle: true`. Making a bucket public is done in the dashboard.
|
|
144
164
|
- Redis has no persistence settings: keep data you cannot lose in Postgres.
|
|
145
165
|
|
|
146
166
|
Every variable each addon exposes: `lizard skills get core --ref deploys --json`.
|
|
@@ -148,61 +168,55 @@ Every variable each addon exposes: `lizard skills get core --ref deploys --json`
|
|
|
148
168
|
## Secrets and config
|
|
149
169
|
|
|
150
170
|
```
|
|
151
|
-
lizard secrets list [--service <svc>] [--global]
|
|
152
|
-
lizard secrets set KEY=v [K2=v2 …]
|
|
153
|
-
lizard secrets set KEY=v --global
|
|
154
|
-
lizard secrets import
|
|
171
|
+
lizard secrets list [--service <svc>] [--global] --json # names only
|
|
172
|
+
lizard secrets set KEY=v [K2=v2 …] --service <svc> # service scope
|
|
173
|
+
lizard secrets set KEY=v --global # every service in the project
|
|
174
|
+
lizard secrets import --service <svc> < .env # values keep their quotes: strip them first
|
|
175
|
+
lizard secrets list --ref --service <svc> --json # the ${{…}} references that resolve
|
|
155
176
|
```
|
|
156
177
|
|
|
157
178
|
- List before you set, so you don't duplicate or shadow a key.
|
|
158
179
|
- Keep secrets in service scope. `--global` is for values that are not secret (`LOG_LEVEL`, `NODE_ENV`, feature flags).
|
|
159
180
|
- Precedence, last wins: addon env < project secrets < project env < app env < app secrets < platform vars (`PORT`, `LIZARD_*`, which cannot be overridden).
|
|
160
|
-
-
|
|
181
|
+
- Setting a secret restarts the service with it, no rebuild; `${{…}}` references are read again then and on every deploy, not on `lizard restart`. Never print a service's full environment.
|
|
182
|
+
- For one service to call another, use `https://${{api.LIZARD_PUBLIC_DOMAIN}}` or the private `http://${{api.LIZARD_PRIVATE_DOMAIN}}:<port>`, not the service name.
|
|
161
183
|
|
|
162
184
|
Scoping rules and build-time variables in detail: `lizard skills get core --ref deploys --json`.
|
|
163
185
|
|
|
164
186
|
## Domains
|
|
165
187
|
|
|
166
188
|
```
|
|
167
|
-
lizard domain --json
|
|
168
|
-
lizard domain
|
|
169
|
-
lizard domain
|
|
189
|
+
lizard domain --service <svc> --json # show the service's onlizard.com domain, or generate one
|
|
190
|
+
lizard domain list --service <svc> --json # its domains, and custom ones waiting for DNS
|
|
191
|
+
lizard domain example.com --service <svc> --json # attach; the hostname is positional, there is no `add`
|
|
192
|
+
lizard domain verify example.com --service <svc> # once the DNS records have propagated
|
|
170
193
|
lizard domain example.com --service <svc> --force # move it here from another of your services
|
|
171
194
|
```
|
|
172
195
|
|
|
173
|
-
Give the user the TXT and CNAME
|
|
196
|
+
Give the user `dnsRecords` from the attach JSON: a TXT record `_lizard-verify.<apex>` and a CNAME for the host. Then run `verify`; it checks only the TXT, and nothing verifies on its own. No TXT in the output means the apex is already proven: only the CNAME is needed. An apex host (`example.com`) needs a DNS provider that can put a CNAME at `@`.
|
|
174
197
|
|
|
175
198
|
## Logs and operations
|
|
176
199
|
|
|
177
200
|
```
|
|
178
|
-
lizard logs --
|
|
179
|
-
lizard logs --build --json
|
|
180
|
-
lizard logs --restart latest --json
|
|
181
|
-
lizard ps --json #
|
|
182
|
-
lizard status
|
|
183
|
-
lizard restart --service <
|
|
184
|
-
lizard redeploy
|
|
185
|
-
lizard scale --service <
|
|
186
|
-
lizard domain example.com --service <name> # attach custom domain (positional, not `domain add`)
|
|
187
|
-
lizard domain --json # show/auto-generate the service's current domain
|
|
188
|
-
lizard domain verify example.com # activate after DNS records propagate
|
|
189
|
-
lizard domain example.com --service <name> --force # move domain here from another of your services
|
|
201
|
+
lizard logs --service <svc> --json # last 200 runtime lines, then exit (--tail N, max 1000); without --service it mixes every service
|
|
202
|
+
lizard logs --build --service <svc> --json # last build's logs
|
|
203
|
+
lizard logs --restart latest --service <svc> --json # log tail of the most recent crash/restart
|
|
204
|
+
lizard ps --json # {apps, addons}: status and bare `domain` (no https://)
|
|
205
|
+
lizard status --json # this folder's link (no auth needed)
|
|
206
|
+
lizard restart --service <svc> # same image and env; rolling only for an HTTP service without a volume
|
|
207
|
+
lizard redeploy --service <svc> --wait --json # rebuild from the latest commit or last upload; waits until ready
|
|
208
|
+
lizard scale --service <svc> --replicas N --memory <mb> --cpu <cores> # replicas 1-10, memory 128-8192 MB, cpu 1-4
|
|
190
209
|
lizard metrics --json # CPU/memory/network/disk (add --cost for cost)
|
|
191
|
-
lizard billing --json # plan, trial, usage this month, Billing link
|
|
192
210
|
lizard metrics --all --json # all services in the project, even from a service-linked directory
|
|
193
|
-
lizard
|
|
194
|
-
lizard
|
|
195
|
-
lizard
|
|
196
|
-
lizard run --service <name> -- <cmd> # run a command LOCALLY with the service's stored secrets (an addon gives its real connection values)
|
|
197
|
-
lizard project list --json # all projects in workspace
|
|
211
|
+
lizard events --service <svc> --json # deploy history + replica status
|
|
212
|
+
lizard run --service <svc> -- <cmd> # run a command LOCALLY with the service's stored secrets (an addon gives its real connection values)
|
|
213
|
+
lizard project list --json # your projects in every workspace (-w <ws> to filter)
|
|
198
214
|
lizard regions --json
|
|
199
|
-
lizard open # open dashboard
|
|
200
215
|
lizard whoami --json # auth check
|
|
201
|
-
lizard
|
|
202
|
-
lizard s3 list --json [--bucket <b>] # list objects in an S3 addon bucket
|
|
216
|
+
lizard billing --json # plan, trial, usage this month, Billing link
|
|
203
217
|
```
|
|
204
218
|
|
|
205
|
-
Metrics options and `lizard run` in detail: `lizard skills get core --ref deploys --json`.
|
|
219
|
+
There is no shell into a running service (`lizard ssh` answers 403); for a sandbox use `lizard sandbox exec`. Metrics options and `lizard run` in detail: `lizard skills get core --ref deploys --json`.
|
|
206
220
|
|
|
207
221
|
## Response format
|
|
208
222
|
|
|
@@ -217,40 +231,44 @@ Skip command-by-command transcripts unless they explain a failure.
|
|
|
217
231
|
## Don't do
|
|
218
232
|
|
|
219
233
|
1. Don't add Docker `HEALTHCHECK` — the platform ignores it (it doesn't run Docker's healthcheck loop).
|
|
220
|
-
2. On the lizardpack auto-detect path, `
|
|
234
|
+
2. On the lizardpack auto-detect path, `package.json` `scripts.start` (Node) and a `Procfile` `web:` line (Python, Ruby) are picked up automatically — don't force a redundant `startCommand`. Once `buildCommand` or `startCommand` is set, the platform generates its own Dockerfile and reads neither, nor the user's `Dockerfile`: set `startCommand` explicitly, or set `dockerfilePath` so the user's Dockerfile and its `CMD` are used as is.
|
|
221
235
|
3. Don't use `lizard up` to switch a service to a git source. It always forces `sourceType=upload`. Use `service set` + `redeploy` instead.
|
|
222
|
-
4.
|
|
236
|
+
4. On git builds, a `Dockerfile` whose `COPY` starts with `dist`, `build`, `out`, `.next` or `public` and that has no install or build `RUN` (`npm`, `pip`, `go build`…) is replaced by a lizardpack one (the build log says so). Add a build step, or set `dockerfilePath` to force it as is.
|
|
223
237
|
5. Don't generate Dockerfiles unsolicited — lizardpack auto-detects most stacks. Try a deploy first; write one only if it fails. Ask before either.
|
|
224
238
|
6. Don't put runtime secrets (DB credentials, API keys, RPC creds, S3 keys) in `--global` "just in case another service needs it later". Scope to the services that consume them — see [Secrets and config](#secrets-and-config).
|
|
225
239
|
|
|
226
240
|
## Billing
|
|
227
241
|
|
|
228
|
-
Billing belongs to the account
|
|
242
|
+
Billing belongs to the account owner. `lizard billing --workspace <id> --json` shows the plan of another workspace's owner.
|
|
229
243
|
|
|
230
244
|
```sh
|
|
231
245
|
lizard billing --json # plan, trial, this month's usage, next charge, billingUrl
|
|
232
246
|
lizard billing start --json # Stripe Checkout link: the Pro trial, or Pro at once
|
|
233
247
|
lizard billing promo <code> --json # a longer trial with more trial usage
|
|
234
248
|
lizard billing open # the Billing page
|
|
235
|
-
lizard metrics --cost --json #
|
|
249
|
+
lizard metrics --cost --json # one project's cost per hour and this period's usage (owner only; a key limited to projects can't read costs); proCredits on Pro
|
|
236
250
|
```
|
|
237
251
|
|
|
238
252
|
Pro costs $19/month, taxes included, and includes $19 of usage each month for
|
|
239
253
|
everything on the account; unused usage does not carry over. Usage above that is
|
|
240
254
|
pay as you go at the published rates, charged to the card as it builds up. A new
|
|
241
255
|
account starts with no plan. The 7-day trial includes $5 of usage; Checkout asks
|
|
242
|
-
for a card and charges nothing until the trial ends, then Pro is $19/month.
|
|
256
|
+
for a card and charges nothing until the trial ends, then Pro is $19/month. Some
|
|
257
|
+
accounts run a longer trial without a card: read `trial.endsAt` and
|
|
258
|
+
`trial.creditCents` from `lizard billing --json` instead of assuming. When
|
|
243
259
|
the trial usage runs out, running resources pause and nothing new can be created
|
|
244
260
|
until Pro starts. Data is kept. Promo codes work only before the first payment.
|
|
245
261
|
Trial accounts run 1 replica per app and 5 sandboxes at once; after the first
|
|
246
262
|
paid invoice, 5 replicas per app and 100 sandboxes (paused sandboxes don't
|
|
247
263
|
count). Pro cards are changed or removed on the Billing page;
|
|
248
|
-
`lizard billing payment-methods remove` works only for Enterprise accounts.
|
|
264
|
+
`lizard billing payment-methods remove` works only for Enterprise accounts (Pro: 409 `CREDITS_NOT_AVAILABLE`).
|
|
249
265
|
Enterprise accounts pay as you go, invoiced monthly. There are no top-ups, no
|
|
250
266
|
auto top-up and no crypto or x402 payments.
|
|
251
267
|
|
|
252
268
|
When the account needs a plan or a payment, every create command (`up`, `add`,
|
|
253
|
-
`sandbox create`, `volume create`, `domain`,
|
|
269
|
+
`sandbox create`, `volume create`, `domain`, `redeploy`, `restart`) fails with
|
|
270
|
+
HTTP 402. In a workspace someone else owns, the 402 is about the owner's plan:
|
|
271
|
+
`lizard billing start` would act on your own account, so ask the owner.
|
|
254
272
|
The JSON error has `code: "PAYMENT_REQUIRED"` (`"INSUFFICIENT_CREDITS"` from
|
|
255
273
|
older servers), a `message` to show the user as is (its last line is the link),
|
|
256
274
|
and `body.status` with the links:
|
|
@@ -264,6 +282,12 @@ and `body.status` with the links:
|
|
|
264
282
|
| `paused` | Running resources are paused, data kept. `message` says why: trial usage used up (Start Pro now, as above) or a failed payment (pay the open invoice in Billing) |
|
|
265
283
|
| anything else | Show `message` and `body.billingUrl` |
|
|
266
284
|
|
|
285
|
+
`sandbox resume` on an account on hold fails with 403 instead (exit `2`). Too many
|
|
286
|
+
sandboxes at once, or too many starts per minute, is HTTP 429 (`SANDBOX_LIMIT_REACHED`,
|
|
287
|
+
`SANDBOX_RATE_LIMITED` with `retryAfterS`), not a billing problem: wait or delete
|
|
288
|
+
idle sandboxes. `billing start` can also answer 402 `UNPAID_INVOICE` (pay
|
|
289
|
+
`body.invoiceUrl` first) or 409 `ALREADY_SUBSCRIBED`.
|
|
290
|
+
|
|
267
291
|
Checkout and invoice pages open in the user's browser; you cannot finish them.
|
|
268
292
|
Give the user the link, never ask for card details in chat, and retry the
|
|
269
293
|
failed command after they say they are done. `start-now` (charges $19 now),
|
|
@@ -20,8 +20,9 @@ This skill documents platform behavior (build pipeline, env precedence, what kno
|
|
|
20
20
|
Before writing commands for a specific project:
|
|
21
21
|
|
|
22
22
|
1. Read the user's `package.json`, `Dockerfile`, `requirements.txt`, framework config — confirm what already exists before adding flags.
|
|
23
|
-
2. Don't assume scripts/conventions that aren't visible. On the lizardpack auto-detect path, `Procfile` (`web:` line, Python/Ruby) and `package.json scripts.start` (Node) ARE picked up as the start command; on the synthesized-Dockerfile path (`buildCommand`/`startCommand` set) neither is read.
|
|
24
|
-
3.
|
|
23
|
+
2. Don't assume scripts/conventions that aren't visible. On the lizardpack auto-detect path, `Procfile` (`web:` line, Python/Ruby) and `package.json scripts.start` (Node) ARE picked up as the start command; on the synthesized-Dockerfile path (`buildCommand`/`startCommand` set) neither is read.
|
|
24
|
+
3. Ports: `lizard up` fixes a new service's port from `--port`, else the folder's Dockerfile `EXPOSE`, else 3000, and the app must listen there (`$PORT`). lizardpack's Python commands bind 8000 and PHP 80: pass `--port 8000` / `--port 80`, or a start command that reads `$PORT`. Git services take the port from the image's `EXPOSE` unless `containerPort` or a `PORT` variable is set. Nothing reads the port from logs.
|
|
25
|
+
4. When in doubt, ask the user or run `lizard <cmd> --help --json`.
|
|
25
26
|
|
|
26
27
|
## Platform builder
|
|
27
28
|
|
|
@@ -29,16 +30,17 @@ Builds run on the platform's build nodes (no local Docker needed). When a build
|
|
|
29
30
|
|
|
30
31
|
### Build decision order
|
|
31
32
|
|
|
32
|
-
1. Repo Dockerfile (verbatim) — if `dockerfilePath`
|
|
33
|
-
2. Synthesized Dockerfile — if `buildCommand` and/or `startCommand` are set on the service
|
|
34
|
-
3.
|
|
33
|
+
1. Repo Dockerfile (verbatim) — if `dockerfilePath` (relative to `rootDirectory`) is set, the platform builds that Dockerfile unchanged and ignores `buildCommand`/`startCommand` for the image. A set `startCommand` still replaces the image's ENTRYPOINT and CMD at run time (`sh -c`, so the image needs `sh`).
|
|
34
|
+
2. Synthesized Dockerfile — if `buildCommand` and/or `startCommand` are set (on the service or via `lizard up`), the platform generates a Go, Python or Node Dockerfile, chosen by the command's first word (anything else gets Node). It replaces the repo Dockerfile and lizardpack, so on other stacks fix the start through a Dockerfile, not `startCommand`.
|
|
35
|
+
3. Root `Dockerfile` — used as is for uploads. For git, used unless it has no install or build `RUN` (`npm|yarn|pnpm|bun|pip|bundle|cargo|go build|mvn|gradle`) and copies a build folder (`COPY dist ...`, `build`, `out`, `.next`, `public`): then lizardpack replaces it and the build log says so.
|
|
36
|
+
4. lizardpack auto-detect — Hugo, Go, Node, Python, Rust, Ruby, PHP, Java, static, first match wins. When nothing matches, the image runs `bash start.sh`, which builds but fails to start.
|
|
35
37
|
|
|
36
38
|
### What triggers a rebuild
|
|
37
39
|
|
|
38
|
-
- `git push` to the tracked branch → auto-rebuild
|
|
40
|
+
- `git push` to the tracked branch → auto-rebuild, when the Lizard GitHub App covers the repo (`lizard git status --json`).
|
|
39
41
|
- `lizard redeploy` / `lizard up` → explicit rebuild.
|
|
40
42
|
- Setting a `VITE_*` or `NEXT_PUBLIC_*` variable → the platform redeploys the running services that receive it, so the build bakes it in. Do NOT chain a `lizard redeploy`. See [Applying an env change](#applying-an-env-change) for which builds receive them.
|
|
41
|
-
- `service set` for build-affecting fields (`repoUrl`, `branch`, `sourceType`, `buildCommand`, `dockerfilePath`, `rootDirectory`) → auto-rebuilds running
|
|
43
|
+
- `service set` for build-affecting fields (`repoUrl`, `branch`, `sourceType`, `buildCommand`, `dockerfilePath`, `rootDirectory`) → auto-rebuilds a service whose status is `running`. Do NOT chain a `lizard redeploy` after it — that queues a second build. A service that never came up, crashed or stopped doesn't rebuild: run `lizard redeploy`.
|
|
42
44
|
- `service set` for runtime-only fields (`startCommand`, `preDeployCommand`, `containerPort`, `watchPatterns`) → no auto-rebuild. Follow with `lizard redeploy` to apply.
|
|
43
45
|
- All other env vars / secrets → applied without a rebuild; the service restarts to pick them up.
|
|
44
46
|
|
|
@@ -50,7 +52,7 @@ First question for a new service: upload vs git repo. **Always check for a git r
|
|
|
50
52
|
git remote get-url origin
|
|
51
53
|
```
|
|
52
54
|
|
|
53
|
-
- **Exit 0 with a GitHub URL → use the git-source path below**, not `up`. Parse `owner/repo` from the URL and run `lizard add -r owner/repo
|
|
55
|
+
- **Exit 0 with a GitHub URL → use the git-source path below**, not `up`. Parse `owner/repo` from the URL and run `lizard add -r owner/repo -n <svc>`. This is strongly preferred: pushes redeploy (with the Lizard GitHub App), and there's no re-upload on every change.
|
|
54
56
|
- **No remote / non-GitHub / not a git repo → use tarball upload (`lizard up`).** This is the fallback for quick local iteration or no-remote situations, not the default.
|
|
55
57
|
|
|
56
58
|
`lizard up` always works regardless of git state, which makes it the path of least resistance — resist it when a GitHub remote exists. Only fall back to upload when the remote check actually fails. (For a private repo whose remote exists but isn't yet accessible to Lizard, run `lizard git connect` to install the GitHub App, then use the git-source path — don't silently downgrade to a tarball.)
|
|
@@ -58,29 +60,34 @@ git remote get-url origin
|
|
|
58
60
|
### Git-source deploy (preferred when there's a remote)
|
|
59
61
|
|
|
60
62
|
```
|
|
61
|
-
# One-shot for a new service from GitHub:
|
|
62
|
-
lizard add -r owner/repo --json
|
|
63
|
+
# One-shot for a new service from GitHub (tracks main):
|
|
64
|
+
lizard add -r owner/repo -n <svc> --json
|
|
63
65
|
|
|
64
|
-
#
|
|
66
|
+
# Another branch:
|
|
67
|
+
lizard add -r owner/repo -n <svc> --no-deploy --json
|
|
68
|
+
lizard service set <svc> --set branch=<branch> --json
|
|
69
|
+
lizard redeploy --service <svc> --wait --json
|
|
70
|
+
|
|
71
|
+
# Existing service: switch source to git (rebuilds by itself when the service is running;
|
|
72
|
+
# otherwise follow with `lizard redeploy --service <svc>`):
|
|
65
73
|
lizard service set <svc> \
|
|
66
74
|
--set sourceType=github \
|
|
67
75
|
--set repoUrl=https://github.com/owner/repo \
|
|
68
76
|
--set branch=main \
|
|
69
77
|
--json
|
|
70
|
-
lizard redeploy --service <svc>
|
|
71
78
|
```
|
|
72
79
|
|
|
73
|
-
When `repoUrl` is set, pushes to the
|
|
80
|
+
`add -r` with a name that already exists overwrites that service (branch back to `main`, commands cleared) and redeploys it: pick a new `-n`. A private repo Lizard can't read answers 404 `Repository not found`: `lizard git connect --json` gives an `installUrl` for the user. When `repoUrl` is set, pushes to the branch redeploy through the Lizard GitHub App. With a `rootDirectory` or watch patterns, only pushes touching either one redeploy; `autoDeploy=false` turns pushes off.
|
|
74
81
|
|
|
75
|
-
Useful `service set` fields (
|
|
82
|
+
Useful `service set` fields (the full list is in the plain `lizard service set --help`; the JSON schema leaves it out):
|
|
76
83
|
|
|
77
84
|
- `sourceType` = `github | upload`
|
|
78
85
|
- `repoUrl`, `branch`, `rootDirectory`
|
|
79
86
|
- `dockerfilePath` — use a specific repo Dockerfile, bypasses lizardpack auto-detect
|
|
80
87
|
- `buildCommand`
|
|
81
|
-
- `startCommand`, `preDeployCommand` — `preDeployCommand` runs before `startCommand` at the start of every container (each replica, each restart), and only when `startCommand` is also set. Make it safe to run many times and at the same time.
|
|
88
|
+
- `startCommand`, `preDeployCommand` — `preDeployCommand` runs before `startCommand` at the start of every container (each replica, each restart), and only when `startCommand` is also set (otherwise it is skipped). If it fails, the container never starts. Make it safe to run many times and at the same time.
|
|
82
89
|
- `watchPatterns` — string array, comma-separated or JSON
|
|
83
|
-
- `containerPort` — TCP port the app listens on (
|
|
90
|
+
- `containerPort` — TCP port the app listens on (a new `lizard up` service gets 3000 unless `--port` or an `EXPOSE` says otherwise). Set to `0` for [worker mode](#worker-mode).
|
|
84
91
|
- `name` — rename a service (lowercase a-z, digits, hyphens; 1–40 chars). Goes through `config:apply`; the legacy `PATCH /api/apps/:id` returns 410. Refs to the old name (`${{old.KEY}}`) stop resolving: update them.
|
|
85
92
|
|
|
86
93
|
Field names are flat and match the wire schema 1:1 (and `service show` output). No `build.*` / `deploy.*` / `source.*` grouping exists in the API, DB, or node-agent.
|
|
@@ -93,8 +100,9 @@ Field names are flat and match the wire schema 1:1 (and `service show` output).
|
|
|
93
100
|
lizard up --json
|
|
94
101
|
```
|
|
95
102
|
|
|
96
|
-
- Uploads cwd as a tarball (
|
|
97
|
-
- Streams build logs
|
|
103
|
+
- Uploads cwd as a tarball (at most 150 MB compressed) and forces `sourceType=upload`. In a git repo it sends tracked files plus untracked files that `.gitignore` doesn't exclude; outside git it skips `node_modules`, `.git`, `dist`, `build`, `.next`, virtualenvs and caches, so a prebuilt `dist/` is not sent. There is no `.lizardignore`, and `.dockerignore` is not read.
|
|
104
|
+
- Streams build logs; ends with `{ event: "deployed", status: "running", url }`. A failed build ends with `{ event: "error", message }` and exit 1; no `deployed` event means the service isn't running yet (see the core guide).
|
|
105
|
+
- With no linked service, `up` deploys into the service named like `package.json` `name` (else the folder), and switches it to an upload even if it was git-backed. `--service <name>` deploys to that service, creating it when none has the name; a folder linked to an addon (after `lizard add postgres`) is treated as unlinked.
|
|
98
106
|
- Flags: `--project`, `--service`, `--region`, `--build-command`, `--start-command`, `--pre-deploy-command`, `--port`, `--detach`, `--ci`.
|
|
99
107
|
- If cwd isn't linked and no `--project` is given, it links the folder to the default project (see the core guide) and deploys there as a new service. `--project <name>` uses that project, or creates it if none matches. It never creates a project from the folder name on its own.
|
|
100
108
|
- `lizard up` always switches the service to `sourceType=upload`. Do not use it to update a git-backed service — use `lizard redeploy` or push to the remote.
|
|
@@ -104,15 +112,15 @@ lizard up --json
|
|
|
104
112
|
For services that don't expose an HTTP listener (background workers, reconcilers, queue consumers, cron-style polling loops), set `containerPort=0`. The platform then:
|
|
105
113
|
|
|
106
114
|
- Skips `PORT` env injection (the worker doesn't bind anywhere).
|
|
107
|
-
-
|
|
115
|
+
- Runs no readiness check, and each deploy stops the old copy before starting the new one (two copies never overlap).
|
|
108
116
|
- Skips `EXPOSE` in the synthesized Dockerfile.
|
|
109
|
-
-
|
|
117
|
+
- A generated `.onlizard.com` domain and route may still exist; they answer with an error.
|
|
110
118
|
|
|
111
119
|
Set it one of three ways:
|
|
112
120
|
|
|
113
121
|
```
|
|
114
122
|
lizard up --port 0 # new upload-source worker
|
|
115
|
-
lizard port 0 [--service <svc>] # flip existing service to worker mode
|
|
123
|
+
lizard port 0 [--service <svc>] # flip existing service to worker mode, then `lizard redeploy`
|
|
116
124
|
lizard service set <svc> --set containerPort=0 # same, via the config:apply path
|
|
117
125
|
```
|
|
118
126
|
|
|
@@ -135,7 +143,7 @@ Two scopes exist. No workspace-level globals.
|
|
|
135
143
|
addon-issued env < project secrets < project env < app env < app secrets < platform vars
|
|
136
144
|
```
|
|
137
145
|
|
|
138
|
-
App secrets override project secrets. Platform vars
|
|
146
|
+
App secrets override project secrets. Platform vars come last and cannot be shadowed: `PORT` (absent in worker mode), `LIZARD_PROJECT_ID`, `LIZARD_SERVICE_NAME` (an internal `app-…` handle, not the dashboard name), `LIZARD_PUBLIC_DOMAIN` (absent until the service has a domain; a comma list once a custom domain is attached) and `LIZARD_PRIVATE_DOMAIN`. For service-to-service URLs use `${{<svc>.LIZARD_PRIVATE_DOMAIN}}`, not the service name. A `PORT` you set yourself doesn't override the injected one, but it becomes `containerPort` at the next deploy when the port wasn't set explicitly. Addon-issued env is every running Postgres and Redis addon's public `DATABASE_URL` / `REDIS_URL`, injected into every service at its next deploy or secret change; with two addons of a type, either may win.
|
|
139
147
|
|
|
140
148
|
### Secret scoping
|
|
141
149
|
|
|
@@ -144,22 +152,23 @@ Default to service-scope. `--global` puts the value into `process.env` of every
|
|
|
144
152
|
Rules:
|
|
145
153
|
|
|
146
154
|
- Check first: `lizard secrets list` (+ `--global`) before set/update — avoid creating a duplicate or shadowing an existing key (service scope wins over global; see [Precedence](#precedence-last-writer-wins)).
|
|
147
|
-
- Default — service-scope: `lizard secrets set KEY=v --service <svc>` per consumer. For addon DSNs, prefer a private reference when the consumer can reach it: `lizard secrets set DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' --service <svc>` (no separate `env` command — refs are interpolated
|
|
155
|
+
- Default — service-scope: `lizard secrets set KEY=v --service <svc>` per consumer. For addon DSNs, prefer a private reference when the consumer can reach it: `lizard secrets set DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' --service <svc>` (no separate `env` command — refs are interpolated wherever they appear). Refs are read again on every deploy, redeploy and secret change, not on `lizard restart`; there is no automatic credential rotation. A ref to another service sees only its stored values and platform vars, not the `DATABASE_URL` it got automatically.
|
|
156
|
+
- `secrets import` keeps quotes and `export ` prefixes as part of the value: strip them first.
|
|
148
157
|
- `--global` only for non-secrets and provably-public values: `LOG_LEVEL`, `NODE_ENV`, feature flags, frontend `SENTRY_DSN`. If unsure whether a value is a secret, treat it as one. A compromised service reads its own env; broader scope = more credentials exposed for no reason.
|
|
149
158
|
|
|
150
159
|
### Applying an env change
|
|
151
160
|
|
|
152
161
|
- Runtime vars/secrets apply without rebuilding the image. The application process restarts to read its new environment; do not promise uninterrupted requests.
|
|
153
|
-
- `VITE_*` / `NEXT_PUBLIC_*` (build-time baked) → setting one redeploys the running services that receive it; a plain restart won't pick them up. Only
|
|
162
|
+
- `VITE_*` / `NEXT_PUBLIC_*` (build-time baked) → setting one redeploys the running services that receive it; a plain restart won't pick them up. Only some builds bake them in: lizardpack or a reused repo Dockerfile on a GitHub service, or a Node-style build generated from `buildCommand`/`startCommand`. A `dockerfilePath` build, or a `lizard up` upload without those overrides, gets no Lizard variables at build time, and no build gets build args except `COMMIT_SHA`. For public values there, commit them in `.env.production`, set a build command, or write them into the Dockerfile.
|
|
154
163
|
- Verify a non-secret value or the application's behavior. Do not print the full environment: it can expose credentials.
|
|
155
164
|
|
|
156
165
|
## Managed addons
|
|
157
166
|
|
|
158
167
|
Provision with `lizard add <type>`. Each addon exposes a fixed env-var set; reference by name from a consumer service via `${{<addon-name>.KEY}}`. The first addon of a given type gets the bare type as its name (so use `postgres` in the reference for the first Managed Postgres instance); subsequent ones get `{type}-{adjective}-{noun}` like `postgres-autumn-bear`. There's no type-alias fallback — a ref must use the addon's actual name. Refs match the addon's current name, so renaming it breaks existing refs: update them after a rename. Every running Postgres and Redis addon's `DATABASE_URL` / `REDIS_URL` also reaches every service in the project at the lowest precedence; a value set on the consumer overrides it.
|
|
159
168
|
|
|
160
|
-
- `postgres` — two connection URLs: prefer `DATABASE_PRIVATE_URL` when available and reachable within the same project and region (no ingress/egress charges); use `DATABASE_URL` for public access, such as local clients or external CI (network charges may apply). Also exposes `PGHOST`, `PGPORT
|
|
169
|
+
- `postgres` — two connection URLs: prefer `DATABASE_PRIVATE_URL` when available and reachable within the same project and region (no ingress/egress charges); use `DATABASE_URL` for public access, such as local clients or external CI (network charges may apply). Private URLs resolve only in the addon's region, and `lizard add` defaults to `us-east-1`. Also exposes `PGHOST`, `PGPORT` (the public endpoint), `PGUSER`, `PGPASSWORD`, `PGDATABASE`, `POSTGRES_USER`, `POSTGRES_DB`, `POSTGRES_PASSWORD`.
|
|
161
170
|
- `redis` — `REDIS_URL`; services in the same project should use `REDIS_PRIVATE_URL`. No eviction policy and no append-only file are configured: if it runs out of memory, the instance restarts and recent writes can be lost. Keep data you cannot lose in Postgres.
|
|
162
|
-
- `s3` — `S3_ENDPOINT`, `S3_DEFAULT_BUCKET`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_REGION`. Auto-creates a private bucket named `default
|
|
171
|
+
- `s3` — `S3_ENDPOINT`, `S3_DEFAULT_BUCKET`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_REGION`. Auto-creates a private bucket named `default`; each S3 addon stores up to 16 GiB. Make a bucket public from the dashboard's S3 browser; objects in a public bucket are served without auth two ways: the gateway URL the dashboard shows, `https://s3-<region>.onlizard.com/<addonId>/<bucket>/<key>`, or the platform proxy `<dashboard-host>/api/s3/<addonId>/public/<bucket>/<key>` (the host `lizard open` launches; long-lived immutable cache headers). For AWS SDK use, set `forcePathStyle: true`. ACL flips aren't on the CLI yet, so point users at the dashboard. To push a local file into a bucket directly (no AWS SDK needed), use `lizard s3 upload <file> [--addon <name>] [--bucket <name>] [--key <key>] [--content-type <type>]` — auto-resolves the project's only S3 addon and bucket `default` if omitted; prints `{key, etag, size, url}` (`url` is `null` unless the bucket is public). `lizard s3 list|ls [--bucket <name>] [--prefix <p>]` lists objects in a bucket. `lizard s3 url <key> [--expires <seconds>]` prints a presigned link (default 1 hour, at most 7 days) that downloads a private object without credentials. The CLI has no ACL command: make a bucket public in the dashboard, or with an S3 `PutBucketAcl` (`public-read`) call using the addon's credentials.
|
|
163
172
|
|
|
164
173
|
## Composition patterns
|
|
165
174
|
|
|
@@ -168,10 +177,12 @@ Multi-step requests follow natural chains. Return one unified response, don't fa
|
|
|
168
177
|
- First deploy from git — pick action via the setup decision flow in the core guide → `lizard add -r owner/repo` → stream build → surface URL.
|
|
169
178
|
- First deploy from local code — Setup decision flow → `lizard up` → surface URL.
|
|
170
179
|
- Add a managed database to an existing service — `lizard add postgres` → bind the consumer's `DATABASE_URL` to the private reference as described above (the service restarts with it; no redeploy needed).
|
|
180
|
+
- Keep files across deploys — `lizard volume create data --service <svc> --mount-path /data` (one volume per service; the service restarts with it) → point the app's file paths there.
|
|
171
181
|
- Add object storage to a service — `lizard add s3` → reference `${{s3.S3_ENDPOINT}}`, `${{s3.S3_DEFAULT_BUCKET}}`, `${{s3.S3_ACCESS_KEY_ID}}`, `${{s3.S3_SECRET_ACCESS_KEY}}`, `${{s3.S3_REGION}}` from the consumer service. The `default` bucket is private; to serve files without auth, have the user make it public in the dashboard's S3 browser, then objects are served at `<dashboard-host>/api/s3/<addonId>/public/default/<key>`. See [Managed addons](#managed-addons).
|
|
172
|
-
- Wire a fresh git source on an existing service — `service set --set sourceType=github --set repoUrl=… --set branch=…`
|
|
173
|
-
- Fix a failed build — `logs --build
|
|
174
|
-
-
|
|
182
|
+
- Wire a fresh git source on an existing service — `service set --set sourceType=github --set repoUrl=… --set branch=…` (rebuilds a running service by itself; otherwise `redeploy`).
|
|
183
|
+
- Fix a failed build — `logs --build --service <svc>` → diagnose → fix project (user's repo) OR adjust `buildCommand` / `startCommand` via `service set` → `redeploy --service <svc> --wait` → `logs` to verify.
|
|
184
|
+
- Fix a crash-looping service — `logs --restart latest --service <svc>` → fix the cause (secret, port, code) → `redeploy --service <svc> --wait`: a service whose first deploy failed gets its URL only from a successful deploy.
|
|
185
|
+
- Add a custom domain — `domain <host> --service <svc>` (the hostname is a positional, there is no `add` subcommand) → give the user `dnsRecords` → `domain verify <host> --service <svc>` once DNS propagates (it checks only the TXT; nothing verifies on its own). `domain list --service <svc>` shows pending domains. If the host is already attached to another of the user's services, the attach 409s with a reclaim hint — re-run with `--force` to move it here.
|
|
175
186
|
|
|
176
187
|
## Logs, metrics and lizard run
|
|
177
188
|
|
|
@@ -185,6 +196,6 @@ The project overview includes `Egress` (outbound bytes per second) and `Volumes`
|
|
|
185
196
|
Watch mode refreshes CPU and memory every 3 seconds and I/O history every 30 seconds.
|
|
186
197
|
JSON output includes the history in each service's `series` and `timestamps` fields.
|
|
187
198
|
|
|
188
|
-
`lizard run --service <app>` injects stored values only: `${{…}}` refs arrive as literal text, and platform vars (`PORT`, `LIZARD_*`) are not set. `--service <addon>` injects the addon's real connection values, so use it to run a local command against a database. To check a service's wiring, use `lizard logs --build --service <svc>` and `lizard secrets list --service <svc> --
|
|
199
|
+
`lizard run --service <app>` injects stored values only: `${{…}}` refs arrive as literal text, and platform vars (`PORT`, `LIZARD_*`) are not set. `--service <addon>` injects the addon's real connection values, so use it to run a local command against a database. To check a service's wiring, use `lizard logs --build --service <svc>` (it warns about every reference that came back empty), `lizard secrets list --service <svc> --json` (names) and `lizard secrets list --ref --service <svc> --json` (the references that resolve; `available: false` for an addon that isn't running); shell access into services is off.
|
|
189
200
|
|
|
190
201
|
For exact flags, `lizard <cmd> --help --json`. Other commands not shown above: `lizard git` (GitHub integration), `lizard config` (project configuration), `lizard workspace` (workspace info) — discover each with `lizard <cmd> --help --json`.
|