Command Line Interface
The fullfinity-server CLI is the primary tool for managing your Fullfinity installation. It handles server startup, module management, and code generation.
Basic Usage
Section titled “Basic Usage”fullfinity-server -c config.yaml [options] [command]The -c/--config flag is required for all operations.
Starting the Server
Section titled “Starting the Server”Basic Server Start
Section titled “Basic Server Start”fullfinity-server -c config.yamlThis starts the server using settings from config.yaml. The API will be available at http://localhost:8000 by default.
Start with Specific Database
Section titled “Start with Specific Database”fullfinity-server -c config.yaml -db mycompanyIn multi-tenant setups, use -db to specify which database to connect to.
Custom Host and Port
Section titled “Custom Host and Port”fullfinity-server -c config.yaml --host 127.0.0.1 --port 9000Override the default binding address and port.
Custom Worker Count
Section titled “Custom Worker Count”fullfinity-server -c config.yaml --workers 8Override the number of worker processes (default from config file).
Rebuild Frontend Before Starting
Section titled “Rebuild Frontend Before Starting”fullfinity-server -c config.yaml --rebuildRebuilds the React frontend from source (app/) and copies the built files to static/ before starting the server.
Module Management
Section titled “Module Management”All module operations require the -db flag to specify the target database.
Discover New Modules
Section titled “Discover New Modules”fullfinity-server -c config.yaml -db mycompany --update-module-listScans the module paths for new or updated modules and registers them in the database. Run this after adding new module folders.
Install Modules
Section titled “Install Modules”# Install single modulefullfinity-server -c config.yaml -db mycompany -i sales
# Install multiple modulesfullfinity-server -c config.yaml -db mycompany -i sales,invoicing,crm
# Long formfullfinity-server -c config.yaml -db mycompany --install sales,invoicingInstalls the specified modules and their dependencies. The installation process:
- Resolves module dependencies
- Runs database migrations
- Loads security groups and access rules
- Loads views, actions, and menus
- Loads seed data
Update Modules
Section titled “Update Modules”# Update specific modulesfullfinity-server -c config.yaml -db mycompany -u sales,invoicing
# Update all installed modulesfullfinity-server -c config.yaml -db mycompany -u all
# Long formfullfinity-server -c config.yaml -db mycompany --update allUpdates modules to apply changes:
- New or modified fields (runs schema migration)
- Updated views and actions
- New security rules
- Updated seed data
Uninstall Modules
Section titled “Uninstall Modules”fullfinity-server -c config.yaml -db mycompany --uninstall salesRemoves a module and cleans up:
- Deletes records owned by the module
- Updates dependent modules to restore their original state
- Reverts any extensions made by the uninstalled module
Warning: Uninstalling a module may delete user data associated with that module.
Initialize Modules (New Database)
Section titled “Initialize Modules (New Database)”fullfinity-server -c config.yaml -db newcompany --init core,sales,invoicingCombines --update-module-list and --install for new database setup. Use this when setting up a fresh tenant database.
Module Operations Without Starting Server
Section titled “Module Operations Without Starting Server”fullfinity-server -c config.yaml -db mycompany -u all --init-onlyThe --init-only flag performs the module operations and exits without starting the server. Useful for:
- CI/CD pipelines
- Database updates in deployment scripts
- Batch operations
Upgrades
Section titled “Upgrades”upgrade is an alias for -u all — there is no separate version-based upgrade path. After pulling new code, run either:
git pull origin mainfullfinity-server -c config.yaml -db mycompany -u all # or: ... upgradeThis runs the additive schema sync and replays the schema-change ledger (renames, deletes, complex/data migrations) in one atomic transaction — per installed module, in change-id order. It’s safe to re-run (idempotent) and rolls back wholesale on failure. There are no pre_upgrade/post_upgrade hooks and no framework-version gating.
See Migrations & Upgrades for how schema changes are recorded (check --only schema / resolve) and replayed.
Consistency & Schema Commands
Section titled “Consistency & Schema Commands”Four verbs manage the schema contract and the build-time consistency gates. All are no-database (they compose the model surface from code) except preview --db.
check — run the consistency gates
Section titled “check — run the consistency gates”Runs every build-time gate and exits 1 on any failure, so it can gate CI and pre-commit:
fullfinity-server -c config.yaml check # all gates (report every failure)fullfinity-server -c config.yaml check --only schema # one gate: schema|views|templates|refs|valkey|manifestsfullfinity-server -c config.yaml check --module sales # scope to a single modulefullfinity-server -c config.yaml check --strict # views/templates gates: enforce the full anchor ruleset--only | Gate |
|---|---|
schema | the append-only field-surface contract (no renamed/removed/retyped field or Selection choice) |
views | view inheritance stability (hooks target stable anchors, never titles/positions) |
templates | report/portal/email template inheritance: extensions target a stable #id/[data-anchor]/field:<chain> in their base (never CSS/content/position), and every base body’s structural nodes are anchor-covered so third parties can extend it |
refs | every stored reference — Q-domains, filter-groups, visible_setting, field-paths, model-names, report/email Jinja — resolves against the schema |
valkey | no module reaches past env.valstore into an engine-internal Valkey DB |
manifests | every module manifest has the required keys and a valid category |
With no --only, all gates run and every failure is reported together.
resolve — record a sanctioned schema change
Section titled “resolve — record a sanctioned schema change”When check --only schema fails on an intentional rename/removal/retype, record it (details in Migrations & Upgrades):
fullfinity-server -c config.yaml resolve # interactive promptsfullfinity-server -c config.yaml resolve --assume-renames # auto-record obvious renamesfullfinity-server -c config.yaml resolve --rename Task.due=deadline --delete Task.legacy_notefullfinity-server -c config.yaml resolve --snapshot --module acme # just (re)write the baselinepreview — upgrade transparency
Section titled “preview — upgrade transparency”Before upgrading a customer install, preview what a release breaks in their custom modules, or render the release changelog (details in Upgrade Transparency):
fullfinity-server -c config.yaml preview --db mycompany # audit an install's custom modules (read-only)fullfinity-server -c config.yaml preview # release reference changelog (no database)fullfinity-server -c config.yaml preview --out FILE # write the Markdown to a fileFilestore
Section titled “Filestore”filestore — move a filestore into object storage, and check it landed
Section titled “filestore — move a filestore into object storage, and check it landed”Attachments live outside the database, so switching FILESTORE_BACKEND from local to s3
means the files have to be copied. The database does not change: an attachment row stores a
storage key, and the same string addresses the file on disk and in a bucket.
fullfinity-server -c config.yaml filestore copy --db mycompany --dry-runfullfinity-server -c config.yaml filestore copy --db mycompanyfullfinity-server -c config.yaml filestore verify --db mycompanycopy uploads every local file the configured backend does not already hold. It is idempotent
and safe to run while the instance is serving: anything already there is skipped, so it can be
interrupted, re-run, and run a second time after the cutover to carry whatever was uploaded in
between. Node-local scratch (import_tmp/) and part-written files are deliberately left behind.
verify answers a different question — whether every attachment row has bytes the backend can
actually produce. A copy can be complete and the answer still be no, because a row can outlive its
file. It refuses to report success while FILESTORE_LOCAL_FALLBACK is on, since those reads may
have been answered from the local disk you are trying to stop depending on.
The full cutover procedure, including where the fallback fits, is in Configuration.
filestore status / adopt / fork — after copying a database with Postgres
Section titled “filestore status / adopt / fork — after copying a database with Postgres”A database’s files live under an id stored inside it, not under its name (see
Multi-tenancy). That is what
lets a pg_restore onto new hardware keep its attachments — and it means a copy made outside
this application carries the original’s id:
pg_dump prod | psql staging # staging now points at prod's filesTwo live databases, one prefix. Deleting files is blocked while that is true, because the database it was copied from is probably still serving them. Nothing can tell that apart from a disaster restore by looking inside the database, so you resolve it:
fullfinity-server -c config.yaml filestore status --db staging # which prefix, and who owns itfullfinity-server -c config.yaml filestore adopt --db restored # this REPLACES the originalfullfinity-server -c config.yaml filestore fork --db staging # this stands BESIDE itadopt keeps the files and takes ownership — the disaster-restore case, where the original is
gone. fork gives this database a prefix of its own and copies the files into it — the staging
case, where both are running. status exits non-zero when a decision is outstanding, so it can
gate a deploy.
Databases created, cloned or restored through Fullfinity mint their own id and never need this.
Migrating from the old flags
Section titled “Migrating from the old flags”These verbs replaced the earlier artifact-named flags — there are no aliases, so update any scripts or pipelines:
| Old flag | New |
|---|---|
--check-schema | check --only schema |
--check-views (--strict-views) | check --only views (--strict) |
--check-references | check --only refs |
--check-valkey-access | check --only valkey |
--check-manifests | check --only manifests |
| (all gates at once) | check |
--resolve-schema (--rename/--delete/--complex/…) | resolve (same options) |
--snapshot-schema | resolve --snapshot |
--report / --report-out | preview --db / preview --out |
--changelog / --changelog-out | preview / preview --out |
Custom Module Paths
Section titled “Custom Module Paths”fullfinity-server -c config.yaml --module-path ./fullfinity/modules,./modules,/opt/modulesOverride the module search paths (the MODULE_PATHS config key). Fullfinity will scan all specified directories for modules.
Scaffolding a New Module
Section titled “Scaffolding a New Module”The new command scaffolds a module with the standard directory structure and sample files.
fullfinity-server -c config.yaml new my_module
# Create it in a specific directory (default: current directory)fullfinity-server -c config.yaml new my_module --path ./modulesThe module identifier must be a snake_case identifier (letters, digits, underscores; not starting with a digit). The scaffolder writes a ready-to-install module:
my_module/├── __init__.py├── manifest.yaml # Module metadata├── models/ # Model definitions (.py) — includes models/__init__.py├── views/ # UI views, actions, menus (.yaml)├── security/ # Groups, permissions (.yaml)├── data/ # Seed data├── demo/ # Demo data├── i18n/ # Translations├── tests/ # Tests (.py)├── templates/ # Templates├── routes/ # Custom routes└── static/src/{css,js}/ # Frontend assetsThe generated models/, views/, security/, and tests/ folders contain working sample files (a model, list/form views, an action, a menu, a security group, and a test). After scaffolding, install it:
fullfinity-server -c config.yaml -db mycompany -i my_moduleNote: new does not require the -db flag since no database access is needed.
Command Reference
Section titled “Command Reference”Global Options
Section titled “Global Options”| Option | Short | Description |
|---|---|---|
--config | -c | Path to configuration file (required) |
--database | -db | Target database name |
--help | -h | Show help message |
Server Options
Section titled “Server Options”| Option | Description |
|---|---|
--host | Host to bind to (default: 0.0.0.0) |
--port | Port to run on (default: 8000) |
--workers | Number of worker processes |
--rebuild | Rebuild frontend before starting |
--module-path | Comma-separated module directories |
Module Options
Section titled “Module Options”| Option | Short | Description |
|---|---|---|
--install | -i | Install modules (comma-separated) |
--update | -u | Update modules (comma-separated or “all”) |
--uninstall | Uninstall modules (comma-separated) | |
--init | Initialize modules (update list + install) | |
--update-module-list | Scan for new modules | |
--init-only | Exit after module operations |
Upgrade Subcommand
Section titled “Upgrade Subcommand”fullfinity-server -c config.yaml -db mycompany upgradeAlias for -u all: additive schema sync + atomic ledger replay. Requires -db.
New Subcommand
Section titled “New Subcommand”# Scaffold a new module (no -db required)fullfinity-server -c config.yaml new my_module [--path DIR]new options:
| Option | Description |
|---|---|
name | Module identifier (snake_case), e.g. my_module (positional) |
--path | Directory to create the module in (default: current directory) |
Test Subcommand
Section titled “Test Subcommand”# Run the whole suite — creates a self-cleaning ephemeral database automaticallyfullfinity-server -c config.yaml test [options]No -db is needed: the test command creates a fresh, self-cleaning database for the run and
drops it afterwards. Omit --module to run every module’s tests against one install (fastest
for the full suite); pass --module to filter to one.
test options:
| Option | Short | Description |
|---|---|---|
--module | -m | Only run tests for this module (omit to run all) |
--verbose | -v | Verbose output |
-k | Only run tests whose method name matches this pattern (not class names) | |
--json-summary | Write JSON test results to a file | |
--install-only | Install --module and its declared dependencies, then stop — no tests are collected or run. Succeeds if the install and view/security composition did. |
Check Subcommand
Section titled “Check Subcommand”# Run the consistency gates (no -db required)fullfinity-server -c config.yaml check [--only AREA] [--module ID] [--strict]| Option | Description |
|---|---|
--only | Run one gate: schema, views, templates, view-refs, refs, valkey, manifests, i18n, or keys (default: all) |
--module | Scope the check to a single module |
--strict | Views gate: enforce the full anchor ruleset |
Resolve Subcommand
Section titled “Resolve Subcommand”# Record a sanctioned schema change / re-snapshot baselines (no -db required)fullfinity-server -c config.yaml resolve [--snapshot] [--module ID] [decisions…]| Option | Description |
|---|---|
--snapshot | Just (re)generate the committed baselines from code (record no change) |
--module | Scope to a single module |
--assume-renames | Auto-record obvious single-candidate field renames |
--rename, --delete, --complex, --rename-choice, --complex-choice, --rename-model, --delete-model | Declarative, repeatable decisions (non-interactive) |
Preview Subcommand
Section titled “Preview Subcommand”# Upgrade transparency: install audit (--db) or release changelog (no -db)fullfinity-server -c config.yaml preview [--db DB] [--out FILE]| Option | Description |
|---|---|
--db | Audit an installed database’s custom modules against the current base (read-only) |
--out | Write the Markdown to a file instead of stdout |
Common Workflows
Section titled “Common Workflows”Setting Up a New Tenant
Section titled “Setting Up a New Tenant”# Create database (via psql or your preferred method)createdb newclient
# Initialize with core modulesfullfinity-server -c config.yaml -db newclient --init core,sales,crm --init-only
# Start server for the tenantfullfinity-server -c config.yaml -db newclientDeploying a Version Update
Section titled “Deploying a Version Update”# Pull new versiongit pull origin main
# Upgrade after pulling new code (alias for -u all)fullfinity-server -c config.yaml -db production upgrade
# Start serverfullfinity-server -c config.yaml -db productionupgrade is the whole upgrade: additive schema sync plus ledger replay (renames, deletes, complex/data migrations) in one atomic transaction. There is no separate step, and no version-keyed pre_upgrade/post_upgrade hooks — that mechanism has been retired.
Running Fullfinity under Docker? The image swap comes first and the migration is the same command run inside the container — see Installation → Upgrading.
Deploying Module Updates (Same Version)
Section titled “Deploying Module Updates (Same Version)”# Pull latest code (same framework version, module changes only)git pull origin main
# Update all modules on production databasefullfinity-server -c config.yaml -db production -u all --init-only
# Restart server (handled by process manager)Adding a Custom Module
Section titled “Adding a Custom Module”# Scaffold module structurefullfinity-server -c config.yaml new custom_module
# Or create manually:# mkdir -p modules/custom_module/{models,views,data,security,templates}# Create manifest.yaml, models, views...
# Register the modulefullfinity-server -c config.yaml -db mycompany --update-module-list
# Install itfullfinity-server -c config.yaml -db mycompany -i custom_moduleDevelopment Workflow
Section titled “Development Workflow”# Make changes to module code
# Update the module to apply changesfullfinity-server -c config.yaml -db dev -u mymodule --init-only
# Or update and start server in one commandfullfinity-server -c config.yaml -db dev -u mymoduleExit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Configuration error |
Environment Variables
Section titled “Environment Variables”The CLI reads one environment variable, FULLFINITY_CONFIG_PATH, which records the path to the config file so worker processes (Gunicorn/Uvicorn workers, the job runner) can load it. It is set automatically from the -c/--config flag — you normally don’t set it by hand:
export FULLFINITY_CONFIG_PATH=./config.yamlIndividual configuration keys (DB_HOST, SECRET_KEY, etc.) are not overridable via environment variables — they are read from config.yaml (and a sibling config.local.yaml overlay). See Configuration.
Filestore Subcommand
Section titled “Filestore Subcommand”| Option | Description |
|---|---|
copy | verify | Copy local files into the configured backend, or check every attachment row resolves |
status | Which filestore prefix this database uses, and whether it owns it |
adopt | fork | Resolve a database copied in by Postgres: take over the prefix, or take a new one |
--db DB | Database to act on (required) |
--dry-run | Report what would be copied, upload nothing |
Next Steps
Section titled “Next Steps”- Configuration - Configure your installation
- Quick Start - Create your first module
- Creating Modules - Module development guide