Official command-line interface for Marvin CMS Publishing API.
- 📊 Table output by default - Human-readable tables in your terminal
- 🔄 Multiple output formats - Table, JSON, YAML, CSV
- 🔍 Filter and query - Filter by entry type, collection, asset type
- 🎨 Renderer inspection - View entry type renderers and capabilities
- 🚀 Fast - Direct HTTP calls to publishing API
- 🔐 Site client tokens - Uses publishing API (not admin API)
- 👥 Workspace roles - Create invitation tokens with specific roles (VIEWER, AUTHOR, EDITOR, ADMIN, OWNER)
- 🔒 Enterprise-grade security - Secure credential handling, no shell history exposure, token masking in CI/CD
Version 2.6.0+ includes critical security improvements:
- Credentials are never exposed in shell history
- Tokens are automatically masked in CI/CD environments
- Input validation prevents common security vulnerabilities
- Atomic credential file writes prevent corruption
If upgrading from an older version, please see the Migration Guide for breaking changes.
- Node.js 18+
- A running Marvin instance
- A site client token (get from Marvin → Settings → Publishing → Site Clients)
npm install -g @inneropen/marvin-cligit clone https://github.com/inneropen/marvin-cli.git
cd marvin-cli
npm install
npm run build
npm linkThe Marvin CLI supports two authentication methods:
Store your credentials securely:
marvin loginYou'll be prompted for your user token (input is hidden for security). The token is validated before being saved to ~/.marvin/credentials.json.
Benefits:
- Token is never visible in shell history
- Automatic token validation
- Works across all commands
- Secure file permissions (0600)
For CI/CD and automation:
# User authentication (Platform API)
export MARVIN_USER_TOKEN="user_..."
# Site client authentication (Publishing API)
export MARVIN_SITE_TOKEN="site_client_..."
# Workspace configuration
export MARVIN_WORKSPACE_SLUG="your-workspace"
export MARVIN_API_URL="https://marvin.example.com"Security best practices:
- Never commit tokens to version control
- Use your CI/CD's secret management (GitHub Secrets, GitLab CI Variables)
- Rotate tokens regularly
- Use workspace-specific tokens with minimal permissions
To configure a site client token for a specific workspace:
# Interactive (recommended)
marvin workspace token
# From stdin (for scripts)
echo "$SITE_TOKEN" | marvin workspace token --from-stdin
# For specific workspace
marvin workspace token --for my-workspaceNote: Tokens are automatically masked in non-TTY environments (CI/CD logs) to prevent exposure.
# Get workspace site configuration
marvin site
# List all published entries
marvin entries
# Get a single entry
marvin entry about
# List collections
marvin collections
# Get a collection with its entries
marvin collection featured
# List entries in a collection
marvin collection-entries featured
# List all resources
marvin resources
# Get a single resource
marvin resource kuroki-s022
# Get entries that use a resource
marvin resource-entries kuroki-s022
# List all assets
marvin assets# Filter entries by type
marvin entries --entry-type page
marvin entries --entry-type project
# Filter entries by collection
marvin entries --collection featured
# Limit results
marvin entries --limit 10
# Filter assets by MIME type
marvin assets --type image
marvin assets --type videoThe CLI supports four output formats:
marvin entriesOutput:
┌───────────────┬─────────┬─────────┬───────────┬────────────┐
│ Title │ Slug │ Type │ Status │ Published │
├───────────────┼─────────┼─────────┼───────────┼────────────┤
│ About Us │ about │ page │ published │ 2026-07-01 │
│ Contact │ contact │ page │ published │ 2026-07-02 │
└───────────────┴─────────┴─────────┴───────────┴────────────┘
marvin entries --json
# or
marvin entries --output jsonOutput:
[
{
"slug": "about",
"title": "About Us",
"entryType": "page",
"status": "published",
"publishedAt": "2026-07-01T12:00:00Z"
}
]marvin collections --yamlOutput:
- slug: featured
name: Featured Projects
description: Our best work
entryCount: 5marvin resources --csv > resources.csvOutput:
Name,Slug,Type,Description,URL
Kuroki S022 Denim,kuroki-s022,fabric,Premium Japanese selvedge,https://kuroki.comGlobal options (use before the command):
marvin --help # Show help
marvin --version # Show version
marvin --api-url <url> # Override MARVIN_API_URL
marvin --token <token> # Override MARVIN_SITE_CLIENT_TOKEN
marvin --workspace <slug> # Override MARVIN_WORKSPACE_SLUG
marvin --output <format> # Set output format (table, json, yaml, csv)
marvin --json # Shortcut for --output json
marvin --yaml # Shortcut for --output yaml
marvin --csv # Shortcut for --output csvExample:
# Use a different workspace
marvin --workspace other-workspace entries
# Output as JSON
marvin entries --json
# Override API URL and output CSV
marvin --api-url https://marvin.example.com assets --csvmarvin site [--json|--yaml]Fetch workspace site configuration (title, tagline, logo, etc.).
marvin entries [options]Options:
--entry-type <slug>- Filter by entry type (e.g.,page,project)--collection <slug>- Filter by collection--limit <number>- Limit results
Examples:
marvin entries # All entries
marvin entries --entry-type page # Only pages
marvin entries --collection featured # Entries in "featured" collection
marvin entries --limit 5 # First 5 entriesmarvin entry <slug>Fetch a single entry by slug.
marvin collectionsList all collections with entry counts.
marvin collection <slug>Fetch a single collection with metadata.
marvin collection-entries <slug>List all entries in a collection.
marvin resourcesList all resources (fabrics, tools, suppliers, etc.).
marvin resource <slug>Fetch a single resource by slug.
marvin resource-entries <slug>List all entries that reference a resource.
marvin assets [options]Options:
--type <type>- Filter by MIME type prefix (e.g.,image,video,audio)--limit <number>- Limit results
Examples:
marvin assets # All assets
marvin assets --type image # Only images
marvin assets --type video # Only videosmarvin publish renderers [options]List entry types with their renderer declarations and capabilities. By default, only shows entry types marked as rendered (isRendered: true).
Options:
--all- Include all entry types, not just rendered ones
Examples:
marvin publish renderers # Rendered entry types only
marvin publish renderers --all # All entry types
marvin publish renderers --json # JSON outputOutput:
┌──────────────────┬─────────────────┬───────────┬──────────────────────────────────┬─────────────┬──────────┐
│ Name │ Slug │ Renderer │ Package │ Publishable │ Routable │
├──────────────────┼─────────────────┼───────────┼──────────────────────────────────┼─────────────┼──────────┤
│ Page │ page │ page │ @inneropen/marvin-renderers-core │ true │ true │
│ Article │ article │ article │ @inneropen/marvin-renderers-core │ true │ true │
│ FAQ │ faq │ faq │ @inneropen/marvin-renderers-core │ true │ true │
│ Navigation Item │ navigation-item │ navigation│ @inneropen/marvin-renderers-core │ true │ false │
└──────────────────┴─────────────────┴───────────┴──────────────────────────────────┴─────────────┴──────────┘
See Renderers Command Documentation for details.
marvin entries --json > entries.jsonmarvin entries --json | jq 'length'marvin resources --csv > resources.csvif marvin entry about --json > /dev/null 2>&1; then
echo "About page exists"
else
echo "About page not found"
fimarvin assets --type image --json | jq -r '.[].name'No Shell History Exposure:
- Passwords and tokens are entered via secure prompts (hidden input)
- No credential flags on command line
- No exposure in
ps auxor process listings
Token Masking:
- Tokens automatically masked in CI/CD environments
- Full tokens shown only in interactive terminals (TTY)
- Format:
site****xyz(first/last 4 characters)
Atomic Credential Writes:
- Credentials file protected by atomic rename operations
- No corruption on crash or interrupt (Ctrl+C)
- Secure permissions: directory 0700, file 0600
Path Validation:
- Files validated before reading
- Warnings for sensitive paths (SSH keys, credentials, etc.)
- Protection against reading from
/etc/,~/.ssh/,~/.aws/
URL Validation:
- API URLs validated for protocol (http/https only)
- Warnings for HTTP on non-localhost
- Warnings for private IP ranges (SSRF prevention)
Data Validation:
- JSON objects validated before API calls
- Email addresses validated (RFC 5322)
- Positive integers validated with explicit radix
- Graceful shutdown (no data loss)
- No
process.exit(1)mid-operation - Cleanup handlers execute properly
- Clear error messages with suggestions
Make sure you've configured authentication:
# Option 1: Login
marvin login
# Option 2: Environment variables
export MARVIN_API_URL=https://marvin.example.comYour token is invalid or expired:
# Re-authenticate
marvin login
# Or generate new token in Marvin UI:
# Settings → Publishing → Site ClientsNote: The login command validates tokens before saving (v2.6.0+), so you'll know immediately if a token is invalid.
You need to authenticate for Platform API commands:
# Option 1: Save credentials
marvin login
# Option 2: Environment variable
export MARVIN_USER_TOKEN="user_..."
marvin platform entries listNote: The --user-token flag has been removed for security reasons (v2.6.0+). Use environment variables or saved credentials instead.
Check that:
- Your
MARVIN_API_URLis correct - The Marvin server is running
- The workspace slug is correct
- The entry/collection/resource slug exists
Install globally:
npm install -g @inneropen/marvin-cliOr if using from source:
npm linkMake sure you're using Node.js 18+:
node --version # Should be v18 or higherReinstall dependencies:
rm -rf node_modules package-lock.json
npm install
npm run build"Warning: Reading from sensitive path"
You're reading from a potentially sensitive file (e.g., SSH key, credentials). This is usually unintentional.
# If intentional, proceed
# If not, check your --file path
marvin platform entries create --file ~/correct/path.json"Warning: Using HTTP (not HTTPS)"
You're connecting to a non-localhost server over HTTP:
# Use HTTPS for production
marvin --api-url https://marvin.example.com entries list
# HTTP is OK for localhost
marvin --api-url http://localhost:8000 entries list"Warning: API URL points to private IP range"
You're connecting to a private IP address. This is usually intentional for internal services, but could indicate SSRF risk:
# If this is your internal Marvin server, this is OK
# If unexpected, verify the URL
marvin --api-url https://marvin.internal.company.com entries listnpm start -- entries --jsonnpm run devThen in another terminal:
marvin entriesnpm testThis CLI uses:
- Commander.js - CLI framework
- Native fetch - HTTP requests to Marvin API
- dotenv - Environment configuration
- TypeScript - Type safety
The CLI is a thin wrapper around the Marvin Publishing API. It does NOT:
- Import the Python backend
- Start the FastAPI server
- Access the database directly
- Require admin authentication
It ONLY makes HTTP calls to the Publishing API endpoints using site client tokens.
- Migration Guide - Upgrading from older versions
- Security Best Practices - Security features and recommendations
- Marvin SDK - TypeScript SDK for Astro/Next.js sites
- Marvin CMS - Main CMS repository
We welcome contributions! Please see our Contributing Guide for details.
MIT License - See main Marvin repository for details.