SproutOS

Use the SproutOS CLI

Install the latest production-approved CLI, sign in, create projects, configure services, and deploy.

The sprout CLI is the command-line client for SproutOS. It uses the same project and deployment contract as the dashboard and the GitHub Action.

Install and verify the CLI

On macOS or Linux, install the latest production-approved release without sudo:

curl --proto '=https' --tlsv1.2 -fsSL https://sproutos.me/install.sh | bash

The installer detects the operating system and architecture, downloads the exact immutable GitHub release selected by SproutOS production, verifies its SHA-256 digest, and installs sprout in ~/.local/bin. Set SPROUT_INSTALL_DIR to choose another directory.

For Windows, or to inspect and verify the files yourself, use the direct macOS, Linux, and Windows downloads on the SproutOS download page. Each promoted release includes SHA256SUMS and a versioned manifest alongside its five platform archives.

Then check the installed version:

sprout --version
# sprout <version>

Sign in and choose an organization

Sign in through your browser, inspect the authenticated identity, and select the organization that later commands should use:

sprout auth login
sprout auth status
sprout org list
sprout org use my-team

Browser login uses PKCE. The resulting scoped credential is stored in your operating system credential store, not a plaintext configuration file. org use verifies that you can access the organization before saving its slug as the default.

To use a different organization for one command, pass the global --org my-other-team option or set SPROUTOS_ORG. For a trusted headless environment, set SPROUTOS_TOKEN; never put that value in a repository or command-line argument. The environment token takes precedence over the saved credential and sprout auth logout does not remove it.

Create a project in an available region

Every new project requires --region. Ask the active control plane for the regions currently accepting projects, then pass one of its exact codes:

sprout region list
sprout runtime list
sprout project create --name my-site --region us-east-1 --blank \
  --preset next --runtime nodejs24.x
sprout project get my-site

Do not copy a region from an old example without checking region list: availability is a control-plane decision. A blank project uses the server's repository visibility default unless you pass --private or --public.

You can instead connect a repository already known to SproutOS:

sprout project create --name my-site --region us-east-1 \
  --repository-id 01900000-0000-7000-8000-000000000000

Use --github-repo-id for a repository visible to the installed GitHub App. For a repository GitHub cannot identify as a fork, add --upstream owner/repository. Root-directory and Dockerfile overrides are optional; leaving them out preserves the source or signed App Store listing defaults.

Install from the App Store

Copy a listing id from the SproutOS App Store and create its project:

sprout project create --name analytics --region us-east-1 \
  --store 01900000-0000-7000-8000-000000000000 \
  --owner my-github-account --repository-name analytics

The platform resolves an exact signed catalogue commit and immutable plugin digest. It creates the destination repository and services; it does not execute instructions discovered in the upstream repository.

Some listings declare setup inputs. Create a JSON array matching the fields shown by the listing, then pass its file:

[
  { "key": "databasePassword", "value": "replace-me", "secret": true },
  { "key": "port", "value": 3000, "secret": false }
]
sprout project create --name analytics --region us-east-1 \
  --store 01900000-0000-7000-8000-000000000000 \
  --template-input-file ./template-inputs.json

Use --template-input-file - to read the array from stdin. This keeps secret values out of shell history and the process list. Inputs cannot override the signed template's declared structure.

Configure services and environment variables

List organization services, create a project-scoped service, and save a secret without putting its value in shell history:

sprout service list
sprout service create --name app-database --kind postgres --project my-site
sprout env set my-site DATABASE_URL --stdin
sprout env list my-site

Service kinds are postgres, valkey, elasticsearch, and object_storage. Environment targets are production, preview, development, and all (the default). Add --public only for values that may be exposed to client-side application code.

Build and deploy

Build your application first, then point sprout deploy at the finished artifact:

sprout deploy my-site --preset next --runtime nodejs24.x --path .next/standalone
sprout deployment list my-site
sprout logs my-site

The CLI packages output deterministically, negotiates the upload, creates a release, and waits for a terminal deployment result. Presets are static, web, next, hono, function, and android. A direct function also requires --handler. Preview deployments use --environment preview; production is the default. Use deployment get or deployment wait with a deployment id when you need to inspect or wait for an existing release.

Production database migrations remain a customer-owned GitHub Actions step; see Run database migrations. Android releases have additional custody and verification steps; see Distribute Android apps.

Project runtime settings supply the normal default; deploy flags override one release without changing it. See Runtimes and framework presets.

Manage upstream updates and project groups

App Store and upstream-backed projects can ask SproutOS to open reviewed update pull requests:

sprout project update analytics --auto-update \
  --auto-update-cadence one_month --auto-update-mode suggest

Use --auto-update-mode auto_merge only when reviewed pull requests should merge automatically after all platform and repository checks pass. A logical group can be created with --group; add a child using --parent-project <group-id> and select its customer-facing project with --primary-child <child-id> on the group.

Script safely with JSON output

Pass the global --json option to receive one versioned JSON document on standard output:

sprout --json project list
sprout --json api get /v1/regions

The api command accepts only a relative path beginning with /; it rejects absolute and scheme-relative URLs before reading the bearer credential. logs --follow --json is the one streaming exception: it emits one complete JSON envelope per line.

Commands that revoke or remove state require an interactive confirmation: auth logout, project delete, env unset, service delete, and template apply. Use --yes to approve one explicitly. JSON mode never prompts, so a destructive JSON command must include both global options:

sprout --json --yes project delete my-site

Run sprout --help or sprout <command> --help for the complete current flag set. The command groups are auth, org, region, runtime, project, env, service, deploy, deployment, logs, android, api, and template.