Skip to main content

Command-line interface

This page is the reference for foundation4ai, the command-line interface (CLI) of Foundation4. The page describes the global options, the configuration and the connections that the CLI uses, and the arguments, output, errors and exit status of every subcommand. Operators use this page to run maintenance commands in an installation and to read the logs of the installation Jobs. Operator command reference lists the subcommands next to the other operator commands.

Synopsis​

foundation4ai [-h | --help] [-V | --version]
foundation4ai <command> [<subcommand>] [<arguments>]
CommandArgumentsPurposeConnection
serverNoneRuns the API serverFull
workerNoneRuns a workerFull
database migrateNoneApplies pending database migrationsDatabase only
database check-connectionNoneTests the database connectionDatabase only
license system-idNonePrints the system IDDatabase only
license checkNoneChecks the configured licenseDatabase only
license details<LICENSE>Prints the contents of a licenseDatabase only
data providersNoneLists the providers of the configured embedding models and text splittersDatabase only
data download-modelsNoneDownloads the files of the configured embedding models and text splittersFull
admin create-admin-api-key<NAME> [DESCRIPTION] [EXPIRATION]Creates the master keyFull
admin update-admin-api-key[NAME] [DESCRIPTION]Changes the name or the description of the master keyFull
admin generate-admin-api-key<NAME> [DESCRIPTION] [EXPIRATION]Creates an additional administration keyFull
help[<command>] [<subcommand>]Prints the help of the binary or of a commandNone

Arguments are positional. Angle brackets mark a required argument, and square brackets mark an optional argument. An argument that contains spaces is quoted, as in "Master Admin Key". Subcommands accept no option other than -h and --help, and no subcommand reads standard input or asks for confirmation. Connections describes the two connection types.

Invocation​

The API server image contains the binary as /app/foundation4ai, and /app is the working directory of the API server, worker and installation Job containers. Operators run subcommands in the server container of a running API server pod:

kubectl exec -n foundation4ai deploy/foundation4ai-api-server -c server -- ./foundation4ai license system-id

Expected result: the output of the subcommand, here one line of 64 hexadecimal characters. kubectl exec returns the exit status of the subcommand and prints command terminated with exit code <status> for any status other than 0.

The binary runs in the following places:

  • Containers. The server container runs ./foundation4ai server, and the worker container runs ./foundation4ai worker. Operators do not start either subcommand through kubectl exec, because the containers already run both processes.
  • Installation Jobs. The application release runs database migrate, license check and admin create-admin-api-key "Master Admin Key" as installation Jobs at every installation and upgrade, in the order described in Install on Kubernetes.
  • Image default. A container started from the API server image without arguments runs the binary without a command. The binary then prints the help and exits with status 2, so the charts always pass a command.

Global options​

OptionEffectExit status
-h, --helpPrints the help of the binary, or of the command or subcommand before the option, on standard output0
-V, --versionPrints foundation4ai 0.1.0, the version of the program package0
help [<command>] [<subcommand>]Prints the same help as --help0

The version of the program package does not follow the Foundation4 release. The tag of the API server image identifies the release, as described in Charts, images and installation bundle.

./foundation4ai --help prints the following text:

Foundation4.ai API Server

Usage: foundation4ai [COMMAND]

Commands:
admin Admin commands
license License commands
database Database operations
data Data operations
server Run the API Server
worker Run the Worker
help Print this message or the help of the given subcommand(s)

Options:
-h, --help Print help
-V, --version Print version

The following rules apply to the command line:

  • Command groups. admin, license, database and data are groups of subcommands. A group without a subcommand prints the help of the group on standard error and exits with status 2.
  • No command. The binary without a command prints the help on standard error and exits with status 2.
  • Unknown names. An unknown command or subcommand prints error: unrecognized subcommand '<name>', followed by similar names when a similar name exists, and exits with status 2.

Configuration​

Every subcommand reads the configuration from the working directory in the order that Configuration reference describes: defaults.yaml, config/settings.yaml, the config/f4ai-*.yaml files in name order, then the FOUNDATION4AI__<SECTION>__<KEY> environment variables. The configuration directory is fixed at ./config, and the CLI has no option that changes the directory or a configuration key.

