# turbobase

The command-line interface to your [Turbobase](https://turbobase.io/) instance.

Build and ship the apps your team uses, author the extensions that run inside
your instance, promote a reviewed configuration from sandbox to production, and
give an AI coding agent the context it needs to work against your live data
model — all from one binary, over your instance's HTTP API.

**Full documentation: [docs.turbobase.io](https://docs.turbobase.io/)**

Turbobase is a managed service: your instance is provisioned and operated for
you at [console.turbobase.io](https://console.turbobase.io/). This CLI drives an
instance you already have — it is not a way to run the platform yourself.

## Install

```sh
curl -fsSL https://console.turbobase.io/install-cli.sh | bash
```

On Windows:

```powershell
powershell -c "irm https://console.turbobase.io/install-cli.ps1 | iex"
```

The installer verifies the download's checksum, installs into `~/.turbobase`,
and puts `turbobase` on your PATH — no sudo, no package manager. If the machine
has no suitable Node.js it fetches a private one rather than touching your
system install.

This npm package is the same CLI, for anyone who would rather manage it
alongside their other global tools:

```sh
npm install -g @turbobase/cli
turbobase --version
```

Requires **Node 22, or 24 and newer**.

## Sign in

Mint a personal access token in your Turbobase app under **Settings › Access
tokens**, then hand it to the CLI. This is the only sign-in path.

```sh
turbobase auth login --base-url https://acme.turbobase.app --token tb_pat_xxxxxxxx
```

The instance you last signed in to becomes the **active default**, so you never
repeat `--base-url` for the instance you're working on — pass it only to reach a
*different* stored instance. One machine can hold credentials for many
instances.

```sh
turbobase auth status                           # the active instance (*) and every stored sign-in
turbobase auth use https://beta.turbobase.app   # switch the default, no token re-paste
turbobase auth logout                           # drop a sign-in (--base-url <url> / --all)
```

Credentials live in `~/.turbobase/credentials`, written `0600`. Point
`TURBOBASE_HOME` elsewhere to relocate them. On login the CLI checks that the
URL really serves the instance API and that the token is accepted, and warns
loudly if not; `--no-verify` skips the probe.

→ [Access tokens](https://docs.turbobase.io/tenant/access-tokens/)

## What you can do

Eight groups. Run `turbobase --help` for the list, `turbobase <group> --help` to
go deeper.

| Group | What it does |
| --- | --- |
| `auth` | Sign in, switch the active instance, manage stored credentials. |
| `apps` | Build, preview, and ship hosted apps served inside your Turbobase app. |
| `ext` | Author, test, deploy, and observe extensions — hooks and conduits — plus the marketplace. |
| `project` | Scaffold a project and generate the files an AI agent session reads. |
| `release` | Ship your project from your own CI — deploy, status, rollback, list. |
| `sandbox` | Ephemeral local sandboxes seeded from a redacted slice of an instance (`create` not available yet). |
| `kb` | Write findings into your instance's knowledge base. |
| `mcp` | Run the local authoring MCP server that Claude Code talks to. |

## Ship a hosted app

Hosted apps are served from your instance at `/a/<slug>`, so anyone who can open
your Turbobase app can open them — no separate hosting, no separate login.

Because the app is served same-origin, it inherits your instance's auth: no
sign-in page to build, no callback, no CORS, no app-owned keys. Visitors who
aren't signed in are redirected before your bundle loads, and every read runs
under that user's row-level security.

```sh
turbobase apps init reorder-desk ./app      # scaffold locally (Vite + React + TS)
turbobase apps create reorder-desk          # register the app on your instance
turbobase apps push reorder-desk ./app      # record the source — no build, nothing goes live
turbobase apps deploy reorder-desk ./app    # build and cut a new live version
turbobase apps list
```

`create` is required before the first deploy — or pass `deploy --create` to fold
it in. `init` is local-only and touches nothing on the instance. The build runs
**on your machine**; Turbobase serves the result.

`push` and `deploy` are deliberately separate: `push` records the source on the
instance so the app can be pulled and refined from another machine (or by a
coding agent) with `turbobase apps pull`, while `deploy` is what actually goes
live. Push freely, deploy when ready.

Ship it for review before it goes live. `apps deploy --preview` builds and
serves the result at its own URL and leaves `/a/<slug>` untouched; promoting
re-points the app at **the exact bytes that were reviewed**, with no rebuild:

```sh
turbobase apps deploy reorder-desk ./app --preview
turbobase apps preview list reorder-desk
turbobase apps promote reorder-desk <preview-id>
```

Preview links stop resolving after 7 days; the build stays in deploy history and
can still be promoted. Set the app's display name and description in
`turbobase.json` — the manifest is applied on every deploy. The slug is fixed
once created: it is the URL, and nothing redirects the old one.

→ [Build apps on Turbobase](https://docs.turbobase.io/build-apps/)

## Author and deploy extensions

Extensions run inside your instance. **Hooks** fire on record changes;
**conduits** move data between a source and your mirror.

```sh
turbobase project types                                   # types.ts from your live catalog
turbobase ext new hook --record salesOrder --field memo
turbobase project samples                                 # fixtures from the live catalog
turbobase ext lint hooks/<file>.ts                        # catch semantic foot-guns
turbobase ext test hooks/<file>.ts                        # run it in a production-parity sandbox
turbobase ext deploy hooks/<file>.ts                      # ship it
turbobase ext logs <id> --follow                          # watch it run
```

→ [Writing hooks](https://docs.turbobase.io/extending/writing-hooks/) ·
[Writing conduits](https://docs.turbobase.io/extending/writing-conduits/) ·
[Sandboxes and testing](https://docs.turbobase.io/extending/sandboxes-and-testing/)

## Promote a configuration between environments

Your instance's extension configuration can be snapshotted to a file, reviewed
as code, diffed against a target, and promoted:

```sh
turbobase ext export                        # snapshot the live instance to turbobase/bundle.json
turbobase ext plan --to prod                # diff the local bundle against prod — no writes
turbobase ext deploy --to prod              # apply the whole bundle
turbobase ext promote --from sandbox --to prod --confirm acme
```

`promote` is fail-closed: you type the exact target instance slug to confirm, or
nothing happens.

→ [Deploy, plan, promote](https://docs.turbobase.io/extending/deploy-plan-promote/)

## Work with an AI agent

`turbobase project init` scaffolds a project Claude Code can drive — an
authoring guide, a `.mcp.json` pointing your editor at your instance's MCP
servers, skills, and a session hook that keeps generated types fresh.

```sh
turbobase project init
turbobase project types           # types.ts from the live catalog
turbobase project grounding       # INSTANCE.md — source primer, record anatomy, KB retrieval
turbobase project adopt           # what changed in the platform that this project must act on
```

`grounding` writes the same brief the in-product AI surfaces use, so your editor
answers questions about your data the way your instance does. `adopt` asks the
instance what changed in the releases since you last adopted, and leaves the
file alone when there's nothing new.

The scaffolded `.mcp.json` wires two servers on your instance: an **authoring**
server (scaffold, generate types, dry-run, deploy, tail logs — the same library
functions the subcommands call) and a **data** server (catalog, record anatomy,
knowledge base, RLS-scoped reads). `turbobase mcp` is a separate local stdio
server, for clients you'd rather point at a process than a URL.

> **`.mcp.json` holds a live access token.** The scaffold writes it `0600` and
> adds it to `.gitignore`. Keep it out of version control, and rotate the token
> if it was ever pushed.

→ [Connect Claude Code](https://docs.turbobase.io/build-apps/claude-code/)

## Marketplace

```sh
turbobase ext install acme-recipes
turbobase ext publish hooks/<file>.ts --name acme-recipes --pkg-version 1.0.0
```

Both need a registry credential — set `TURBOBASE_REGISTRY_URL` and
`TURBOBASE_REGISTRY_TOKEN` from the token Turbobase support issues you. It is
separate from your instance's access token and is revocable on its own.
Publishing requires a publisher allowlist.

→ [Marketplace](https://docs.turbobase.io/extending/marketplace/)

## In CI

`turbobase project ci` scaffolds a ready-made GitHub Action that signs in with a
`releases:write` token from your secrets and ships the checkout:

```sh
turbobase project ci     # writes .github/workflows/turbobase-release-deploy.yml
```

It runs in **your** repo on **your** runner and uploads your checkout's bytes —
Turbobase clones nothing and holds no GitHub App key. The CLI is the equal front
door if you'd rather drive it yourself:

```sh
turbobase release deploy --target auto --project . --ref HEAD --follow
turbobase release list
turbobase release rollback <id>
```

`ext lint`, `ext test`, and `ext replay` take `--reporter junit|json`, so
results land in your CI's test report:

```sh
turbobase ext lint hooks/ --reporter junit
turbobase ext test hooks/<file>.ts --reporter junit --ci
```

These commands need no instance and run fully offline: `ext new`, `ext lint`,
`ext test`, `ext replay --fixture`, `project init`, and `project ci`. Everything
else resolves an instance and token from your credential store, and says so
plainly when you aren't signed in. Sign in non-interactively with
`turbobase auth login --base-url … --token "$TURBOBASE_PAT"` from a secret.

`ext test` and `ext replay` execute your extension in a real sandbox, which
needs two native packages. An `npm install -g` already has them; with the
one-line installer, fetch them once with `turbobase ext extras install`
(`turbobase ext extras status` reports what you have).

## Output

Colour, spinners, and progress bars are **chrome, written to stderr**. Command
results — ids, tables, JSON, `--reporter` output, streamed logs — go to
**stdout**, so pipes and captured output are never disturbed. Colour turns
itself off when stdout isn't a terminal, and can be forced off with `--no-color`
or `NO_COLOR=1`.

## Versioning

This package's version is the Turbobase release it shipped with, so
`turbobase --version` tells you which platform release the CLI was built and
tested against. A version reaches the `latest` tag only after that release is
live in production.

→ [Releases and adopt notes](https://docs.turbobase.io/releases/)

## Documentation

- [Getting started](https://docs.turbobase.io/getting-started/what-is-turbobase/) — what Turbobase is, and the path to a live instance
- [CLI overview](https://docs.turbobase.io/cli/overview/) — installing, signing in, and the shape of the tool
- [CLI reference](https://docs.turbobase.io/cli/reference/) — every command, its flags, and an example
- [Build apps on Turbobase](https://docs.turbobase.io/build-apps/) — building against your instance
- [Extending Turbobase](https://docs.turbobase.io/extending/writing-hooks/) — hooks, conduits, sandboxes, promotion

Questions the docs don't answer: [support@turbobase.io](mailto:support@turbobase.io).

## Licence

Proprietary — see `LICENSE`. You may install and run it to build, test, and
deploy against instances you are authorised to access, including on your own CI
runners. Redistribution and reverse engineering are not permitted.
