Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

Penpot CLI

Agent-first command-line client for the official Penpot MCP server.

Penpot CLI does not reimplement Penpot operations and does not hardcode the server's tools. It connects through MCP Streamable HTTP, discovers tools dynamically, and invokes them from a shell.

Install

Homebrew is the primary installation method:

brew install oscarhugopaz/tap/penpot-cli

The formula is updated automatically after each GitHub release.

Ubuntu

Install the latest precompiled Linux binary without Homebrew or Go. The installer detects AMD64 or ARM64 and verifies the archive against the published SHA-256 checksum before installing it:

set -euo pipefail

repository="oscarhugopaz/penpot-cli"
release_url="$(curl --fail --silent --show-error --location \
  --output /dev/null --write-out '%{url_effective}' \
  "https://github.com/${repository}/releases/latest")"
version="${release_url##*/}"
version="${version#v}"

case "$(uname -m)" in
  x86_64 | amd64) arch="amd64" ;;
  aarch64 | arm64) arch="arm64" ;;
  *) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac

asset="penpot-cli_${version}_linux_${arch}.tar.gz"
download_url="https://github.com/${repository}/releases/download/v${version}"
install_dir="$(mktemp -d)"
trap 'rm -rf "${install_dir}"' EXIT

curl --fail --silent --show-error --location --retry 3 \
  --output "${install_dir}/${asset}" "${download_url}/${asset}"
curl --fail --silent --show-error --location --retry 3 \
  --output "${install_dir}/checksums.txt" "${download_url}/checksums.txt"

expected_sha="$(awk -v asset="./${asset}" '$2 == asset { print $1 }' \
  "${install_dir}/checksums.txt")"
if [[ ! "${expected_sha}" =~ ^[0-9a-f]{64}$ ]]; then
  echo "Missing or invalid checksum for ${asset}" >&2
  exit 1
fi

printf '%s  %s\n' "${expected_sha}" "${install_dir}/${asset}" | sha256sum --check -
tar -xzf "${install_dir}/${asset}" -C "${install_dir}"
sudo install -m 0755 "${install_dir}/penpot" /usr/local/bin/penpot

penpot version

The installer requires curl, tar, awk, sha256sum, and sudo. On a minimal Ubuntu installation:

sudo apt-get update
sudo apt-get install -y curl ca-certificates coreutils tar gawk

To build the development version from source instead:

make build
./bin/penpot version

Go is needed only for development, not for Homebrew installations using release binaries.

Prerequisites

Start the official Penpot MCP server that matches your Penpot version:

npx -y @penpot/mcp@latest

Then open a Penpot design file, load the Penpot MCP Plugin, and connect the plugin to the server. The default MCP endpoint is:

http://localhost:4401/mcp

Tool discovery works with only the MCP server running. Tools that interact with a design also require Penpot, an open design file, and a responsive connected plugin.

Agent workflow

An agent only needs three commands:

penpot tools --json
penpot tool info TOOL --json
penpot run TOOL --input '{...}' --json

Example:

penpot tool info high_level_overview --json
penpot run high_level_overview --input '{}' --json

With --json, stdout contains exactly one JSON document. Diagnostics go to stderr.

Commands

penpot tools
penpot tool info <tool>
penpot run <tool> [--input <json> | --input-file <path>]
penpot status [--probe-plugin]
penpot config set mcp-url [<url>]
penpot config set timeout <duration>
penpot config get <mcp-url|timeout>
penpot config list
penpot skill install [--force]
penpot version

Global options can appear before or after a command:

--mcp-url <url>
--timeout <duration>
--allow-insecure-remote
--json

Tool input can also be piped:

printf '%s' '{"type":"Penpot"}' | penpot run penpot_api_info --input-file - --json

Agent skill

Install the bundled Penpot CLI skill for compatible coding agents:

penpot skill install

The command writes ~/.agents/skills/penpot-cli/SKILL.md. Re-running it is safe when the installed content is unchanged. If the file was modified, the command preserves it unless replacement is explicitly requested:

penpot skill install --force

Use --json for automation. Restart the coding agent after installing or updating the skill so it can discover the file.

Status

penpot status checks the MCP endpoint, protocol session, and tool discovery. MCP does not expose plugin connection state directly, so the default status reports it as unknown.

penpot status --probe-plugin

The optional probe invokes execute_code with a side-effect-free nonce and reports whether the plugin is responsive. It does not inspect or modify the design.

Configuration

Save the MCP endpoint without editing a file manually. When the URL argument is omitted, the CLI opens a hidden prompt so tokens embedded in remote Penpot URLs are not stored in shell history:

penpot config set mcp-url
MCP URL (input hidden):
penpot config set timeout 2m10s

For automation, pipe the value through stdin instead of placing it in the command arguments:

printf '%s\n' "$PENPOT_MCP_URL" | penpot config set mcp-url

Passing the URL directly remains supported for local endpoints and backward compatibility:

penpot config set mcp-url http://localhost:4401/mcp

Read the stored configuration:

penpot config get mcp-url
penpot config list

All configuration commands support --json. They manage the stored configuration file; command-line flags and environment variables can still override its values.

Precedence, from highest to lowest:

  1. --mcp-url and --timeout
  2. PENPOT_CLI_MCP_URL and PENPOT_CLI_TIMEOUT
  3. $XDG_CONFIG_HOME/penpot-cli/config.json
  4. Built-in defaults

If XDG_CONFIG_HOME is unset, the file is ~/.config/penpot-cli/config.json:

{
  "mcpUrl": "http://localhost:4401/mcp",
  "timeout": "2m10s"
}

Plain HTTP is accepted only for loopback hosts by default. Use HTTPS for remote MCP servers. --allow-insecure-remote is an explicit escape hatch for trusted development networks.

Exit codes

Code Meaning
0 MCP operation completed without isError
2 Invalid command or tool input
3 Invalid configuration
4 HTTP/transport failure
5 MCP protocol failure
6 Tool not found
7 Tool returned isError: true

Some current Penpot tools catch internal failures and return diagnostic text without setting isError. The CLI preserves that response but cannot reliably convert such a textual failure into a non-zero exit code.

Development

Install Go on macOS:

brew install go

Then:

make check

The test suite runs against an in-process MCP Streamable HTTP server and covers discovery, pagination, tool inspection, tool calls, JSON output, and error exit codes.

Releases and Homebrew

Pushing a SemVer tag such as v0.1.0:

  1. runs tests;
  2. builds static macOS/Linux archives for ARM64 and AMD64;
  3. publishes checksums and a GitHub release;
  4. calls the reusable Homebrew notification workflow;
  5. dispatches penpot-cli-release to oscarhugopaz/homebrew-tap.

The repository secret TAP_DISPATCH_TOKEN must be a fine-grained token with access to oscarhugopaz/homebrew-tap and permission to create repository dispatches.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages