---
title: "Scripts and CI"
description: "Run the CLI without prompts, read JSON results, and handle exit codes in scripts and CI."
canonical_url: "https://docs.linguana.dev/docs/cli/automation"
markdown_url: "https://docs.linguana.dev/docs/cli/automation.md"
x_farming_labs_generated_preamble: true
---

# Scripts and CI
URL: /docs/cli/automation
LLM index: /llms.txt
Description: Run the CLI without prompts, read JSON results, and handle exit codes in scripts and CI.
Related: /docs/automate/ci-cd, /docs/cli/commands

# Use the CLI in scripts and CI

Every CLI command can run without prompts. Noninteractive commands never wait for input: they use a default where one exists and otherwise fail immediately with exit code `2` and a message naming the option to supply.

## When the CLI is interactive

The CLI prompts only when both standard input and standard output are terminals and you passed neither `--yes` nor `--json`. In CI, pipes, and redirected output, it is noninteractive automatically.

`--yes` makes a terminal session noninteractive and accepts the defaults below. It never chooses connected mode, creates resources you did not name, or replaces conflicting credentials.

| Choice | Noninteractive behavior |
| --- | --- |
| `create app` template and framework | Required: `--template` and `--framework` |
| `create app` mode | Required: `--demo` or `--connect` |
| `create app` directory | `my-<template>` |
| Package manager | Detected from the invoking package manager, otherwise npm |
| Sign-in | Not started; connected commands fail with `LOGIN_REQUIRED` |
| Organization | Your only organization is selected; with none, `--new-organization` is required; with several, `--organization` is required |
| Project | Created with the directory name when the organization has none; otherwise `--project` or `--new-project` is required |
| Languages for a new project | French, Spanish, and Arabic, when available; pass `--locales` to choose |
| Conflicting environment values or an invalid existing token | Preserved, and the command fails with `ENV_CONFLICT`; pass `--overwrite-env` to replace |

## JSON output

Add `--json` to print one JSON object on standard output. Progress messages, notices, and package-manager output go to standard error, so standard output stays parseable.

```bash title="terminal"
npx @linguanahq/cli create app smoke-test \
  --framework react --template blog --demo \
  --skip-install --json
```

```json title="output"
{"directory":"/home/runner/work/smoke-test","framework":"react","template":"blog","mode":"demo","nextCommand":"npm run dev"}
```

Failures print an error object on standard output instead:

```json title="output"
{"error":{"code":"INPUT_REQUIRED","message":"Connect Linguana or try a demo? Supply an explicit option when running noninteractively."}}
```

Without `--json`, errors go to standard error prefixed with `Linguana:`. JSON results never include account sessions or build tokens, and error messages redact anything that looks like a Linguana token or an authorization header. See the [command reference](/docs/cli/commands) for each command's JSON shape.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success |
| `1` | Operational failure, such as a network, permission, or API error, or a failed `doctor` check |
| `2` | Invalid input, conflicting options, or a missing noninteractive choice |
| `130` | Canceled with Control-C or a canceled prompt |

## Recipes

### Smoke-test template generation

Demo mode needs no account or secrets, so it is safe in any pipeline:

```bash title="terminal"
npx @linguanahq/cli create app smoke-test \
  --framework tanstack-start --template storefront --demo \
  --package-manager npm --yes
cd smoke-test
npm run check-types
npm run build
```

### Provision a project from a script

Connected commands need an account session. On a workstation, run `login` once; later noninteractive commands reuse the saved session:

```bash title="terminal"
npx @linguanahq/cli login
npx @linguanahq/cli create app my-product \
  --framework tanstack-start --template saas --connect \
  --organization ORGANIZATION_ID --new-project "My product" \
  --locales fr,es,ar --yes --json
```

For controlled automation, `LINGUANA_AUTH_TOKEN` may supply an account session, and `LINGUANA_CONFIG_DIR` can isolate saved sessions from the user's own. `LINGUANA_AUTH_TOKEN` must not contain a project build token; the CLI rejects those with `WRONG_TOKEN_TYPE`. Never put an account session in app configuration or browser variables, and store it as a protected CI secret.

### Build in CI without the CLI

Most pipelines do not need the CLI. Builds upload with a project token, which is narrower than an account session: it is scoped to one project and environment and cannot create projects or credentials.

1. Create a project token for the target environment in **Tokens** in the dashboard, or run `env pull` locally.
2. Store `LINGUANA_PROJECT_TOKEN` as a protected CI secret, and the public `LINGUANA_*` and `VITE_LINGUANA_*` values as CI variables.
3. Run your normal build. See [Automate translations in CI](/docs/automate/ci-cd).

<SecurityNote>
Do not run `link`, `env pull`, or connected `create app` in untrusted pull-request jobs. They require an account session that can create projects and credentials with its owner's permissions.
</SecurityNote>

<NextStep>
Look up every flag in the [command reference](/docs/cli/commands).
</NextStep>

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
