framer-cli is an agent-friendly command line wrapper around Framer's Server API. It gives shell scripts, AI coding agents, and local automation a predictable JSON interface for inspecting Framer projects, reading and writing CMS content, and triggering publish or deploy operations.
framer-cliis an unofficial community tool. It is not affiliated with, endorsed by, or supported by Framer or the Framer team.
The package also includes an optional Claude skill scaffold. Running framer-cli init writes a /framer skill into a repository so Claude can use the CLI with focused guidance for Framer CMS and blog workflows.
- Lists Framer project metadata, publish state, deployments, and changed paths.
- Reads Framer CMS collections, fields, and items.
- Creates, updates, or removes CMS items with explicit
--allow-writeconfirmation. - Provides convenience commands for projects with a
Blogcollection. - Accepts JSON from flags, files, or stdin for repeatable automation.
- Emits JSON output and JSON errors so agents can parse results safely.
- Scaffolds a Claude skill under
.claude/skills/framer/.
- Node.js 22 or newer.
- A Framer Server API key.
- A Framer project URL or project ID.
The Node.js 22 requirement comes from Framer's official framer-api package.
git clone https://github.com/decipherai/framer-cli.git
cd framer-cli
npm install
npm run buildRun the local build:
node dist/index.js --help
node dist/index.js methods --prettyFor local development, you can also link the binary:
npm link
framer-cli --helpThe CLI reads configuration in this order:
- Command-line flags.
- Environment variables.
- A
.envfile in the current working directory.
Supported values:
FRAMER_API_KEY="your_framer_server_api_key"
FRAMER_PROJECT_URL="https://framer.com/projects/Your-Project--abc123"
# or:
FRAMER_PROJECT_ID="abc123"You can copy .env.example to .env and fill in your own values. Keep .env out of git.
Inspect a project:
framer-cli call getProjectInfo --pretty
framer-cli call getPublishInfo --pretty
framer-cli cms collections --prettyInspect a CMS collection:
framer-cli cms fields Blog --pretty
framer-cli cms items Blog --limit 10 --prettyCreate or update a CMS item from a file:
framer-cli cms upsert-item Blog --item-file examples/blog-post.json --allow-write --prettyPublish only when you intend to mutate the live project:
framer-cli call publish --allow-write --prettyRead commands run without extra confirmation. Mutating commands require --allow-write.
Commands that require --allow-write include:
framer-cli call applyAgentChangesframer-cli call publishframer-cli call deployframer-cli cms upsert-itemframer-cli cms remove-itemframer-cli blog upsertframer-cli blog remove
This makes it harder for an agent or script to accidentally change a project while it is still gathering context.
List the low-level Framer method wrappers supported by this CLI.
framer-cli methods --prettyInvoke a supported low-level Framer method.
framer-cli call getProjectInfo --pretty
framer-cli call getDeployments --pretty
framer-cli call getChangeContributors --args '[1,5]' --pretty
framer-cli call deploy --args '["deployment_id",["example.com"]]' --allow-write --prettycall expects method arguments as a JSON array. You can pass the array inline, from a file, or through stdin:
framer-cli call deploy --args-file deploy-args.json --allow-write
printf '%s\n' '["deployment_id",["example.com"]]' | \
framer-cli call deploy --args-file - --allow-writeGeneric CMS collection and item commands.
framer-cli cms collections --pretty
framer-cli cms fields Blog --pretty
framer-cli cms items Blog --limit 20 --pretty
framer-cli cms get-item Blog --slug "my-post" --pretty
framer-cli cms upsert-item Blog --item-file post.json --allow-write --pretty
framer-cli cms remove-item Blog --slug "old-post" --allow-write --prettyConvenience commands for projects that use a Blog collection.
framer-cli blog fields --pretty
framer-cli blog list --limit 20 --pretty
framer-cli blog get --slug "my-post" --pretty
framer-cli blog upsert --item-file post.json --allow-write --pretty
framer-cli blog remove --slug "old-post" --allow-write --prettyblog upsert and cms upsert-item behave as upserts:
- If the payload includes an existing
id, the CLI updates that item. - Otherwise, if the payload slug matches an existing item, the CLI updates by slug.
- Otherwise, the CLI creates a new item.
- On updates, the CLI preserves the current draft state unless you explicitly set
draftor pass--draft/--published. - On id-based updates, the CLI preserves the current slug unless you explicitly change it.
Scaffold the Claude skill into the nearest git repository.
framer-cli init
framer-cli init --forceThis writes:
.claude/skills/framer/SKILL.md.claude/skills/framer/cli.md.claude/skills/framer/blog.md.claude/skills/framer/content.md
It also adds the required CLI permissions to .claude/settings.json.
After setup, use the skill in Claude with:
/framer
/framer blog create a draft post about our launch
/framer publish
cms upsert-item and blog upsert expect a single JSON object:
{
"slug": "example-post",
"draft": true,
"fieldData": {
"FIELD_ID": {
"type": "string",
"value": "Example value"
}
}
}Use framer-cli cms fields <collection> before writing. Framer CMS writes use field IDs, not display labels, and enum fields require enum case IDs.
You can provide item payloads with:
--item '<json>'--item-file /path/to/file.json--item-file -to read from stdin
npm install
npm run check-types
npm run build
npm pack --dry-runThe source lives in src/. The compiled package output goes to dist/.
Missing API key: setFRAMER_API_KEYor pass--api-key.Missing project: setFRAMER_PROJECT_URL, setFRAMER_PROJECT_ID, or pass--project.Collection "<name>" not found: runframer-cli cms collections --prettyand use the exact collection id or name.Provide exactly one of --id or --slug: narrow the item selector.--allow-write required: re-run the command with--allow-writeonce you intend to mutate the project.Expected a valid enum case: inspect fields and use the enum case ID, not the human label.
MIT