Getting started

Prerequisites

1. Install the CLI and the SDK

Until the SDK packages are published, both come from this repo:

git clone git@github.com:RabiaMakhoul/fluffy-chainsaw.git
cd fluffy-chainsaw && go install ./cmd/fluffy-chainsaw   # → $(go env GOPATH)/bin, put that on PATH
cd sdk/typescript && npm install && npm run build        # build the SDK once

Then in your app ("type": "module" in package.json — the SDK is ESM):

npm install <path-to-clone>/sdk/typescript   # @org/fluffy-chainsaw; companions: -storage, -pubsub, -auth

2. Write markers

The SDK is dumb on purposedb.connect returns a plain descriptor, never a client; bring your own driver (pg, Drizzle, …).

[!IMPORTANT] The fluffy-chainsaw scanner only parses TypeScript files (.ts, .tsx, .mts, .cts) when scanning the codebase for capability markers. Raw JavaScript (.js, .mjs, .cjs) is not supported for resource discovery.

// src/index.ts
import { db, cloudrun } from "@org/fluffy-chainsaw";

const users = db.connect("users");        // "database `users` must exist"

cloudrun.entrypoint("orders-api", async (_req, res) => {
  res.end(`connected to ${users.database}`);
});

3. Tune them in fluffy-chainsaw.yaml

Next to the app (default <dir>/fluffy-chainsaw.yaml):

defaults:
  databases: { instance: app-db }   # every database lives on this server

databases:
  users: { extensions: [pgcrypto] }

instances:                          # the Cloud SQL server(s) — declared here, no code marker
  app-db: { tier: db-custom-1-3840 }

runners:
  orders-api:
    uses: { databases: [users] }
    trigger: { http: true }         # public; omit for private (IAM-only)
    build: { target: orders-api }   # make target that prints the image ref

4. Run locally

fluffy-chainsaw local --deps-only -out .env   # containers for deps + a .env with every descriptor
node --env-file=.env src/index.ts

Real-enough substitutes: Postgres, emulators, filesystem buckets — same app code, only the env differs. Without --deps-only your runners run containerized too (needs the step-5 Makefile), in dev mode: the repo is mounted at /repo and each runner runs node --watch, so code edits restart it in-place — no image rebuild; only fluffy-chainsaw.yaml changes need a re-run. fluffy-chainsaw local-prune tears it down.

[!NOTE] --deps-only only spins up Postgres databases and filesystem buckets. If your app uses the Firebase auth: or realtime: plugins, the corresponding emulators are not started by --deps-only and require running the full containerized mode (fluffy-chainsaw local without flags) with a Makefile.

5. Deploy

Runner images build through your make target: a Makefile whose target prints the image ref as its last stdout line, and a Dockerfile that vendors the unpublished SDK into the image and follows the local dev-mode convention — WORKDIR under /repo mirroring your repo layout, exec-form CMD ["node", "<entry>"] (see runners.md). Then:

fluffy-chainsaw deploy -project <gcp-project> -region <region>

One shot: validates config, builds images, generates the Pulumi program, applies it. The pipeline owns its plumbing deterministically — state backend gs://fluffy-chainsaw-state-<project> (created on first use), stack dev, the documented default passphrase dummy, stack config seeded from the flags, and every needed GCP API enabled by the program itself, retrying while enablement propagates. Overrides: PULUMI_BACKEND_URL, PULUMI_CONFIG_PASSPHRASE. A fresh project needs billing + the gcloud logins, nothing else. Firebase stages run only for auth/Hosting apps. Individual steps: cli.md.