Skip to content

fusebase-dev/fusebase-cli

Repository files navigation

Fusebase Apps CLI

A command-line tool for managing Fusebase applications. Build, develop, and deploy apps to the Fusebase platform.

Architecture

See Architecture for detailed documentation on the CLI's architecture, command system, configuration, and development workflow.

For deeper understanding of:

  • MCP integration
  • API client layers (legacy vs SDK)
  • LLM capability discovery
  • Core concepts (products, apps, data access)

See:

CLI Usage

See CLI Commands & Interactive Prompts for comprehensive documentation on all available commands, options, and interactive prompts.

Installation

Prerequisite: Bun v1.0+ — the CLI runs as a Bun script and requires Bun at runtime regardless of how you install it.

Install Bun if you don't have it:

curl -fsSL https://bun.sh/install | bash

The CLI is not published to npm. Install globally from this repo:

Option 1 – Install from Git:

bun install -g git+https://github.com/fusebase-dev/fusebase-cli.git

Bun downloads the package and links the fusebase binary globally.

Option 2 – Link from a local clone (for development):

cd /path/to/apps-cli
bun install
npm link

Then run fusebase from anywhere. Use npm link, not bun link --global — Bun does not add the package bin to your PATH.

Run without installing:

cd /path/to/apps-cli
bun index.ts [command]

Commands

fusebase version

Print CLI version (from package.json).

fusebase auth [--api-key <apiKey>]

Set the API key for authentication with the Fusebase API.

Options:

Option Description
--api-key <apiKey> The API key to store. If not provided, the OAuth auth flow is started.
--dev Use the dev environment

Example:

# Interactive mode
fusebase auth

# Direct mode
fusebase auth --api-key=your-api-key-here

# Use dev environment
fusebase auth --api-key=your-api-key --dev

fusebase init

