CLI & Build Tools
GoatDB provides CLI tools for scaffolding and local development, plus programmatic build/dev APIs used from your project scripts.
CLI Commands
init — Scaffold a Project
Creates a complete project structure with a React client, GoatDB server, shared schema, and build tooling.
Deno:
deno run -A jsr:@goatdb/goatdb init
deno run -A jsr:@goatdb/goatdb init ./my-app # optional target directory
Node.js (requires Node.js 24+):
npx -y @goatdb/goatdb init
npx -y @goatdb/goatdb init ./my-app # optional target directory
If you install globally (npm install -g @goatdb/goatdb), you can run goatdb init directly.
Generated structure
After running init, your project looks like this:
my-app/
├── client/
│ ├── index.html # HTML shell served to the browser
│ ├── index.css # Base stylesheet
│ ├── index.tsx # React entry point — registers schemas and mounts <App />
│ └── app.tsx # Root component — start editing here
├── common/
│ └── schema.ts # GoatDB schema definitions — add your schemas here
├── server/
│ ├── debug-server.ts # Development server (port 8080, live reload)
│ ├── server.ts # Production server entry with CLI args
│ └── build.ts # Script to compile to a standalone executable
├── .gitignore # Ignores node_modules, build, server-data, etc.
└── deno.json / package.json # Project config (runtime-dependent)
Node.js only adds package.json, tsconfig.json, .npmrc, and server/server-sea.ts (for embedded binary mode).
Key behaviors
- Idempotent — existing files are never overwritten, safe to re-run.
- Auto-installs dependencies — runs
deno addornpm installafter scaffolding. - Runtime auto-detected — produces the correct config files and import paths for whichever runtime invokes it.
Run the dev server
# Deno
deno task dev
# Node.js
npm run dev
Both commands start a server at http://localhost:8080 with live reload on file changes.
link / unlink — Local Development
Swap your project's GoatDB dependency to point at a local clone. Useful when working on GoatDB itself alongside your app.
link/unlink requires Deno to be installed, even for Node.js projects. On Node.js projects it edits package.json to use a file: path, but Deno is still the runtime that executes the command. Contributing to GoatDB's source (not just using it) requires Deno.
# Point project at local GoatDB
deno run -A jsr:@goatdb/goatdb/link link ../path/to/goatdb
# Restore original dependencies
deno run -A jsr:@goatdb/goatdb/link unlink
The
/linkin the import path is the module entry point;linkorunlinkis the subcommand passed as the first argument.
What link does
- Deno projects: Creates
vendor/goatdbsymlink → local path, rewritesdeno.jsonimports to use the symlink. - Node.js projects: Updates
package.json@goatdb/goatdbentry to"file:/absolute/path". - Saves original state to
goat.link.jsonand adds it plus modified config files to.gitignore.
unlink reverses all of this — restores goat.link.json values, removes the symlink, and cleans .gitignore.
Build & Development APIs
These are TypeScript APIs imported from @goatdb/goatdb/server/build and invoked from project scripts, not directly from the command line.
Building Standalone Executables
Packages your app into a single binary with all assets embedded. Invoked programmatically from server/build.ts (generated by init).
import { compile, type CompileOptions } from '@goatdb/goatdb/server/build';
await compile({
serverEntry: './server/server.ts', // Server entry point (required)
jsPath: './client/index.tsx', // React client entry (required)
buildDir: './build', // Intermediate build output (required)
htmlPath: './client/index.html', // HTML template (optional)
cssPath: './client/index.css', // Stylesheet (optional)
outputName: 'my-app', // Binary name, default: "app" (optional)
});
Platform and architecture
await compile({
// ...
os: 'linux', // 'mac' | 'linux' | 'windows'
arch: 'x64', // 'x64' | 'arm64'
});
Deno only supports cross-compilation. Running compile on a Mac with os: 'linux' produces a Linux binary.
Node.js builds are always native — run compile on the target OS.
Code signing
await compile({
// ...
signing: {
// macOS
identity: 'Developer ID Application: Your Name (TEAMID)',
hardenedRuntime: true,
entitlements: './entitlements.plist',
notarize: {
keychainProfile: 'my-notarization-profile',
staple: true,
},
// Windows
windows: {
thumbprint: 'ABC123...', // certificate store (preferred)
timestampUrl: 'http://timestamp.digicert.com',
},
},
});
Run compilation
# Deno
deno task compile
# Node.js
npm run compile
Both tasks invoke server/build.ts, which is pre-wired with your project's paths.
Development Server
The development server is scaffolded by init into server/debug-server.ts — you don't need to configure anything. It starts on port 8080 and rebuilds client assets on file changes.
deno task dev # or: npm run dev
Programmatic use
If you need to embed a debug server in a custom script:
import { startDebugServer } from '@goatdb/goatdb/server/build';
import { registerSchemas } from './common/schema.ts';
registerSchemas();
await startDebugServer({
jsPath: './client/index.tsx',
htmlPath: './client/index.html',
cssPath: './client/index.css',
buildDir: './build',
watchDir: '.', // directory to watch for changes
port: 8080,
orgId: 'dev-org', // simulate a specific org's environment (optional)
setup: async (server) => { // called after init, before HTTP listening (optional)
// access server.db here for event handlers, background tasks, etc.
},
});
Watch options:
| Option | Default | Description |
|---|---|---|
watchDir | '.' | Root directory to watch for changes |
watchFilter | Ignores dotfiles, .tmp files, .git/, node_modules/, build/, server-data/ | (path: string) => boolean — return true to trigger a rebuild |
beforeBuild / afterBuild | — | Async hooks that run before/after each rebuild |
orgId simulates a specific organization's environment locally. setup is called after the server and database are initialized but before HTTP listening begins — use it to access the GoatDB instance for server-side logic (event handlers, background processes, custom endpoints).