Continuous Integration | Ghostable CLI 3.x | Ghostable                              Menu

 Continuous Integration

   CI principles
-------------

- Pass all selections as flags; CI has no interactive prompt session.
- Prefer `--json`, `--format github`, or `--sarif` over parsing human output.
- Use one scoped automation credential per trust boundary.
- Do not enable `--show-values` or echo `GHOSTABLE_CI_TOKEN`.
- Keep production credentials out of untrusted pull-request jobs.

 Create CI access
----------------

From an owner device:

 CI credential     Copy

 ```
$ ghostable access create --name github-actions --kind ci --grant staging:reader

```

 Store the returned token in the CI platform as `GHOSTABLE_CI_TOKEN` and commit the generated public device, policy, and access-grant changes. A reader grant is sufficient for validation, review, and test-time decryption.

 Validation and review
---------------------

 CI checks     Copy

 ```
$ ghostable validate --env staging --json
$ ghostable review --base origin/main --head HEAD --format github
$ ghostable hygiene report --env staging --sarif

```

 Pass an explicit base in CI so comparisons do not depend on checkout tracking configuration. Validation, review, and scan exit non-zero when actionable findings remain. Hygiene reports findings in its payload but exits successfully unless execution itself fails, so enforce hygiene thresholds through the SARIF consumer or a separate policy step.

 Run tests with values
---------------------

Inject values into the test process without writing a persistent env file:

 Test with injected values     Copy

 ```
$ ghostable env run --env staging --no-inherit --mask-output --strict -- npm test

```

 `--no-inherit` reduces ambient runner variables, `--mask-output` replaces exact injected values found in child stdout and stderr, and `--strict` fails when requested configuration is missing or invalid. Masking is best effort: encoded, transformed, split, or file-written values can still escape. The runner can access decrypted process memory, so use an isolated CI environment.

 Pull-request safety
-------------------

  Forked code is untrusted

 Do not expose a Ghostable token to workflows executing code from forks or unreviewed pull requests. A malicious test can read process environment, memory, or files after Ghostable decrypts values, even when command output is masked.

Run repository-only secret scanning without credentials on untrusted changes, and reserve decryption for protected branches or reviewed deployment jobs.

 Automation contract
-------------------

   `stdout`  Automation-oriented output is written here when --json, --format github, or --sarif is supported and selected.

  `stderr`  Usage, verification, runtime, and final failure messages are written here. A failing JSON command may still emit a complete JSON result on stdout.

  `Exit 0`  The command completed and its checks passed.

  `Exit 1`  Invalid usage, a runtime or verification error, or findings from commands that fail checks such as validate, review, and scan. Hygiene reports findings without failing by default.

  `Exit 130`  An interactive prompt was canceled.

  `env run`  Returns the child process exit code when that process starts and exits unsuccessfully.

 Structured formats are available only when the command's `--help` lists them. Version-lock the CLI, ignore unknown JSON fields, and never assume structured output is secret-free: credential creation intentionally returns its token, while value-reading commands remain redacted unless plaintext output is explicitly requested.

See the [command reference automation contract](https://ghostable.dev/docs/3.x/reference/commands#automation-contract) for the supported formats and a validation payload example.

 Example pipeline
----------------

 This GitHub Actions workflow scans pull requests without a credential and limits decryption to pushes on the protected `main` branch. Store `GHOSTABLE_CI_TOKEN` as a repository or environment secret available only to the protected job.

 ```
name: Ghostable

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  scan-untrusted:
    if: ${{ github.event_name == 'pull_request' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx ghostable review --base "origin/${{ github.base_ref }}" --head HEAD --secrets-only --format github

  protected-checks:
    if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
    runs-on: ubuntu-latest
    env:
      GHOSTABLE_CI_TOKEN: ${{ secrets.GHOSTABLE_CI_TOKEN }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx ghostable validate --env staging --json
      - run: npx ghostable review --base "${{ github.event.before }}" --head "${{ github.sha }}" --format github
      - run: npx ghostable env run --env staging --no-inherit --mask-output --strict -- npm test
```

Pin `@ghostable/cli` and commit the lockfile so CI and developers execute the same 3.x release.

    On this page

    [ ![Ghostable](https://ghostable.dev/images/logo-dark.svg) ![Ghostable](https://ghostable.dev/images/logo-light.svg) ](https://ghostable.dev)

   CLI 3.x     [   CLI 3.x ](https://ghostable.dev/docs/3.x) [   Desktop ](https://ghostable.dev/docs/desktop)

  CLI 3.x introduction Documentation local first no login encrypted repository plaintext hosted service

  Installation Documentation brew homebrew npm npx linux windows PATH version update

  Start a new project Getting Started setup seed dotenv owner initialize

  Adopt an existing project Getting Started existing env import authoritative source adopt

  Onboard a team member Getting Started join request approve roles offboarding pull request

  Repository and storage Core Concepts .ghostable git conflict merge worktree private identity metadata

  Environments Core Concepts protected production preview staging push sync pull replace run mask-output

  Variables and promotions Core Concepts var promote copy context annotation key

  Access and devices Core Concepts identity reader writer grantor owner revoke rotate leave delete

  Daily development workflow Workflows pull diff validate review clean daily

  Review and secret scanning Workflows scan sarif github suppress secrets drift

  Hygiene and rotation Workflows rotation stale unused suppression environment key

  Automation credentials Automation &amp; CI GHOSTABLE\_CI\_TOKEN ci deploy credential powershell revoke replace

  Continuous integration Automation &amp; CI GitHub Actions fork pull request JSON stdout stderr exit codes mask-output

  Deployments Automation &amp; CI Forge Vapor Cloud provider CLI dry-run preserve remote keys temporary files

  Validation Reference schema required nullable regex min max different\_from

  Command reference Reference --help --json NO\_COLOR flags aliases exit code automation

  Configuration Reference ghostable.yaml activity mode auditEnvironments scan ignores deployTarget dotenv syntax

  Security Reference cryptography XChaCha20 Poly1305 HKDF user presence threat model

  Backups &amp; Offline Reference recovery offline restore clone key identity

  Agent integration Reference AGENTS.md capabilities allowlist coding agent

  Troubleshooting Reference no project found revoked identity stale policy user presence invalid CI token provider CLI git conflict diagnostics

  Ghostable Desktop overview Desktop

  Installation Desktop

  Projects and setup Desktop

  Interface tour Desktop

  Environments and variables Desktop

  Local environment files Desktop

  Validation and review Desktop

  Activity Desktop

  Access and automation Desktop

  Project settings Desktop

  Application settings Desktop

  Licensing and updates Desktop

  Security and storage Desktop

  Troubleshooting Desktop    No results found