The following rules apply to the configuration of the CLI:

  • Complete configuration. Every subcommand parses the whole configuration, including the keys that the subcommand does not use. A missing or invalid required key stops the subcommand with a message such as Error: "Failed to parse config: missing field `license` for key \"default.app\"".
  • Start time. A subcommand reads the configuration when the subcommand starts, and the API server and worker processes read the configuration when the processes start. Configuration change describes the restart that applies a change to the running processes.
  • Database settings. The database-only subcommands use database.url and database.ca_cert, and ignore database.schema, database.embeddings_schema and database.pool_size. The license subcommands therefore compute the system ID from the public schema, as described in Licensing.
  • Worker pool. worker uses a database pool of 1 connection, whatever the value of database.pool_size.
  • Log level. app.log_level applies to server and worker. The other subcommands write no log lines, only the output that this page lists. The warning with the system ID that the API server logs after a license failure therefore does not appear in the output of the admin subcommands or of data download-models.

Connections​

Each subcommand uses one of two connection types:

  • Database only. database migrate, database check-connection, the three license subcommands and data providers open one PostgreSQL connection with database.url and database.ca_cert. These subcommands report every connection failure as Error: "Failed connecting to database", without the reason. Database shows how a PostgreSQL client finds the reason.
  • Full connection. server, worker, data download-models and the three admin subcommands build the same connection as the API server. The full connection needs PostgreSQL with pgvector, a valid license, the Redis-compatible cache, NATS JetStream and a valid application secret.

The full connection runs the following steps in order, and the first failure stops the subcommand:

  1. Connects to PostgreSQL with the pool size, the schemas and the certificate authority (CA) certificate of the configuration, creates missing schemas and applies pending migrations.
  2. Computes the system ID from database.schema and checks app.license.
  3. Connects to the Redis-compatible cache.
  4. Connects to NATS JetStream, and creates the object store nats.bucket and the stream nats.stream when missing.
  5. Decodes the application secret app.secret.
  6. Prepares the address of the gRPC service in grpc.url. The connection to the gRPC service opens on first use.

The admin subcommands and data download-models report a failure of any step as Error: "Failed to create database connection: <reason>". The beginning of the reason names the step:

Reason begins withStep
ORM error:PostgreSQL connection or migration
Invalid license, Expired licenseLicense check
Redis error:Redis-compatible cache
Nats error:NATS JetStream
Decryption error: Error decoding secret keyApplication secret
gRPC error:Address of the gRPC service

Before these steps, the full connection reads the four paths keys, and a missing key stops the subcommand with Error: "missing field `<key>`". A cache URL that cannot be parsed stops the process with a panic message instead of an Error: line, as described in Troubleshooting. The messages of server and worker differ and are listed in Troubleshooting.

Output and exit status​

Subcommands print results on standard output and errors on standard error:

Exit statusMeaningStandard error
0The subcommand completed, or the help or version was printed on requestEmpty
1The subcommand failedError: "<message>"
2The command line is invalid, or names a group without a subcommand, or no commanderror: <reason> followed by the usage, or the help
134The process stopped on an internal error with the abort signalA message that contains panicked at

The following rules apply to the output:

  • Quoted messages. The message after Error: is printed as a quoted string, so a quotation mark inside the message appears as \".

  • License results. license details exits with status 0 when the license is invalid or expired, and license check exits with status 0 after the wait that follows a failed check. Scripts read the printed result, not the exit status.

  • Argument errors. An invalid argument prints the reason and a pointer to the help, as in the following output for an expiry without a time:

    error: invalid value '2027-01-31' for '[EXPIRATION]': premature end of input

    For more information, try '--help'.

Process subcommands​

Server​

server runs the API server. The subcommand builds the full connection, authenticates with the master key and listens on app.host and app.port. The process logs at app.log_level, and at the level info the log shows Starting <branding.name> API on <host>:<port>. On the interrupt signal or the termination signal, the API server stops accepting connections, completes open requests and exits with status 0.

The API server reports connection and master key failures after Error: "Failed to initialize server: , and a listen address that cannot be used as Failed to bind to address: <reason>. Troubleshooting lists the messages with the causes.

Worker​

worker runs a worker. The subcommand opens the metrics listener on port 9090, builds the full connection with a database pool of 1 connection, and authenticates with the master key. After a wait of 2 seconds, the worker logs Starting Foundation4.ai worker at the level info and fetches processing jobs from NATS JetStream in batches of up to 100 jobs.

The following rules apply to the worker:

  • Stop signal. The worker stops on the interrupt signal. The termination signal that Kubernetes sends does not stop the worker, so a stopping worker pod runs until the termination grace period ends, as described in Scaling and performance.
  • Startup errors. The worker reports connection failures as Failed to connect to Foundation4.ai: <reason>, master key failures as Failed to initialize Foundation4.ai: <reason>, and queue consumer failures as Error creating message queue consumer: <reason>. When port 9090 is already in use, the worker stops with a panic message that contains Failed to install recorder.
  • Queue errors. The worker ends the process when a read from the queue fails, as described in Troubleshooting.

