Two surfaces
The SKILL + CLI path is what every onboarding flow ships against. The agent reads recipes from
SKILL.md and shells out to fjall … subcommands, getting back TOON-formatted, exit-coded output with credentials masked by default. --agent is how the agent asks for that output, on every command that has an agent surface.
The MCP server is a thin transport wrapper that exposes a subset of CLI commands as MCP tools. It exists because some hosts cannot load skill files. It is pre-1.0: end-to-end coverage is partial and the protocol-frame contract can change between betas.
Output mode
From fjall 38,--agent on the command line is the only way to get agent output, and the only input to the decision.
Through 37.x the CLI inspected the machine it ran on: seventeen environment markers (CLAUDECODE, CURSOR_TRACE_ID, CODEX_SANDBOX, GEMINI_CLI, AI_AGENT and the rest) behind a TTY check. The same script emitted TOON on one host and prose on another. That inference is deleted.
Without the flag no command emits agent output, on any host, whatever editor or harness you run it under. A human running Fjall inside an agent session now gets exactly the output they get in a terminal.
There is no --no-agent. It went with the inference, and fjall … --no-agent now fails with an unknown-option error rather than silently doing something else. Delete it from any 37.x script.
An agent or wrapper that relied on being auto-detected must pass --agent. Anything that already passed it is unaffected.
Commands that refuse the flag
Thirteen command paths have no agent surface. They refuse--agent, --budget, --fields and --full before the command runs, rather than answering with prose under a success exit code. Each refusal names what to do instead.
Masked by default, with declared carve-outs
The value a command exists to hand back travels verbatim. Every other field on the same result masks as usual.
A verbatim field is neither masked nor thinned by
--budget. Masking one would redact nothing the caller does not already hold, and would return *** to the question the command was asked, which reads as an answer and is not one.
When to pick which
- Claude Code uses SKILL. Run
fjall agent install-skillto install the recipe. - Anything else uses MCP. Build the server from a checkout and register it in your client’s MCP server list. If your host later grows SKILL support, switch. The SKILL path is faster, more thoroughly tested, and gets new flows first.
SKILL + CLI quick start
Options
The skill bundle ships with the CLI and is stamped with its version. Re-run
fjall agent install-skill after every CLI upgrade: it rewrites the recipe in place and reports the version it replaced.
A skill installed before fjall 38 tells the agent that destroying an unused application clears an application-limit refusal, which it never did. From fjall 38 the recipe says destroy does not clear it, and points at fjall apps deregister <app> --confirm <app>, run by an organisation owner or admin on a signed-in user credential.
With the skill installed, the agent follows the plan, review, apply recipe for application scaffolding: preview with fjall apps create --dry-run --agent, review the TOON output, apply, then deploy.
Add session-start context
install-skill writes the recipe only. Ambient session context is a separate opt-in step:
SessionStart entry to ~/.claude/settings.json which runs fjall agent session-context. Claude Code is the only host the installer targets today. See Session Hooks for opt-out, idempotency, and the payload shape.
MCP server quick start (beta)
1
Install the CLI the server shells out to
2
Build the server from a checkout
Run these from the inner workspace root (
<repo>/fjall/). @fjall/util provides the protocol schema and @fjall/cli is the subprocess target, so build both first.3
Register the server with your host
For Claude Desktop, edit
~/Library/Application Support/Claude/claude_desktop_config.json:4
Restart your host
The production tools, the
scaffold_from_repo prompt, and the fjall://plans/{planToken} resource scheme appear after restart.CLI resolution
The server locates the Fjall CLI at startup in two steps, in order:FJALL_CLI_PATH, an absolute path tocli.js.- A sibling lookup beside
process.execPath, which finds a globalnpm install -g fjall.
FjallCliNotFound. Set FJALL_CLI_PATH when the CLI lives outside the standard global-install path:
Production tools (MCP)
The server registers 23 production tools, plus a dev-onlyscaffold.protocol.echo behind FJALL_MCP_DEV=1. Every project-scoped tool takes an absolute path and spawns the CLI there, so the CLI reads that project’s fjall-config.json, active target, and organisation binding.
Scaffolding
Scaffold inputs
plan_app_scaffold refuses anything outside its declared vocabularies at the plan boundary, rather than minting a token whose apply fails in the CLI. pattern, patternTier and type derive from the same @fjall/util tuples fjall apps create reads. The rest are free-form strings or booleans, checked for shape rather than membership.
Every CLI-facing field lands in
resolvedInputs and is re-emitted on the apply argv, so apply_app_scaffold runs what the human reviewed. intent is recorded on the plan and never reaches the argv. path becomes the apply run’s --into.
A host built from a 37.x checkout sent free-form strings for pattern, type and database, and a patternTier of tinkerer or enterprise. Those are rejected now.
Organisation
Resources and deployment
There is no de-register tool. Freeing an application slot against the plan limit is CLI-only:
fjall apps deregister <app> --confirm <app> (see fjall apps).
Confirming a destroy
destroy is irreversible and has no plan/apply pair, so consent is taken before anything is spawned.
A bare call asks the host to confirm through MCP elicitation, and only a proceed: true answer reaches the CLI. The prompt names the application and the resolved project directory, because an agent that resolved a different project than the user had in mind is what the prompt exists to catch.
force and skipConfirmation both default to false, and both are strict booleans: the string "false" is a validation error, not consent. force does not bypass the confirmation. It adds --force to the CLI call once the host has answered.
The host gets ten minutes to put the prompt in front of a person, and a progress report from the host restarts that clock rather than counting against it. A host that cancels the request while the prompt is up gets a refusal, never a spawn.
Every one of these refusals ends Nothing was destroyed.
Regions
Compliance remediation
CI setup
plan_ci_setup pins the provider and application its own fjall ci setup --plan run resolved, never the values you passed, because apply_ci_setup replays the stored record rather than re-detecting. It refuses with CI_SETUP_PIN_UNRESOLVED, and plans nothing, when that run reports no provider and app (the cure it names: check the project resolves under fjall ci setup --plan, then re-plan), and again when what it resolved disagrees with an explicit provider or app you asked for. force, which overwrites an existing workflow file, is a strict boolean: the string "false" is a validation error, not consent.
apply_ci_setup writes the workflow file and returns workflowPath and mintUrl. It never returns a token: POST /api/ci/tokens accepts only interactive browser sessions, so the CLI has no mint path. Mint the token in the web app as an owner or admin under Settings → CI/CD Tokens (the mintUrl the tool returns), store it as the CI secret, then run verify_ci_setup. See CI/CD Deployment.Read-only listings
The server also registers
list_resources, which is not currently usable: it invokes fjall list without an application name, and the CLI requires one. Run fjall list --app <name> in a terminal for a single application’s resources.
Fjall has no manual profile step and no
fjall profile command. AWS profiles are derived in memory from your organisation config, and the active deployment account is selected with fjall target set <name>. See Understanding Profiles.Plan, review, apply
Most write paths split into a read-only plan tool and a destructive apply tool. Agents call them in order so the host can render the intermediate plan before any writes. Thedetect_app_framework, plan_app_scaffold, apply_app_scaffold trio is the canonical scaffold flow.
add_resource and destroy are the two exceptions. Neither has a plan tool, so there is no intermediate plan for the host to render before the write.
Plan tools return a planToken valid for 15 minutes. plan_app_scaffold additionally stores the plan as an MCP resource at fjall://plans/{planToken}, where the token is an HMAC-SHA256 value bound to the plan id, its expiry, and a per-process server secret. apply_app_scaffold takes that URI as planUri. The other apply tools take the bare planToken.
Both the apply tools and the resource read verify the token before any lookup:
Restarting the server invalidates outstanding plans by design.
Authentication
Both surfaces read the same token store at~/.fjall/auth.json (or $FJALL_CONFIG_DIR/auth.json). Run fjall login once before the agent’s first call.
Next Steps
Session Hooks
Install the hook that loads Fjall context at agent session start.
fjall login
Authenticate the CLI before the agent’s first call.
Understanding Profiles
See how AWS profiles are derived and how
fjall target selects the deploy account.fjall ci
Mint deploy tokens and wire up CI, the surface the CI setup tools drive.