How do I get JSON from the Grain CLI?
Add the global --json option before the command. It emits exactly one envelope and avoids prompts.
Docs
The Grain CLI connects local folders to workspaces, moves files, runs workspace commands, records revisions and manages shares. This reference lists every registered command with exactly the flags in its public usage string.
grain [--json] [--workspace <id>] <command>
grain -v--json emits one JSON envelope and never prompts. --workspace <id> selects a workspace explicitly. The -v version option prints the CLI version. With no command, the CLI prints help and exits with status 1; an unknown command reports Unknown command: <command>.
grain login
grain logout
grain init [path] [--organization <id>] [--name <name>] [--template <template>] [--folder <path>] [--keep-failed] [--no-open] [--no-agent-config] [--dry-run]
grain new [name] [--template <template>] [--folder <path>] [--name <name>] [--organization <id>] [--keep-failed] [--checkout] [--no-open] [--no-start]
grain list [--organization <id>] [--folder <path>] [--query <text>]
grain use [workspace-id|--clear] [--dry-run]
grain status
grain exec <command...>
grain shell [--command <command>]
grain start [path] [--foreground] [--restart] [--no-pull] [--continue|--abort] [--no-open] [--debounce-ms <n>] [--push-interval-ms <n>]
grain stop [path]
grain pull [--force]
grain checkout [--dry-run]
grain checkouts list
grain checkouts remove <workspace-id> [--discard] [--dry-run]
grain push [--force] [--no-reload] [--dry-run]
grain checkpoint [-m <message>] [--dry-run]
grain restore <revision-number> [--dry-run]
grain share [--public | --password <pw>] [--path <path>] [--name <name>] [--no-reuse] [--dry-run]
grain share list
grain share update <shareId> [--mode off|public|password] [--password <pw>] [--regenerate-slug] [--name <name>] [--path <path>] [--dry-run]
grain share revoke <shareId> [--dry-run]
grain open
grain release [--dry-run]
grain mcp
grain refresh [path]
grain clone [workspace-id] [path]
grain upload <local-path...> [--to <workspace-dir>]
grain doctor [path]
grain upgrade [--target react-vite|nextjs]| Command and help | Expected output | Failure messages |
|---|---|---|
login has no flags and saves revocable authentication through the desktop app. | Prints the path where the revocable CLI token was saved. | Unknown login option: <option> |
logout has no flags and removes local credentials after attempting remote revocation. | Confirms that local credentials were removed and whether the remote session was revoked; it also reports when the CLI was already logged out. | Unknown logout option: <option>; a warning says when the remote session could not be confirmed revoked. |
init [path]: --organization, --name, --template, --folder, --keep-failed, --no-open, --no-agent-config, --dry-run. | A static workspace prints Created static workspace <id>; uploading managed content; the app-runtime branch reports that it linked the local root to the workspace. Dry run states that no changes were made. | Not a directory: <path>; Template must be one of: html, empty, nextjs, react-vite.; Missing value for <flag>. |
new [name]: --template, --folder, --name, --organization, --keep-failed, --checkout, --no-open, --no-start. | Progress ends by reporting the created path and linked workspace id. | Provide a project name: grain new <name>, or grain new --name <name>.; Checkout-mode workspaces use the canonical checkout path; do not pass a local path with --checkout. |
| Command and help | Expected output | Failure messages |
|---|---|---|
list: --organization, --folder, --query filter the organization tree and workspace names. | Each workspace line contains id, name, folder, source and sandbox status. | Unknown list option: <option>; Missing value for <flag>; Folder not found: <path>. |
use [workspace-id|--clear]: --clear removes the default and --dry-run previews a change. | Reports the selected default workspace by name and id, or prints a clear/no-change message. | Use either a workspace id or --clear, not both.; --dry-run requires a workspace id or --clear. |
status has no command flags. | Lines report loggedIn, workspace, root and sandbox; offline and logged-out states appear as warnings. | Unknown status option: <option>. Workspace and network problems are returned as warnings where possible. |
| Command and help | Expected output | Failure messages |
|---|---|---|
exec <command...> has no CLI flags in its usage. Put -- before a child command that begins with a dash. | Streams the child process output and exits with its status. | Usage: grain exec <command...>; static workspaces report This HTML workspace has no compute runtime. |
shell: --command <command> runs one remote shell command; without it, the shell is interactive. | Streams the remote shell session and returns its exit status. | Missing value for --command; JSON mode reports Interactive shell is unavailable with --json. |
start [path]: --foreground, --restart, --no-pull, --continue, --abort, --no-open, --debounce-ms, --push-interval-ms. | Reports the watched root, then prints synced <n> upsert(s), <n> delete(s) after changes. | --continue and --abort are mutually exclusive; invalid timings report Invalid --debounce-ms value or Invalid --push-interval-ms value. |
stop [path] has no flags. | Stops continuous sync for the linked folder. | Usage: grain stop [path]; checkout folders report A checkout folder does not run the continuous sync daemon. |
| Command and help | Expected output | Failure messages |
|---|---|---|
pull: --force accepts intentional replacement when normal reconciliation is not enough. | pulled <n> remote change(s), deleted <n> local path(s), preserved <n> local change(s). | Unknown pull option: <option>. Usage: grain pull [--force]; an active sync client reports that another sync client holds the workspace lease. |
checkout: --dry-run resolves a checkout path without creating it. | Reports reuse, a planned path, or the workspace id and completed checkout path. | Unknown checkout option: <option>; Use --dry-run only once.; incomplete checkout paths must be removed before retrying. |
checkouts list has no flags. checkouts remove <workspace-id> accepts --discard and --dry-run. | List prints workspace id, path and dirty when applicable. Remove prints Removed checkout or Would remove checkout. | Checkout <id> has unpushed changes. and the action Push the checkout or rerun with --discard. |
push: --force, --no-reload, --dry-run. | pushed <n> path(s); dry run reports proposed upserts and deletes. | Remote drift reports The remote workspace changed since this folder was last synchronized.; an active operation reports a sync-client lease error. |
upload <local-path...>: --to <workspace-dir> changes the destination from the default upload directory. | Prints the archive size while extracting, then Uploaded <destination> for each root. | Usage: grain upload <local-path...> [--to <workspace-dir>]; Missing value for --to; static uploads must run from a linked checkout. |
clone [workspace-id] [path] has no flags. | Reports the cloned workspace id and destination path. | Usage: grain clone [workspace-id] [path]; the target must be a directory and empty; an empty organization reports No workspaces found in this organization. |
| Command and help | Expected output | Failure messages |
|---|---|---|
checkpoint: -m <message> labels the revision and --dry-run previews it. | checkpointed revision #<n> or checkout already matches the latest revision. | Missing checkpoint message. Usage: grain checkpoint [-m <message>] [--dry-run]; Use --dry-run only once. |
restore <revision-number>: --dry-run previews paths and the safety snapshot. | restored revision #<old> as #<new>. | Usage: grain restore <revision-number> [--dry-run]; Use --dry-run only once. |
share: create accepts --public, --password, --path, --name, --no-reuse, --dry-run; update accepts --mode, --password, --regenerate-slug, --name, --path, --dry-run; revoke accepts --dry-run; list has no flags. | Create and update print Share: <url> and Canonical: <url>. List prints each id, mode and URLs or No shares. Revoke prints Revoked: <url>. | --public and --password are mutually exclusive.; --mode must be off, public, or password.; list rejects mutation flags; update and revoke require a share id. |
open has no flags and opens the selected workspace in the desktop app. | Reports that the desktop app was asked to open the selected workspace id. | Usage: grain open; if the app is closed, the action asks you to start it and retry. |
refresh [path] has no flags and asks the desktop app to refresh previews. | Reports that the desktop app was asked to refresh previews for the selected workspace id. | Usage: grain refresh [path]; if the app is closed, the action asks you to start it and retry. |
release: --dry-run previews removal of a clean checkout. | Removed checkout <id> at <path> or Would remove checkout <id> at <path>. | Dirty, sync-mode or invalid checkouts are not removed; unknown flags report Unknown release option: <option>. |
| Command and help | Expected output | Failure messages |
|---|---|---|
mcp has no flags and starts the Model Context Protocol server over standard input and output. | The process stays attached to stdio and responds to MCP requests rather than printing human progress. | Usage: grain mcp when extra arguments are supplied. |
doctor [path] has no flags. | Prints CLI version, authentication, API, session expiry, workspace link and remote root. | Unknown doctor option: <option> or Usage: grain doctor [path] for more than one path. |
upgrade: --target react-vite|nextjs promotes a pushed static workspace to an app runtime. | Returns promotion details; it does not update the CLI binary. | Usage: grain upgrade [--target react-vite|nextjs]; unpushed files report This checkout has local changes that are not in the active managed-content revision. |
Add the global --json option before the command. It emits exactly one envelope and avoids prompts.
Add global --workspace <id> before the command, or set a machine default with the use command.
No. It promotes a pushed static workspace to an app runtime. The Mac app refreshes its bundled CLI when the app updates.
Use it only when you intentionally accept the overwrite described by the command. Normal remote drift should be pulled and reviewed before pushing again.
Follow the first-artifact guide for the five commands that end in a share URL.
Free forever. No card. Bring your own agent.