Use Fulldev apps from a terminal or an AI agent. The CLI discovers the full HTTP API from OpenAPI and is a thin client of the Fulldev MCP server at https://app.full.dev/mcp, which has the tools of every app your organization gives you: it reads the tools, their schemas, and the instructions from the server each time, so it stays in step with the apps. Each app's tools start with its name, such as cms_.
| App | For |
|---|---|
cms |
Editing your website through the Fulldev CMS |
connect |
Your business tools, such as Shopify, through Fulldev Connect |
scan |
Scanning websites with Fulldev Scan, for administrators only |
sites |
A finished website from Fulldev Sites, for administrators only |
pages |
Reports and plans as web pages with Fulldev Pages, for administrators only |
contacts |
Daily synchronization of your Google contacts across multiple accounts with Import and Export |
send |
Customer message scenarios and deliveries |
work |
Tasks, projects and goals in your organization |
Run it from npm. It needs Node.js 24 or later.
npx -y fulldev --help
pnpm dlx fulldev --helpOr install it once:
npm install -g fulldev
fulldev --helpAdd the agent skill, which tells an agent when and how to use the CLI:
npx skills add fulldotdev/clifulldev login # once, for every app and organization
fulldev status # signed in, valid, email, organizations, expiry
fulldev logoutfulldev login opens your browser at app.full.dev, where you sign in with your Fulldev account, with a code sent to your email or with Google, and choose the organizations fulldev may work in: all of yours at first. It waits up to 10 minutes. Add --no-browser to only print the link.
On a computer without a browser, such as over SSH, run fulldev login --no-browser and open the link on your own computer. The page after sign-in does not load there, because it is meant for the computer that runs fulldev: copy its address from the address bar and paste it into the terminal.
One sign-in covers every app of the organizations you chose: the tokens are for the Fulldev MCP server, which checks on every call which apps you may use in which organization. To change the organizations, run fulldev login again. fulldev status lists them, with their slugs and the apps you may use in each.
fulldev logout revokes the refresh token at the authorization server (access tokens cannot be revoked and expire within 15 minutes) and deletes the tokens from this computer. When revoking fails, for example offline, it still deletes them and says so.
How it works:
- Browser sign-in uses OAuth with PKCE (S256) and a redirect to
http://127.0.0.1:<random port>/callback, or the pasted address of that redirect, after checking that it belongs to this sign-in. It asks for the server's MCP URL as the resource, so the token is only valid there. - The CLI is a public OAuth client that needs no registration: its client id is the address of its Client ID Metadata Document, which the authorization server at
https://app.full.dev/api/authreads. It never registers a client, so sign-in to a server that does not support such documents fails withCLIENT_METADATA_UNSUPPORTED. - Tokens are stored in the OS keychain (macOS Keychain, Windows Credential Manager, or the Secret Service on Linux) under the service
fulldev, one entry per server. Where no keychain is available, such as in many containers and CI runners, they go to~/.config/fulldev/auth.json(or$XDG_CONFIG_HOME/fulldev/auth.json), readable only by you;fulldev statussays which one is used. - Access tokens are refreshed when they expire. Parallel commands take turns through a lock file next to it, so they never refresh the same token twice.
Commands never start a sign-in without a terminal (when stdin or stdout is not a TTY): they fail at once with exit code 3 and say to run fulldev login. At a terminal they open the browser sign-in themselves; --no-login turns that off.
fulldev instructions # how to use every app you may use, from the server; read first
fulldev tools # name, title and description of every tool
fulldev call cms_list_repositories
fulldev cms instructions # the overview and the CMS's own part
fulldev cms tools # the CMS's tools only
fulldev cms tools commit_files # description, input schema, output schema, annotations
fulldev cms call read_file '{"branchId":"<id>","path":"src/content/home.md"}'
fulldev cms call commit_files --file changes.json
echo '{"branchId":"<id>"}' | fulldev cms call get_preview -
fulldev cms form wait <branchId> <formId> --timeout 60
fulldev help cms call # help for any commandAfter fulldev <app>, a tool's name may leave out the app's prefix: fulldev cms call read_file calls cms_read_file.
When the sign-in is for more than one organization, a call names the organization to work in with --org <slug>; without it the tool answers ORGANIZATION_REQUIRED. fulldev tools and fulldev instructions show the tools of every organization together. --all-orgs calls a tool that only reads in every organization that has its app and prints the answers together, each with its organization:
fulldev cms call list_repositories --org het-clubhuis
fulldev cms call list_repositories --all-orgs # {"organizations":[{"organization":{...},"result":{...}}, ...]}On the server the organization is the tool's organization argument, which every app tool takes when the sign-in is for several; fulldev_list_organizations lists them.
call prints the tool's result as JSON on stdout. When the tool fails, it prints the error on stderr and exits with 1.
fulldev cms form wait keeps calling cms_wait_for_form until the person sends the form, with a progress line on stderr each round, then prints the result. After --timeout minutes (default 30) it stops, also in the middle of a request, prints the form id, and exits with 2, so you can run it again.
Data is JSON on stdout. instructions and help are plain text. Progress lines go to stderr. Every error, including a wrong command, is one JSON object on stderr:
{
"error": {
"code": "SIGN_IN_REQUIRED",
"message": "Not signed in to Fulldev. Run: fulldev login",
"command": "fulldev login"
}
}| Code | Meaning |
|---|---|
| 0 | Done |
| 1 | Error, from the tool or the CLI |
| 2 | form wait timed out |
| 3 | Sign-in needed |
| 64 | Usage error |
--url <mcp url> or FULLDEV_URL selects another server, such as a deploy preview's, which serves it at /mcp. Each server has its own sign-in.
FULLDEV_URL=https://deploy-preview-12--fulldev-app.netlify.app/mcp fulldev login
fulldev cms tools --url https://deploy-preview-12--fulldev-app.netlify.app/mcppnpm install
pnpm check # format, lint, type check, tests, and that dist/ is up to date
pnpm build # writes dist/cli.mjsAn app is one entry in src/apps.ts; the server's address is server there. The OAuth client id is clientMetadataUrl in src/oauth.ts; the document at that address is published with the full.dev website.
dist/ is committed, because npx github:fulldotdev/cli runs it without a build step. Run pnpm build and commit dist/ with every source change.
Every change that users get adds a changeset with pnpm changeset. The fulldev package is published only from fulldotdev/cli: merging a change with its changeset to main opens a release pull request, and merging that publishes to npm from GitHub Actions with trusted publishing and provenance, without an npm token.
MCP shortcuts remain the curated tool interface. On a server exposing OpenAPI, the same CLI can discover and call every product HTTP operation, including ones omitted from MCP:
fulldev api contacts
fulldev api contacts.accounts.list '{}' --org my-company
fulldev contacts api accounts.list --file input.json --org my-companyUse an operation id from fulldev api <app>. Input is a JSON object, a file with --file, or stdin with -. Reads send query parameters; changes send JSON. Existing OAuth credentials and organization grants cover both interfaces. The CLI refuses redirects and paths outside the selected app before sending credentials. Servers without OpenAPI continue to support the existing MCP commands.