Initialize a new Fusebase app in the current directory. This command will:

  1. Prompt you to select an organization (or use the only one if there's just one)
  2. Let you select an existing app or create a new one
  3. Optionally copy a project template if the directory is empty
  4. Create a fusebase.json configuration file

Arguments: None

Options:

  • --name <name> - App title/name (if not provided, prompted)
  • --subdomain <subdomain> - App subdomain (e.g. my-app)
  • --org <orgId> - Organization ID (skips org selection)
  • --ide <preset> - IDE preset: claude-code, cursor, vscode, opencode, codex, or other (single choice; generates all IDE configs by default)
  • --force - Overwrite existing IDE config files/folders
  • --git - After setup, initialize local Git and sync with configured GitLab remote (creates/uses repo in <gitlabGroup>/<dev|prod>/..., sets origin, pushes current branch)
    • Also enabled automatically if global flag git-init is active (fusebase config set-flag git-init)
  • --skip-git - Skip local Git initialization and GitLab sync (overrides both --git and global git-init)
  • --git-tag-managed - If app is managed, add managed topic to the GitLab project during sync
    • In interactive init, CLI shows a suggested GitLab repo name and lets you edit it before sync

Interactive Prompts:

  • Organization selection - Choose from your available organizations
  • App selection - Choose an existing app or create a new one
    • When creating a new app: enter title and subdomain
  • Project template - If directory is empty, the template is used automatically. If not empty, you'll be asked whether to continue in the current folder.
  • IDE configuration - MCP config is generated for all supported IDEs by default (unless --ide is provided); required MCP servers from the catalog (respecting flags) are written automatically. Optional servers are not configured during init — run fusebase integrations later.
  • App name - Name for package.json (if using template)

Example:

mkdir my-app
cd my-app
fusebase init

Output:

Creates a fusebase.json file with the following structure:

{
  "orgId": "your-org-id",
  "productId": "your-app-id"
}

fusebase git

Initialize a local Git repository in the current directory (git init), ensure baseline .gitignore, and print local workflow hints.

fusebase git sync [--git-tag-managed]

Sync the current local repository with GitLab using global config from ~/.fusebase/config.json:

  • gitlabHost (for example gl.nimbusweb.co)
  • gitlabToken
  • gitlabGroup (base namespace; env subgroup dev/prod is selected from current auth env)

Behavior:

  • Creates/uses GitLab project with visibility private
  • Project name is generated as app-<base>-<env> (for example app-workspace-tools-dev)
  • Base priority: Fusebase app title (with transliteration fallback for Cyrillic) → current folder name → app subdomain
  • Configures local origin (without overwriting existing different origin)
  • Pushes current branch to remote
  • With --git-tag-managed, applies topic managed for managed apps
  • Equivalent short form: fusebase git --git-sync [--git-tag-managed]

Config example:

{
  "gitlabHost": "gl.nimbusweb.co",
  "gitlabToken": "glpat-xxxxxxxxxxxxxxxx",
  "gitlabGroup": "vibecode"
}

Examples:

cd my-app
fusebase git
fusebase git sync
fusebase git sync --git-tag-managed

fusebase app list

List all apps for the current app with their URLs.

Arguments: None

Options: None

Prerequisites:

  • App must be initialized (fusebase init)
  • API key must be configured (fusebase auth)

Example:

fusebase app list

Output:

Apps:

  My App
    ID:   app-id-123
    URL:  https://your-app-id.thefusebase.app/my-app
    Permissions:
      ID               Title             Type
      ---------------  ----------------  --------
      dashboard-id-123 Sales Dashboard   Table
      database-id-456  Customer Database Database

Total: 1 app(s)

fusebase deploy

Deploy apps to Fusebase. For each app this command will:

  1. Install dependencies and run lint (if the app has a lint script in its package.json)
  2. Run the build command (if configured)
  3. Compute a SHA-256 frontendHash of the upload directory and a backendHash of the backend/ folder (if present)
  4. Compare those hashes against the active version and take one of:
    • No changes → skip the app entirely (no new version, no upload, no backend deploy). Logs ✓ No changes for app, skipping deploy.
    • Frontend unchanged, backend changed → create a new version, reuse the previous frontend bundle via copyFrontendParams (no upload), then re-deploy the backend.
    • Frontend changed → create a new version, upload files, persist the new frontendHash. Backend is handled per its own hash (skipped/copied or re-deployed).
  5. With --force, hash matches are ignored and a full upload + redeploy runs for every app.
  6. If the app contains openapi.json and the app-api-registry flag is enabled, validate it and publish the app API manifest to the app registry.

Arguments: None

Options:

Option Description
--force Force re-upload and re-deploy regardless of frontend/backend hash match

Prerequisites:

  • App must be initialized (fusebase init)
  • API key must be configured (fusebase auth)
  • At least one app must have a path configured in fusebase.json

Examples:

# Skips apps with unchanged frontend + backend
fusebase deploy

# Always uploads and redeploys
fusebase deploy --force

App Configuration in fusebase.json:

{
  "orgId": "...",
  "productId": "...",
  "apps": [
    {
      "id": "app-id",
      "path": "apps/my-app",
      "build": {
        "command": "npm run build",
        "outputDir": "dist"
      }
    }
  ]
}

fusebase api validate [--file <path>]

Validate the app OpenAPI contract for the Phase 1 app API MVP.

Behavior:

  • looks for openapi.json in the current directory by default
  • also detects openapi.yaml / openapi.yml, but YAML validation is not supported in this MVP yet
  • validates:
    • OpenAPI 3.1
    • info.title
    • info.version
    • operation presence
    • unique operationId
    • basic x-fusebase-* fields

Examples:

fusebase api validate
fusebase api validate --file openapi.json

Output:

  • success summary with title, version, and operation ids
  • or a list of validation issues with JSON paths

fusebase app update <appId>

Update settings for an existing app.

Arguments:

Argument Required Description
appId Yes The ID of the app to update

Options:

Option Description
--access <principals> Set access principals, comma-separated (e.g., visitor, orgRole:member)
--permissions <permissions> Replace dashboardView/database permissions
--sync-gate-permissions Analyze the app path and replace gate permissions

Access Principals:

The --access option replaces the entire access principal list. Principals are comma-separated entries:

Principal Description
visitor Any unauthenticated visitor (public access)
orgRole:<id> Org members with a specific role. Valid ids: guest, client, member, manager, owner

Examples:

# Make an app publicly accessible
fusebase app update feat_abc123 --access=visitor

# Allow org members only
fusebase app update feat_abc123 --access=orgRole:member

# Allow multiple roles
fusebase app update feat_abc123 --access=orgRole:member,orgRole:client

# Public access + org members
fusebase app update feat_abc123 --access=visitor,orgRole:member

# Replace dashboard/database permissions only
fusebase app update feat_abc123 --permissions="dashboardView.dash_1:view_1.read;database.id:db_1.write"

# Sync Gate permissions only
fusebase app update feat_abc123 --sync-gate-permissions

# Replace dashboard/database and Gate permissions in one request
fusebase app update feat_abc123 --permissions="dashboardView.dash_1:view_1.read" --sync-gate-permissions

See App Permissions for the full permissions model and merge semantics.


fusebase app create

Create and configure an app for development.

Options:

Option Description
--name <name> (Required) App title
--subdomain <subdomain> (Required) Subdomain for the app (e.g., my-app)
--path <path> (Required) Local app directory path (e.g., apps/my-app)
--dev-command <command> (Required) Dev server command (e.g., npm run dev)
--build-command <command> (Required) Build command (e.g., npm run build)
--output-dir <dir> (Required) Build output directory (e.g., dist)
--access <principals> Set access principals on creation (e.g., visitor, orgRole:member)
--permissions <permissions> Set manual dashboardView/database permissions

Example:

fusebase app create --name="My App" --subdomain=my-app --path=apps/my-app --dev-command="npm run dev" --build-command="npm run build" --output-dir=dist

If you later scaffold a backend into that app with:

fusebase scaffold --template backend --dir apps/my-app

the CLI creates openapi.json automatically if it does not already exist.

The spa feature template ships a built-in /link route that handles app magic links: it reads ?id=…&redirect=… from the URL, calls the Gate activation endpoint (POST /apps/magic-links/{id}/activate), persists the returned tokens as cookies (fbsfeaturetoken for the Gate feature token, fbsdashboardtoken for the dashboard-service feature token, eversessionid for the session), and redirects to the deep page. Expired, revoked, and not-found cases each render a tailored UI inline, so closed-access apps work for one-click client onboarding without extra wiring. The Gate base URL is auto-derived from window.location.hostname for Fusebase-managed app domains; for custom domains set VITE_FUSEBASE_GATE_URL=https://<your-gate-host>/v4/api/proxy/gate-service/v1 at build time (Vite inlines import.meta.env.VITE_* into the bundle). See project-template/.claude/skills/fusebase-gate/references/app-magic-links.md for the full Gate contract (invite vs self-service vs activate).

Updates fusebase.json:

{
  "orgId": "...",
  "productId": "...",
  "apps": [
    {
      "id": "app-id",
      "path": "apps/my-app",
      "dev": {
        "command": "npm run dev"
      },
      "build": {
        "command": "npm run build",
        "outputDir": "dist"
      }
    }
  ]
}

fusebase dev start [app]

Start the development server for an app. This command:

  1. Starts the app's dev server (if dev.command is configured)
  2. Starts the Fusebase dev server UI (port 4173)
  3. Starts the API proxy server (port 4174)
  4. Creates a per-session debug log folder under the selected app directory at logs/dev-<timestamp>/
  5. Opens the dev UI in your browser

Arguments:

Argument Required Description
app No App ID or path (from fusebase.json apps). If not provided, you'll be prompted to select one.

Options: None

Prerequisites:

  • App must be initialized (fusebase init)
  • API key must be configured (fusebase auth)
  • At least one app must be configured in fusebase.json

Example:

# Interactive app selection
fusebase dev start

# Start specific app by ID
fusebase dev start my-app-id

# Start specific app by path
fusebase dev start apps/dashboard

Dev Server Components:

Component Port Description
Frontend UI 4173 React app that displays apps in iframes
API Proxy 4174 Proxies requests to Fusebase API with authentication

Per-session Debug Logs:

Each fusebase dev start run creates a session folder inside the selected app directory:

<app-dir>/logs/dev-<timestamp>/
  browser-logs.jsonl
  access-logs.jsonl
  backend-logs.jsonl
  frontend-dev-server-logs.jsonl

App Token Flow:

The dev server automatically handles app token delivery:

  1. Fetches app tokens from the Fusebase API
  2. Sends tokens to the app iframe via postMessage
  3. Sets cookie fbsapptoken so same-origin app backend requests can authenticate without relying on a custom header
  4. Your app receives the token:
window.addEventListener('message', (event) => {
  if (event.data?.type === 'featuretoken' && event.data?.token) {
    // Use event.data.token for API calls
  }
});

For custom app backends (/api/*), treat x-app-feature-token as optional in deployed mode and read x-app-feature-token or cookie fbsapptoken on the server.


fusebase update

One command to refresh a generated app after a CLI or template upgrade:

  1. CLI binary update — runs first (skips automatically in local linked/source mode). Use --skip-cli-update to disable this stage. On Windows, this launches the installer and exits so fusebase.exe can be replaced; after the installer finishes, run fusebase update again to continue app stages.
  2. Agent assets — refreshes AGENTS.md, .claude/skills/, .claude/agents/, .claude/hooks/, .claude/settings.json.
  3. MCP + IDE — selectively regenerates Dashboards and/or Gate MCP tokens and refreshes IDE configs when the CLI’s permission policy no longer matches .env markers DASHBOARDS_MCP_POLICY_FP and GATE_MCP_POLICY_FP (SHA-256 of the canonical permission sets; Gate includes isolated-stores extras when that global flag is on). Tokens must also be present in .env. Use --force-mcp to refresh both regardless.
  4. Managed SDK versions — bumps only packages listed under fusebaseCli.managedDependencies in project-template/package.json (defaults to @fusebase/dashboard-service-sdk and @fusebase/fusebase-gate-sdk). Root package.json gets missing entries added; app package.json files are updated only if those deps already exist (nothing new is injected into apps).
  5. npm install — runs only in directories where a managed dependency version actually changed.

Pre-update Git checkpoint: In a TTY, you are prompted for an optional commit before changes (empty commit if the tree is clean). If current branch tracks a remote (upstream configured), the pre-update commit is pushed immediately. Without Git, you are warned about rollback risk and can initialize a repo first. Use --skip-commit to skip, or --commit to run the checkpoint in CI/non-interactive mode without prompts.

Prerequisites: fusebase.json with orgId and productId; fusebase auth for stages that touch MCP tokens.

Behavior by directory:

  • In an app directory (fusebase.json exists): runs full flow (CLI + app stages). On Windows, a CLI binary update exits after launching the installer; rerun the command after installation to run app stages.
  • Outside an app directory: runs only CLI binary update.
  • Use --skip-product to force CLI-only mode even inside an app directory.

Examples:

fusebase update
fusebase update --dry-run
fusebase update --skip-product
fusebase update --skip-skills --force-mcp
fusebase update --skip-install
fusebase update --skip-commit

Flags (stages default on; use no-* to disable):

Flag Effect
--skip-product Skip app stages and run only CLI update
--skip-cli-update Skip automatic CLI self-update stage
--skip-skills Skip agent asset refresh
--skip-mcp Skip MCP token + IDE refresh
--force-mcp Always refresh MCP tokens + IDE configs
--skip-deps Skip managed dependency version sync
--skip-install After dep sync, do not run npm install
--skip-commit Skip pre-update Git checkpoint
--commit Run Git checkpoint without prompts (non-interactive)
--dry-run Print planned work only

fusebase update is the single update command.


fusebase sidecar

Manage sidecar containers for an app backend or for a specific cron job. Sidecars are pre-built Docker images that run alongside the main container, sharing its network namespace (reachable on localhost). Stored in fusebase.json under apps[].backend.sidecars[] (backend) or apps[].backend.jobs[].sidecars[] (per cron job).

# Add a sidecar to the backend (default — same as today)
fusebase sidecar add --feature <featureId> --name <name> --image <image> \
  [--port <port>] [--tier small|medium|large] [--env KEY=VALUE ...] \
  [--secret KEY|KEY:ALIAS ...]

# Add a sidecar to a specific cron job (requires the job-sidecars flag)
fusebase sidecar add --feature <featureId> --job <jobName> --name <name> --image <image> \
  [--port <port>] [--tier small|medium|large] [--env KEY=VALUE ...] \
  [--secret KEY|KEY:ALIAS ...]

# Remove a sidecar
fusebase sidecar remove --feature <featureId> --name <name> [--job <jobName>]

# List configured sidecars
fusebase sidecar list --feature <featureId> [--job <jobName>]

Options:

  • --feature <featureId> (required) — app ID
  • --name <name> (required for add/remove) — sidecar name. Lowercase letters, digits, and hyphens; max 63 chars; must start with a lowercase letter.
  • --image <image> (required for add) — Docker image reference (e.g. browserless/chrome:latest)
  • --port <port> — port the sidecar listens on (informational; localhost:<port> from the main container)
  • --tier small|medium|large — resource tier (default: small)
  • --env KEY=VALUE — environment variables, repeatable
  • --secret KEY|KEY:ALIAS — whitelist an app secret key (registered via fusebase secret create) to inject into the sidecar as an env var, repeatable. Use KEY:ALIAS to expose the secret under a different env var name inside the sidecar. On collision between sidecar env and a secret key, the sidecar's static env value wins. Deploy fails with a ValidationError listing every missing key if any referenced secret is not registered for the app.
  • --job <jobName> — attach the sidecar to the named cron job instead of the backend. Requires the job-sidecars flag (fusebase config set-flag job-sidecars). Without --job, all three subcommands target backend sidecars exactly as today.

Limits and rules:

  • Max 3 sidecars per scope. The backend's cap is independent of each job's cap — every job has its own 3-sidecar budget.
  • Sidecar names must be unique within a scope. The same name (e.g. chromium) may exist on the backend and on a cron job; they are separate containers in separate replicas.
  • Backend sidecars share the backend container app's network namespace. Cron-job sidecars share the cron job replica's network namespace only — they are isolated from the backend's sidecars and from sidecars in other jobs.
  • Replicas of a cron job complete when the main job container exits. Non-exiting sidecars (headless browsers, Redis, etc.) are torn down automatically with the replica; replicaTimeout=3600s is the hard ceiling.
  • fusebase dev start does not run cron jobs nor sidecars — they only take effect after fusebase deploy.

fusebase env create

Create or overwrite .env in the current app with MCP token and URL. Use this after fusebase init or when the token has expired.

When .env is created/updated, the command refreshes both Dashboards and Gate MCP tokens. In interactive terminals, it then offers to immediately run fusebase config ide --force for all IDE MCP configs; if declined, it prints that command as the next step.

Options: --no-force — only create .env if missing; do not overwrite existing file.

Prerequisites: App must be initialized (fusebase.json with orgId), API key configured (fusebase auth).

Example:

fusebase env create

Configuration Files

~/.fusebase/config.json

Global configuration stored in your home directory:

{
  "apiKey": "your-api-key",
  "env": "dev",
  "flags": ["mcp-beta"],
  "gitlabHost": "gl.nimbusweb.co",
  "gitlabGroup": "vibecode",
  "gitlabToken": "glpat-xxxxxxxxxxxxxxxx"
}

Experimental Flags

Flags gate experimental features. The update command uses flags to conditionally include/exclude template assets via Eta templates.

Flag Effect
mcp-beta Unlocks optional MCP servers in the integrations catalog that are marked beta (see ide-configs/mcp-servers.ts)
git-init Makes fusebase init automatically offer local Git initialization (same behavior as passing --git; can be disabled per run with --skip-git) and includes Git workflow skill files in generated apps
git-debug-commits Enables strict debug/deploy traceability section inside the git-workflow skill: deploy preflight + dirty-tree guard, commit-per-fix, and SHA/tag traceability in debug/deploy reports
app-business-docs Copies the app-business-docs skill into the app: keeps docs/en/business-logic.md (English) aligned with real behavior — domain rules, main user flows, edge cases; update after business-logic changes or when debugging unclear behavior
mcp-gate-debug Copies the mcp-gate-debug skill: after Fusebase Gate MCP tool runs, summarize smooth vs rough paths and suggest improvements to .claude/skills/fusebase-gate, prompts, or MCP server behavior — prioritize isolated stores (SQL/NoSQL) flows
isolated-stores Enables isolated stores functionality (SQL/NoSQL); also turns on required template references and isolated_store.* permissions in fusebase env create
portal-specific-apps Includes portal-specific app guidance in prompts: fusebase-portal-specific-apps skill, {{CurrentPortal}} dashboard filter reference, and portal auth-context handling notes
job-sidecars Enables per-job sidecar containers for cron jobs. Unlocks --job <jobName> on fusebase sidecar add/remove/list so sidecars can be attached to specific cron jobs (apps[].backend.jobs[].sidecars[]) in addition to the backend. Each job has its own 3-sidecar cap, independent of the backend cap; sidecar names are unique per scope. Also gates the per-job sidecar sections of the app-sidecar and app-backend skill templates.

Enable a flag globally, then refresh the project template:

fusebase config set-flag app-business-docs   # Business-logic documentation skill
fusebase config set-flag mcp-gate-debug      # Gate MCP debug / improvement summary skill
fusebase config set-flag isolated-stores     # Isolated stores functionality (SQL/NoSQL)
fusebase config set-flag portal-specific-apps # Portal-specific apps prompts/guidance
fusebase update --skip-mcp --skip-deps --skip-cli-update --skip-commit  # Refresh agent assets only

Other examples:

fusebase config set-flag mcp-beta    # Enable beta-gated MCP catalog entries
fusebase config remove-flag mcp-beta # Disable
fusebase config flags              # Interactive flag selector (TTY)
fusebase config flags --list       # List active flags (non-interactive)
fusebase update --skip-mcp --skip-deps --skip-cli-update --skip-commit  # Regenerate project files

To permanently graduate a flag (remove gating and enable the feature forever), use the /remove-flag skill in your coding agent:

/remove-flag <flag-name>

Recreate IDE config

Re-run IDE MCP setup in the current project (same logic as during fusebase init): copy config for the chosen IDE and substitute URL/token from .env.

fusebase config ide                # Generate MCP config for all IDEs
fusebase config ide --ide cursor   # Use Cursor preset
fusebase config ide --ide cursor --force   # Overwrite existing files

GitLab sync config

Configure the GitLab settings used by fusebase init --git and fusebase git sync:

fusebase config gitlab                 # Interactive setup/update
fusebase config gitlab --show          # Print current values (token masked)
fusebase config gitlab --host gl.nimbusweb.co --group vibecode --token glpat_xxx
fusebase config gitlab --clear-token   # Remove stored token

MCP Integrations

Interactive catalog (optional servers) plus custom HTTP MCP servers stored in fusebase.json under mcpIntegrations.custom:

fusebase integrations                  # checkbox: catalog optional + custom entries
fusebase integrations --ide cursor     # limit writes to one IDE (optional)
fusebase integrations --no-prompt      # skip UI; optional catalog = inferred from IDE configs
fusebase integrations list-templates   # requires managed-integrations flag
fusebase integrations connect-template --template-name github # requires managed-integrations flag; scopes to current appId

# Custom server (GET reachability check by default; use --skip-check to skip)
fusebase integrations add my-mcp --url https://example.com/mcp --type http [--token TOKEN]
fusebase integrations add my-mcp --url https://example.com/mcp --header 'Authorization: Bearer x'
fusebase integrations disable my-mcp   # keep fusebase.json entry; strip from IDE configs
fusebase integrations enable my-mcp    # turn back on and re-apply IDE configs
fusebase integrations remove my-mcp    # alias: delete — remove from fusebase.json and IDE configs

Custom definitions may include token (sent as Authorization: Bearer … unless you set headers yourself) and enabled: false when disabled.

fusebase.json

Project-specific configuration in your app root:

{
  "orgId": "organization-id",
  "productId": "app-id",
  "apps": [
    {
      "id": "app-uuid",
      "path": "apps/my-app",
      "dev": {
        "command": "npm run dev"
      },
      "build": {
        "command": "npm run build",
        "outputDir": "dist"
      }
    }
  ]
}

Typical Workflow

  1. Authenticate with your API key:

    fusebase auth
  2. Initialize a new app:

    mkdir my-app && cd my-app
    fusebase init
  3. Configure an app for development:

    fusebase app create
  4. Start the development server:

    fusebase dev start
  5. Deploy to Fusebase:

    fusebase deploy

Framework Detection

The CLI automatically detects common frameworks and suggests appropriate dev/build commands:

  • Vite - npm run dev / npm run build (output: dist)
  • Next.js - npm run dev / npm run build (output: .next)
  • Create React App - npm start / npm run build (output: build)
  • Generic npm - Reads from package.json scripts

Environment Variables

Variable Description
ENV Set to dev to use the development environment

License

MIT

About

FuseBase CLI

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors