Skip to main content
Dispatcher command. fjall apps reads its subcommand from the first positional argument. Run it bare and it lists applications.

Overview

fjall apps is the application-level view of your organisation. It carries five subcommands: The accepted surface is exactly those five names plus two aliases. Anything else exits with Unknown subcommand and prints the five canonical names back to you.

Plural and singular are different commands

Three adjacent spellings exist. None of them is a typo of another.
fjall account never lists anything, and fjall accounts never deploys anything. Each command’s own description names the other, because the adjacency is deliberate rather than accidental.

Prerequisites

Usage

The second positional is the subcommand’s argument: an application name for describe and deregister, a path for detect. list and create take no positional.

Subcommands

ls and show are accepted but not advertised, so the unknown-subcommand error lists only the five canonical names:

apps list

Fetches every application in your organisation, then probes each one’s health in parallel. Health comes from two sources: an in-flight deployment record wins outright, and otherwise the state of the application’s network CloudFormation stack decides. Output:
unknown is not folded into not deployed. One is a definite state, the other is an unreadable one. A summary line reading 1 unknown means the health probe could not answer, not that the application is missing.
At a terminal, fjall apps list renders in the interactive UI, prints the same rows and exits. It presents no menu and selects nothing. Pass --non-interactive for plain output.

apps describe

Prints the name, health and ID, then every scalar field on the application record:
Nested objects are skipped, so the output stays one field per line. Omit the name and the command refuses before doing any work:
An application that genuinely does not exist reports Application "api" not found. A credential or network failure reports its own message instead, so a blip is never presented as a missing application.

apps create

Scaffolds an application from flags and registers it with Fjall. --name is required: without it the command fails with Application creation requires a name.
fjall apps create never opens the interactive wizard, even at a terminal. The guided six-tier flow lives on fjall create app. The two commands share the same flag block, so anything you can pass to one you can pass to the other.
Its full option set is in Create options below.

apps detect

Reads a repository and reports what Fjall can build from it. With no path it scans the current directory. A relative path resolves against the current directory, and a path that is not an existing directory is refused. Detection is the first step of the application-creation recipe, and it is mandatory for an existing repository. The values it reports are the values apps create asks for, so running it first removes the guesswork:
1

Detect

One row per workspace, each carrying a framework, a suggested name, a port and a pattern recommendation.
2

Read the recommendation, not the framework

Pass the recommended pattern to --pattern. Framework names and pattern names are different vocabularies, and a framework name passed to --pattern is refused.
3

Create

Seed the flags from the detected row: suggestedAppName for --name, and the create block’s source, buildCommand and outputDir for a static site.
4

Deploy

See fjall deploy.

What detection reads

A workspace is classified from its package.json dependencies. A monorepo is expanded through its workspace globs, so every workspace gets its own row. Monorepo tools recognised: npm-workspaces, pnpm, lerna, turbo, nx. A workspace with no framework and no Dockerfile is classified library, and Fjall will not scaffold infrastructure around it.

Human output

Only the facts go to stdout: the Repo type: and Root package: lines, then for each detected application a blank line, its path, and its framework, package, dockerfile, port, suggested name and suggested config path lines. Everything else goes to stderr. That covers the Fjall framework detection header, the Detected N app(s): line, the No scaffoldable apps detected sentence and every warning, so a piped stdout carries only the detection facts. An empty result is reported honestly. When the scan hit warnings, detection says the scan was degraded and that paths it could not read were never scanned, rather than asserting the repository holds nothing.

JSON output

One line of JSON on stdout:
A failure writes {"ok": false, "error": { … }} and exits 1. In human mode the same failure prints Detection failed: … to stderr.
create.outputDir is a framework convention, not a verified path. Build the site and confirm the directory exists before you deploy, or the deploy succeeds and serves an empty bucket.
create.source is relative to the application’s fjall/<name> config directory, not the repository root. The leading ../.. is part of the value. Pass it to --source verbatim.

apps deregister

Removes an application’s registration from Fjall, and nothing else. This is the only verb that frees a slot against your plan’s application limit.
De-registration is irreversible: nothing restores the record, and afterwards the CLI can no longer address the application by name — fjall destroy included. If you want the AWS infrastructure gone, destroy first, de-register second.

Destroying does not free the slot

fjall destroy tears the CloudFormation stacks down and deliberately leaves the record behind, so the application can be redeployed later and its history survives. That record is what the plan counts, so a destroy alone never gets an organisation under its limit:
The refusal arrives as one line. A link to the Change plan page is appended to it when the server can build one. The sequence that clears both:
1

Destroy the infrastructure

Optional, and it has to come first. Skip it only if you want the AWS resources to keep running, because de-registering leaves them in place with nothing in the CLI able to name them.
2

De-register the record

The slot is free the moment this returns.

--confirm retypes the name

--confirm must match the application name exactly. It is checked before the authentication gate, so a missing or mismatched value costs no round trip and tells you the real mistake:
A value that does not match is refused, and the refusal names the application it expected:
Leaving the application name off is refused on the same side of the gate:
There is no --yes. A retype names its subject, so consent given for one application cannot be replayed against another. On success:

Who can run it

An organisation owner or admin, signed in on a user credential — the fj_ key fjall login writes. A scoped machine token (fjall_ak_, fjall_dk_) is refused, because de-registration is a membership-role decision rather than a token-scope one.

Refusals

Every refusal below leaves the record exactly where it was.

Options

Command options

--mcp-protocol on any other subcommand emits an INVALID_SUBCOMMAND frame and exits 2. It never falls through to a human render, because a failure path that wrote to stdout would corrupt the frame stream.

Shared flags

Create options

Every flag below is registered on fjall apps but read only by apps create. This is the same block fjall create app registers, so the two commands stay in lockstep.
--pattern nextjs parses but is refused at creation: the Next.js pattern has no CDK construct yet, so nothing is scaffolded and nothing is written. Use --pattern payload for a Next.js-based application, or supply a static export with --pattern staticsite.
--tier and --type belong to different application modes and are mutually exclusive. --tier carries the pattern tier for --pattern applications, --type carries the tier for Dockerfile applications. Crossing them is refused with an error naming the correct flag.

Agent mode

All five subcommands have an agent surface. --agent renders TOON instead of tables, and --fields is validated against that subcommand’s schema before the authentication gate, so a typo fails fast rather than after a round trip. On apps deregister the receipt carries deregistered: true beside name. It is a field rather than an implied truth of the success block, because it says the Fjall record is gone and says nothing about the AWS stack. Select id alongside them:
The success help block carries two suggestions, both pointing at what is still standing:
On apps detect, agent mode is checked before --output. Passing --agent --output json renders TOON, not JSON. Omit --agent when a subprocess needs the JSON contract — nothing else turns agent mode on.
Full reference: Agent mode.

Exit codes

Next Steps

fjall create

The guided application wizard, and the same flag block as apps create.

fjall list

List the resources declared inside one application’s infrastructure.ts.

fjall accounts

List provider accounts. The plural sibling that is not this command.

fjall deploy

Ship an application to AWS once it is created.