fulldev
v2.0.0
Published
Use Fulldev from the command line: one command for each Fulldev tool you may use, and its HTTP API.
Maintainers
Readme
Fulldev CLI
Use Fulldev from a terminal or an AI agent. Its commands are the Fulldev tools you may use, one command per tool, such as fulldev work list-tasks for work_list_tasks. The CLI reads them from the server each time, so it stays in step with Fulldev.
Install
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 Fulldev, through the Fulldev tools when they are connected and otherwise this CLI. It comes from the latest npm release:
npx skills add https://cdn.jsdelivr.net/npm/fulldev/skills/fulldev/SKILL.mdSign in
fulldev login # once, for every organization of the connection
fulldev status # signed in, valid, email, organizations, expiry
fulldev orgs # the organizations, with their slugs
fulldev logoutfulldev login opens your browser at app.full.dev, where you sign in with your Fulldev account, name the AI connection, tick its organizations (none at first) and choose how far it may go: Read (the default), Make changes or Administer. 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.
Every call is checked against the connection's choices and your current access. Change or revoke the connection under AI connections on your Fulldev profile. Running fulldev login again creates a separate connection.
fulldev logout revokes the refresh token at the authorization server (an issued access token may remain valid for up to 15 minutes; revoke the AI connection on your Fulldev profile to end its access immediately) 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 2.1 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.
Use
fulldev tools # every command you may use
fulldev work # one app's commands
fulldev work list-tasks --help # its description and fields
fulldev account get # your organizations, member id and apps
fulldev work list-tasks --status open --org acme # fields as --<field> <value>
fulldev work list-tasks --limit 20 --cursor <cursor>
fulldev work search --query "launch plan"
fulldev work get-task --id <id>
fulldev work create-task --title "Plan the launch" --labels launch --labels q4
fulldev work update-task '{"id":"<id>","title":"Plan","revision":3}'
fulldev connect google-calendar-events --from 2026-11-02T00:00:00Z --to 2026-11-09T00:00:00Z
fulldev account invite-member -f invite.json
echo '{"email":"[email protected]"}' | fulldev account invite-member -The tool <app>_<name> is the command fulldev <app> <name>, with - for _. fulldev tools --json prints the tools as the server lists them, with their input schemas, and fulldev <app> <command> --help --json one.
A command takes a JSON object as the argument, from a file with -f or --file, or from stdin with -, and each field of the tool's input as --<field> <value>, such as --member-id for memberId. A boolean is --<field> or --no-<field>; a list takes its flag once per item, or one JSON array; an object takes JSON. A field that is not in the tool's input, or given twice, is a usage error before anything is sent.
--org <slug> is the tool's organization: when the connection is for more than one organization, name the one to work in, or the server answers ORGANIZATION_REQUIRED. fulldev orgs lists the slugs.
The CLI's options of a command (--file, --text-file, --raw and, for a change, --idempotency-key) come after the command. A field of that command with the same name takes the flag, such as a tool's file: that option is then unavailable for the command, and its --help says so. -f <path> always reads the JSON input from a file. --url, --org, --json, --no-login, --no-browser, --help and --version are always the CLI's own, wherever they are: no tool or contract has a field of those names, and every command takes them, ignoring any it does not use, except login, which refuses --no-login.
Update a row only while nobody else changed it by sending the revision you read: a stale one answers REVISION_CONFLICT. A tool whose description says to confirm first changes something for people, such as an invitation email: an agent confirms with the person first.
Idempotency
Every command whose tool takes an idempotencyKey is sent with one, new for each run. When one fails, such as on a lost connection, its error names the key: repeat the command with --idempotency-key <key>, and the server does it at most once. The same key with another request is IDEMPOTENCY_CONFLICT; one still running is IN_PROGRESS.
The HTTP API's commands
fulldev api has the commands of the HTTP API's catalog, for its data types, actions and services. They take input as the tools' commands do, and send an Idempotency-Key with every create, update, action and service update.
fulldev api overview # the organizations and, in one, what you may use
fulldev api types # the data types you may read, with their operations
fulldev api tasks --help # its operations, filters and fields
fulldev api tasks list --status open --limit 20 # filters as --<filter> <value>
fulldev api tasks get <id>
fulldev api tasks update <id> '{"title":"Plan","revision":3}'
fulldev api actions # the actions you may run
fulldev api describe invite_member # its input, permission and whether to confirm
fulldev api run invite_member --email [email protected] --role member
fulldev api services get scan <id> # an instance's settings and status
fulldev api services query scan findings --site-id <id>Exact text
For Markdown and other text, --text-file <field>=<path> puts a file's exact UTF-8 content in one field of the input, and --raw <field> prints one text field of the result as it is, without JSON quotes or an added newline. Nothing is trimmed, and line endings stay as they are.
fulldev work update-task '{"id":"<id>","revision":3}' --text-file notes=plan.md
fulldev work get-task --id <id> --raw notes > plan.md- A field is a dotted path, such as
content.blocks.0.markdown. Objects on the way are made; arrays must be in the JSON, with the item. - The JSON and the flags leave that field out, and each field is named once.
-reads stdin, for one input only. - Names such as
__proto__andconstructor, an existing field, a missing array item, and text that is not UTF-8 are usage errors (exit 64), before anything is sent. - When the tool's output schema, or the type's row schema for
fulldev api, shows the field can never be text,--rawrefuses before sending (exit 64). - When the request succeeded but its field is missing or not text,
--rawprints nothing on stdout and exits with 1. The error has"succeeded": trueand the fullresult, such as a new row's id: use it, and do not send the request again.
Output and exit codes
Results print as tables, and one row as aligned fields; --json prints the server's JSON instead. A failed tool is an error with the server's code, message, status and details. Progress lines go to stderr. An error prints its code and message on stderr, with its details below; with --json it is one JSON object:
{
"error": {
"code": "SIGN_IN_REQUIRED",
"message": "Not signed in to Fulldev. Run: fulldev login",
"server": "https://app.full.dev/mcp",
"command": "fulldev login"
}
}| Code | Meaning | | ---- | --------------------------------- | | 0 | Done | | 1 | Error, from the server or the CLI | | 3 | Sign-in needed | | 64 | Usage error |
Deploy previews and local servers
--url <url> or FULLDEV_URL selects another server, such as a deploy preview's or a local one: its MCP URL, or its origin, which means its /mcp. Each server has its own sign-in.
FULLDEV_URL=https://deploy-preview-12--fulldev-app.netlify.app fulldev login
fulldev tools --url http://localhost:5173How it talks to the server
The tools' commands use the server's MCP endpoint, the URL the sign-in's token is issued for: tools/list for the commands, their help and flags, and tools/call to run one. fulldev api uses the HTTP API at /api/v1: GET /api/v1/overview and GET /api/v1/catalog for what you may use, GET /api/v1/catalog/<name> for a contract, /api/v1/data/<type>[/<id>|/search] for data, /api/v1/actions[/<name>] for actions and /api/v1/services[/<name>[/<id>]] with /api/v1/services/<name>/queries/<query> for services. fulldev orgs and fulldev status read the organizations from GET /api/v1/organizations. Redirects are refused, so the token never leaves the server it was issued for.
Develop
The CLI is packages/cli in Fulldev's workspace. From the workspace root:
vp run --filter fulldev check # format, lint and type check, with the workspace's settings
vp run --filter fulldev test:unit # its tests, once
vp run --filter fulldev build # writes dist/cli.mjs
vp run test:unit # its tests with every package's
vp run check # the checks of the whole workspaceThe server's address is server in src/target.ts. The OAuth client id is clientMetadataUrl in src/oauth.ts; the document at that address is published with the full.dev website.
Releases
The fulldev package is released by the workspace's CLI workflow (.github/workflows/cli.yml), which npm trusts without a token, and a maintainer's approval with 2FA. To release:
- In a pull request, set the new
versioninpackage.jsonand add it toCHANGELOG.md. - After it is merged, push the tag
cli-v<version>on that commit ofmain. The workflow checks that the tag matchespackage.json, runscheck,test:unitandbuild, packs that build and stages the version aslatest. - Approve it under Staged Packages on npmjs.com, or with
npm stage approve <id>. Only then can it be installed.
A version such as 0.8.0-rc.0 may be tagged on any branch and is staged under the dist-tag next, for a test with npx fulldev@next.
