Skip to Content
Develop locally (CLI)

Develop locally with the bool CLI

The bool CLI lets you build an app on your own machine, use a Bool project as its backend (entities, records, end-user auth), and publish to Bool hosting — all from the command line. Your local code reads and writes the project’s real data through the same gateway a deployed Bool uses; there’s no separate local database to keep in sync.

Before you start

Local development talks to a project through the Bool gateway, so the project must be a gateway-backed project. bool create makes one for you, so the quickest start is to let the CLI create the project and the app together (below).

If instead you want to link an existing project and it was created before gateway support, linking fails with:

This project runs on the v1 runtime (no gateway), so it can't be used as a managed backend from a local app. Create a new project to get the gateway runtime.

You have two ways forward: start a new project with bool create (or the Bool editor) and develop against that, or have Bool make an upgraded copy of the existing one and link that instead — see Upgrading an older app’s backend.

You’ll also need a personal access token for the CLI to authenticate. Create one at Settings → API tokens and either pass it with --token or export it as BOOL_TOKEN (see Environment variables).

Install

Install once, globally, to get bool on your PATH:

npm install -g bool-sdk

Stable since bool-sdk@0.3.0 — no tag needed. A next channel still carries prereleases if you want to test something unreleased.

Prefer not to install globally? Add bool-sdk as a dev dependency and prefix commands with npx (npx bool <command>). The rest of this page uses the global bool form.

Quick start

Create a project and a working todo app in one step, then publish it:

export BOOL_TOKEN=<your-access-token> # from Settings → API tokens bool create my-todos --deploy

This creates a gateway-backed project, scaffolds a Vite + React todo app wired to it through bool-sdk, links the two (writing bool.config.json, .env.bool, and generated types), declares a public todos entity, and — with --deploy — publishes it to a live URL. Drop --deploy to stop after scaffolding and run it locally first:

cd my-todos npm install npm run dev # reads and writes your Bool project's real data bool deploy # publish when ready

The project name is optional — a bare bool create picks a friendly name and scaffolds into a matching folder.

Commands

bool create [name]

Scaffold a new Bool project and a matching todo app in one command, then link and (optionally) deploy it.

bool create my-todos # create project + scaffold ./my-todos bool create my-todos --path apps/todos # scaffold into a specific folder bool create my-todos --deploy # also publish it immediately

create checks that the new project is ready for local development before it writes any files — if it isn’t, the command stops and scaffolds nothing.

Connect a folder you already have to an existing Bool project.

bool link --project <id>

Writes three files into the current directory:

  • bool.config.json — public connection config (commit this)
  • .env.bool — the project’s admin data key, BOOL_API_KEY (gitignored — keep it secret; link adds it to .gitignore for you)
  • bool/types.d.ts — generated TypeScript types for your entities

Then wire up the client (see Using the client).

The admin data key is written only for the project owner; a collaborator’s link still works for types, entities, and deploy — they just supply their own key.

bool types

Regenerate bool/types.d.ts from the project’s current entity schemas. Run it after changing your data model so your editor’s types match.

bool types

bool entities

Inspect and manage your data model.

bool entities # list the project's entities and their fields bool entities pull # write the project's schemas into bool/entities/ bool entities push # declare local bool/entities/*.jsonc on the project

push reads bool/entities/ by default; pass --dir <path> to point elsewhere. Schema changes are additive migrations applied server-side — you add entities and fields; existing data is preserved.

See Entity schema files for the file format.

bool deploy

Zip the app’s source and publish it. Bool builds in the cloud and serves it at a stable URL.

bool deploy bool deploy --dir apps/todos # deploy from a subdirectory bool deploy --token <access-token> # use an explicit token

Build output, dependencies, and machine-local files (node_modules, dist, .git, bool.config.json, .env*) are excluded from the archive automatically. There’s a size cap on the uploaded archive; if you exceed it the CLI reports the exact limit — see Troubleshooting for how to slim a deploy.

Entity schema files

Entities live in bool/entities/ as .jsonc files (JSON with comments). Each file is a JSON-Schema object with a top-level name, a properties map, and Bool’s x-bool-access keyword. Bool manages id, created_at, and (on private entities) owner_iddon’t declare those yourself.

A public entity is one shared table anyone can read and write (no sign-in):