Database subcommands​

Database migration​

database migrate applies the pending migrations of the database schema, records each migration in the table schema_migrations, and prints Migrated to latest schema. The migration Job runs the command before the license check at every installation and upgrade, and the API server, the workers and the master key Job also apply pending migrations at startup.

The following rules apply to the migration:

  • Earlier table format. When a table named schema_migrations with exactly one column exists, the command drops that table before applying the migrations, because the table then has the format of an earlier Foundation4 version. The database is therefore dedicated to Foundation4, as Database requires.
  • Direction. Each migration runs in one transaction, and migrations only move forward. The CLI has no command that reverts a migration, as described in Database.
  • Errors. Error: "Failed connecting to database" means that the connection failed. Error: "Failed applying migrations: <reason>" means that the connection succeeded and a migration failed, as described in Troubleshooting.

Database connection check​

database check-connection opens a connection with database.url and database.ca_cert and prints Ok. The check covers the address, the credentials and the Transport Layer Security (TLS) settings. The check does not cover the schemas, the migrations or the pgvector extension. A failure prints Error: "Failed connecting to database" without the reason; Operator command reference tests the same connection with a PostgreSQL client that shows the reason.

License subcommands​

The license subcommands compute the system ID from the public schema of the database in database.url. Before the first migration, the database has no api_keys table, and the license subcommands fail with Error: "Failed generating system id". Licensing describes licenses and the system ID.

System ID​

license system-id prints the system ID as one line of 64 hexadecimal characters. The Foundation4 provider issues a license for this value, as described in Licensing.

License check​

license check checks the license in app.license against the system ID and prints two lines:

SystemID: <system ID>
Checking for a valid license... OK
ResultMeaningProcess after the result
OKThe license is valid for the system ID and has not expiredExits with status 0
Missingapp.license is an empty stringWaits 365 days, then exits with status 0
InvalidThe license is malformed, of an unsupported version, or issued for another system IDWaits 365 days, then exits with status 0
ExpiredThe expiry date of the license has passedWaits 365 days, then exits with status 0

The wait keeps the license check Job running, so the system ID stays in the Job log and the application installation stops at the Helm timeout, as described in Troubleshooting. In a running pod, operators use license details instead of license check. Under the charts, an empty license value in the secrets file stops every installation Job with a configuration error before the check, as described in Secrets and keys.

License details​

license details <LICENSE> checks the license given as the argument against the system ID and prints the contents of the license. The license is one argument in quotes:

kubectl exec -n foundation4ai deploy/foundation4ai-api-server -c server -- ./foundation4ai license details '<license>'

Expected result for a license that matches the database:

License: <license holder> (expires on <date> <time> UTC)
System ID: <system ID>
Version: 2
Limits:
Pipelines: <limit>
Documents: <limit>

A license without an expiry date shows (perpetual), and optional Description: and Environment: lines appear when the license carries these fields. Licensing describes every line. For a license that cannot be used, the single line Invalid or Expired replaces the contents, and the command exits with status 0. Operator command reference reads the license value from the secrets file.

Data subcommands​

Provider list​

data providers lists the distinct providers of the embedding models and of the text splitters in the database, in no fixed order. A database with only the seeded objects of Providers and models produces the following output:

Found embedding providers:
- FastEmbedEmbeddings

Found text splitters providers:
- RecursiveCharacterTextSplitter
- CharacterTextSplitter
- NLTKTextSplitter

The list names the providers that configured objects use, not every provider that Foundation4 supports. Providers and models lists the supported providers.

Model download​

data download-models builds the full connection and downloads the files of the configured embedding models and text splitters. For each distinct combination of provider, model and parameters, the command prints Downloading data for embedding provider <provider>, model <model>. The command then prints Found text splitters providers: and one Downloading data for text splitter provider: <provider> line for each distinct text splitter provider and parameters.

ProviderDownloadDestination
FastEmbedEmbeddingsThe file named in the onnx parameter, the files in data_files and the tokenizer files, from the Hugging Face Hub; the model name has the form <owner>/<repository>paths.fastembed in the container that runs the command
OpenAIEmbeddingsNoneNone
GPT4AllEmbeddingsThe gRPC service loads the model and downloads the model filepaths.gpt4all in the gRPC service container of the pod
HuggingFaceEmbeddingsThe gRPC service loads the model through the Hugging Face librarypaths.huggingface in the gRPC service container of the pod
HuggingFaceEndpointEmbeddingsThe gRPC service creates the endpoint clientNone
Text splitter providersThe gRPC service creates each text splitter; NLTKTextSplitter downloads the NLTK punkt_tab datapaths.nltk in the gRPC service container of the pod, for NLTKTextSplitter