{ "name": "todos", "type": "object", "properties": { "title": { "type": "string", "description": "The task text" }, "completed": { "type": "boolean", "default": false } }, "required": ["title"], "x-bool-access": "public" }

A private entity gives each signed-in user their own rows. Set "x-bool-access": "private" and Bool adds an owner_id column plus row-level security — you never declare owner_id in properties:

{ "name": "tasks", "type": "object", "properties": { "title": { "type": "string" }, "done": { "type": "boolean", "default": false } }, "required": ["title"], "x-bool-access": "private" }

For a private entity, owner_id defaults to the signed-in user, so app code doesn’t set it. But the admin data key (BOOL_API_KEY) has no end-user identity, so a create from a local script or backend must pass owner_id explicitly:

// Signed-in end user — owner_id is filled in automatically: await bool.entities.tasks.create({ title: "Buy milk" }); // Admin key (BOOL_API_KEY) — no identity, so set owner_id yourself: await bool.entities.tasks.create({ title: "Buy milk", owner_id: userId });

Using the client

After create or link, create the client from the generated config:

import { createBoolClient } from "bool-sdk"; import config from "./bool.config.json"; export const bool = createBoolClient({ supabaseUrl: config.supabaseUrl, supabaseAnonKey: config.supabaseAnonKey, schema: config.schema, appOrigin: config.appOrigin, slug: config.slug, apiKey: process.env.BOOL_API_KEY, // from .env.bool; VITE_BOOL_API_KEY in Vite }); const todos = await bool.entities.todos.list("-created_at"); await bool.entities.todos.create({ title: "Ship it" });

Live data in React

The methods above are one-shot promises — right for scripts, event handlers, and anything outside React. For a screen, use useQuery on the same handler instead: it loads the rows, keeps them current as anyone else changes them, and makes your own writes appear instantly (undoing them if the save fails).

import { bool } from "./bool"; // wherever you created the client function Todos() { const todos = bool.entities.todos.useQuery({ filter: { done: false }, sort: "-created_at" }); if (todos.loading) return <Spinner />; if (todos.error) return <button onClick={() => todos.refetch()}>Couldn't load — retry</button>; return ( <> {todos.data.map((t) => ( <label key={t.id}> <input type="checkbox" onChange={() => todos.update(t.id, { done: true })} /> {t.title} </label> ))} <button onClick={() => todos.create({ title: "New" })}>Add</button> </> ); }

useQuery is a React hook, so the usual rules apply — call it at the top of a component, unconditionally. It takes the same filter and sort you’d pass to .filter(...), plus limit, and an inline options object is fine (no useMemo needed). Handle all three states: loading, error, and the rows — rendering only data turns a failed load into a convincing empty screen.

One setup step: the hook lives in the React entry point, so your app must import it once — import "bool-sdk/react"; next to where you create the client. Apps Bool generates already have this line. Without it, useQuery throws an error telling you exactly this.

Environment variables

BOOL_TOKEN

Your personal access token, used to authenticate CLI calls to the Bool platform (create, link, types, entities, deploy).

export BOOL_TOKEN=<your-access-token>

Get one from Settings → API tokens. You can also pass --token on any command instead of exporting it.

BOOL_API_KEY

The project’s admin data key, written to .env.bool by link/create. Pass it to createBoolClient as apiKey so local code can read and write the project’s data. It has full access to every row, so it’s for your own scripts and local development only — never ship it in client code. Deployed apps don’t use it; their end users authenticate through Bool auth instead.

Troubleshooting

command not found: bool — the global install didn’t land on your PATH. Reinstall with the -g flag (npm install -g bool-sdk); if it’s still missing, check npm bin -g and add that directory to your shell profile, or skip the global install and use npx bool <command>.

No access token — set BOOL_TOKEN (or pass --token). Create the token at Settings → API tokens.

This project runs on the v1 runtime — the project you’re linking predates gateway support and can’t be used as a local backend. Either create a new project with bool create, or upgrade the existing one and link the upgraded copy.

Archive is over the size limit — the CLI prints the exact cap. Slim the deploy by removing unused dependencies, splitting code / using dynamic imports, moving large assets to a CDN, or trimming your schema.

Types out of date — run bool types to regenerate bool/types.d.ts from the project’s current schemas.

Learn more

Last updated on