The following limits apply to the model download:

  • Seeded model. The seeded embedding model has no onnx parameter, so the command stops at that model with Error: "Invalid parameter: missing field `onnx`". The models listed after the seeded model and all text splitters are then not processed.
  • One pod. The files land in the containers of the pod where the command runs. Other pods do not receive the files, and the files are lost when the containers restart. Models, packages and air-gapped installs describes model and package images, which deliver files to every pod.
  • Network access. The command needs access to the Hugging Face Hub and to the download sources of the gRPC service providers, so the command applies to connected deployments only.
  • Errors. Download failures print Error: "Invalid parameter: Error downloading model from Hugging Face: <reason>" for FastEmbed files and a message that begins with gRPC error: for providers in the gRPC service. Query failures print Failed to retrieve embedding providers: <reason> or Failed to retrieve text splitters providers: <reason>.

Admin subcommands​

The admin subcommands create and change keys that hold every permission. Access control describes the master key, and Secrets and keys describes the master key values of an installation.

Master key creation​

admin create-admin-api-key <NAME> [DESCRIPTION] [EXPIRATION] creates the master key from app.master.key and app.master.secret and prints Admin API key created successfully. The master key Job runs the command at every installation and upgrade with the name Master Admin Key and no other argument.

ArgumentTypeRequiredEffect
NAMEStringYesName of the key. Every key has a unique name.
DESCRIPTIONStringNoDescription of the key
EXPIRATIONDate and time in RFC 3339 form, such as 2027-01-31T00:00:00ZNoExpiry of the key. A value without a time or without a UTC offset fails with exit status 2.

The following rules apply to the master key creation:

  • Existing key. When a key with the identifier app.master.key exists, the command leaves the name, the description, the expiry and the stored secret of that key unchanged, and prints the success message.
  • Permissions. The command sets the permissions of the key to read, write and execute on every object type, with the allow-list *, and removes the cached copy of the key from the Redis-compatible cache.
  • Expiry. The API server and the workers authenticate with the master key at startup, so the master key stays active and unexpired. The master key Job therefore passes no expiry.
  • Errors. A failure of the full connection prints Error: "Failed to create database connection: <reason>". A key that cannot be stored prints Error: "Failed creating admin API key: <reason>", and a name that another key uses produces a reason that begins with Conflict error (unique):.

Master key update​

admin update-admin-api-key [NAME] [DESCRIPTION] changes the name, the description or both of the key with the identifier app.master.key, and prints Admin API key updated successfully.

The following rules apply to the master key update:

  • Arguments. The first argument sets the name, and the second argument sets the description. The help of the command lists four arguments, [NAME] [DESCRIPTION] [ACTIVE] [EXPIRATION], but the command accepts at most two. A third argument fails with error: unexpected value '<value>' for '[DESCRIPTION]' found; no more were expected and exit status 2.
  • Omitted arguments. An omitted argument leaves the value unchanged, and the command without arguments changes neither value. The description cannot be removed; an empty string "" sets an empty description.
  • Other effects. The command sets the permissions of the master key as admin create-admin-api-key does, and removes the cached copy of the key. The command changes no other property of the master key.
  • Errors. Error: "Failed updating admin API key: Api Key not found: <master key identifier>" means that no key has the identifier app.master.key. Error: "Failed updating admin API key: SQL error: <reason>" means that the change cannot be stored, for example because another key uses the name.

Administration key generation​

admin generate-admin-api-key <NAME> [DESCRIPTION] [EXPIRATION] creates a new key with a random identifier, a random secret of 32 letters and digits, and the permissions of the master key. The arguments are those of admin create-admin-api-key:

kubectl exec -n foundation4ai deploy/foundation4ai-api-server -c server -- ./foundation4ai admin generate-admin-api-key "Operations key" "Administration key for the operations team"

Expected result:

Admin API key created successfully.
Key : <key identifier>
Secret: <32-character secret>

The following rules apply to the generated key:

  • Single output. The output is the only copy of the secret. The command runs in a session whose output is not recorded, and the secret goes directly to the organization's secret store.
  • Use. The new key is an administration key for API requests, as described in Manage API keys and permissions. The new key does not replace the master key, because the API server and the workers authenticate with app.master.key at startup.
  • Errors. The command prints the same errors as admin create-admin-api-key.