@s2p2/confluence-cli
v0.1.13
Published
A TypeScript CLI for Atlassian Confluence — fork of pchuri/confluence-cli with blog posts, labels, diagnostics, and grouped commands
Maintainers
Readme
Confluence CLI
A powerful command-line interface for Atlassian Confluence that allows you to read, search, and manage your Confluence content from the terminal.
Features
- 📖 Read pages - Get page content in text or HTML format
- 🔍 Search - Find pages using Confluence's powerful search with
--spaceand--typefilters - ℹ️ Page info - Get detailed information about pages
- 🏠 Spaces - List spaces and get space details
- ✏️ Create pages - Create new pages with support for Markdown, HTML, or Storage format
- 📝 Update pages - Update existing page content and titles
- 🗑️ Delete pages - Delete (or move to trash) pages by ID or URL
- 📎 Attachments - List, download, upload, or delete page attachments
- 🏷️ Labels - List, add, and remove labels on pages
- 💾 Properties - List, get, set, and delete content properties (key-value metadata)
- 💬 Comments - List, create, and delete page comments (footer or inline)
- 📰 Blog posts - List, create, update, and delete blog posts
- 📦 Export - Save a page and its attachments to a local folder
- 🛠️ Edit workflow - Export page content for editing and re-import
- 🔀 Profiles - Manage multiple Confluence instances with named configuration profiles
- 🔒 Read-only mode - Profile-level write protection for safe AI agent usage
- 🔄 Format conversion - Convert between Markdown, HTML, Storage, and text formats locally (no server required)
- 🩺 Diagnostics - Validate configuration, authentication, and connectivity with
doctor {--json}output on most commands for machine-readable results- 🔧 Easy setup - Simple configuration with environment variables or interactive setup
Installation
npm
npm install -g @s2p2/confluence-cliOr run directly with npx:
npx @s2p2/confluence-cliClaude Code Integration
confluence-cli ships as a Claude Code plugin. Once installed, Claude Code understands all confluence-cli commands automatically and receives updates when the skill is improved.
Option 1: Install as Plugin (recommended)
Add the marketplace and install the plugin:
/plugin marketplace add S2P2/confluence-cli
/plugin install confluence@S2P2-confluence-cliOption 2: Install Skill manually
If you prefer not to use the plugin system, copy the skill documentation into your project:
confluence install-skillThis creates .claude/skills/confluence/SKILL.md in your current directory. Claude Code picks it up automatically.
Quick Start
Initialize configuration:
confluence initRead a page:
confluence read 123456789Search for pages:
confluence search "my search term"List child pages:
confluence children 123456789Create a new page:
confluence create "My New Page" SPACEKEY --content "Hello World!"Update a page:
confluence update 123456789 --content "Updated content"
Configuration
Option 1: Interactive Setup
confluence initThe wizard helps you choose the right API endpoint and authentication method. It recommends /wiki/rest/api for Atlassian Cloud domains (e.g., *.atlassian.net) and /rest/api for self-hosted/Data Center instances, then prompts for Basic (email/username + token/password), Service Account (ATSTT token), Bearer (PAT for Data Center), or client-certificate (mTLS) authentication. When Service Account is selected for a Cloud domain, it auto-fetches the cloud ID from /_edge/tenant_info and configures the api.atlassian.com gateway.
Option 2: Non-interactive Setup (CLI Flags)
Provide all required configuration via command-line flags. Perfect for CI/CD pipelines, Docker builds, and AI coding agents.
Complete non-interactive mode (all required fields provided):
confluence init \
--domain "company.atlassian.net" \
--api-path "/wiki/rest/api" \
--auth-type "basic" \
--email "[email protected]" \
--token "your-api-token"Service account (recommended for agents — auto-configures gateway):
# Just provide your site domain and ATSTT token — cloud ID is fetched automatically
confluence init \
--domain "yourcompany.atlassian.net" \
--auth-type "service-account" \
--token "ATSTT..."Scoped API token (manual gateway configuration):
# Replace <your-cloud-id> with your actual Cloud ID
confluence init \
--domain "api.atlassian.com" \
--api-path "/ex/confluence/<your-cloud-id>/wiki/rest/api" \
--auth-type "basic" \
--email "[email protected]" \
--token "your-scoped-token"Named profile (save to a specific profile):
confluence --profile staging init \
--domain "staging.example.com" \
--api-path "/rest/api" \
--auth-type "bearer" \
--token "your-personal-access-token"mTLS profile (self-hosted or reverse-proxied Confluence APIs):
confluence --profile corp init \
--domain "docs.example.com" \
--api-path "/confluence/rest/api" \
--auth-type "mtls" \
--tls-client-cert "~/.certs/client.pem" \
--tls-client-key "~/.certs/client.key" \
--tls-ca-cert "~/.certs/ca-chain.pem"Cookie authentication profile (Enterprise SSO):
confluence --profile sso init \
--domain "confluence.company.com" \
--api-path "/rest/api" \
--auth-type "cookie" \
--cookie "JSESSIONID=abc123xyz..."
# Multiple cookies are also supported:
confluence --profile sso init \
--domain "confluence.company.com" \
--auth-type "cookie" \
--cookie "JSESSIONID=abc123; XSRF-TOKEN=xyz789"Hybrid mode (some fields provided, rest via prompts):
# Domain and token provided, will prompt for auth method and email
confluence init --domain "company.atlassian.net" --token "your-api-token"
# Email indicates basic auth, will prompt for domain and token
confluence init --email "[email protected]" --token "your-api-token"Available flags:
-d, --domain <domain>- Confluence domain (e.g.,company.atlassian.net)-p, --api-path <path>- REST API path (e.g.,/wiki/rest/api)-a, --auth-type <type>- Authentication type:basic,service-account,bearer,mtls, orcookie-e, --email <email>- Email or username for basic authentication-t, --token <token>- API token or password-c, --cookie <cookie>- Cookie for Enterprise SSO authentication (e.g.,"JSESSIONID=...")--tls-client-cert <path>- Client certificate for mTLS authentication--tls-client-key <path>- Client private key for mTLS authentication--tls-ca-cert <path>- Optional CA certificate chain for mTLS authentication--read-only- Enable read-only mode (blocks all write operations)
⚠️ Security note: While flags work, storing tokens in shell history is risky. Prefer environment variables (Option 3) for production environments.
Option 3: Environment Variables
export CONFLUENCE_DOMAIN="your-domain.atlassian.net"
export CONFLUENCE_API_TOKEN="your-api-token" # or password for on-premise (alias: CONFLUENCE_PASSWORD)
export CONFLUENCE_EMAIL="[email protected]" # required for basic auth (alias: CONFLUENCE_USERNAME for on-premise)
export CONFLUENCE_API_PATH="/wiki/rest/api" # Cloud default; use /rest/api for Server/DC
# Optional: set to 'bearer' for self-hosted/Data Center, 'service-account' for ATSTT tokens
export CONFLUENCE_AUTH_TYPE="basic"
# Optional: select a named profile (overridden by --profile flag)
export CONFLUENCE_PROFILE="default"mTLS environment variables:
export CONFLUENCE_DOMAIN="docs.example.com"
export CONFLUENCE_API_PATH="/confluence/rest/api"
export CONFLUENCE_AUTH_TYPE="mtls"
export CONFLUENCE_TLS_CLIENT_CERT="~/.certs/client.pem"
export CONFLUENCE_TLS_CLIENT_KEY="~/.certs/client.key"
export CONFLUENCE_TLS_CA_CERT="~/.certs/ca-chain.pem" # optionalCookie environment variables (Enterprise SSO):
export CONFLUENCE_DOMAIN="confluence.company.com"
export CONFLUENCE_API_PATH="/rest/api"
export CONFLUENCE_AUTH_TYPE="cookie"
export CONFLUENCE_COOKIE="JSESSIONID=abc123xyz..."Service account (recommended for agents):
export CONFLUENCE_DOMAIN="api.atlassian.com"
export CONFLUENCE_API_PATH="/ex/confluence/<your-cloud-id>/wiki/rest/api"
export CONFLUENCE_AUTH_TYPE="service-account"
export CONFLUENCE_API_TOKEN="ATSTT..."
export CONFLUENCE_SITE_URL="https://yourcompany.atlassian.net"CONFLUENCE_API_PATH defaults to /wiki/rest/api for Atlassian Cloud domains and /rest/api otherwise. Override it when your site lives under a custom reverse proxy or on-premises path. CONFLUENCE_AUTH_TYPE defaults to basic when an email is present and falls back to bearer otherwise. For mtls, set CONFLUENCE_TLS_CLIENT_CERT and CONFLUENCE_TLS_CLIENT_KEY; CONFLUENCE_TLS_CA_CERT is optional.
Custom domains on Confluence Cloud:
If your Confluence Cloud instance uses a custom domain (e.g., wiki.example.org instead of *.atlassian.net), the CLI may misidentify it as a Server/Data Center instance and produce broken link formats. Set CONFLUENCE_FORCE_CLOUD=true to override the automatic detection:
export CONFLUENCE_FORCE_CLOUD=trueOr add "forceCloud": true to your profile in ~/.confluence-cli/config.json:
{
"profiles": {
"default": {
"domain": "wiki.example.org",
"forceCloud": true
}
}
}Link rendering on Cloud (linkStyle):
Some Cloud instances — particularly custom-domain Cloud setups — fail to render smart links (<a data-card-appearance="inline">) and show "Cannot handle: DefaultLink" errors instead. If you hit this, set linkStyle to plain to emit simple <a href> tags, which render reliably everywhere:
export CONFLUENCE_LINK_STYLE=plainOr per-profile:
{
"profiles": {
"default": {
"domain": "wiki.example.org",
"forceCloud": true,
"linkStyle": "plain"
}
}
}Valid values: smart (Cloud smart links), plain (simple <a href>), wiki (Server/DC ac:link). When unset, the CLI picks smart for Cloud and wiki for Server/DC — existing behavior is unchanged.
Read-only mode (recommended for AI agents):
export CONFLUENCE_READ_ONLY=trueWhen set, all write operations (create, update, delete, etc.) are blocked at the CLI level. The environment variable overrides the profile's readOnly setting.
Getting Your API Token
Atlassian Cloud:
- Go to Atlassian Account Settings
- Click "Create API token"
- Give it a label (e.g., "confluence-cli")
- Copy the generated token
Atlassian Cloud — Service Account (recommended for agents and automation):
Service accounts use ATSTT tokens via the api.atlassian.com gateway. The service-account auth type auto-fetches the cloud ID from /_edge/tenant_info and configures the correct API path.
- Go to Atlassian Admin → Directory → Service accounts
- Click Create credentials → API token
- Select scopes (see below). You need both Classic (v1) and Granular (v2) scopes.
- Configure with:
confluence init \ --domain "yourcompany.atlassian.net" \ --auth-type "service-account" \ --token "ATSTT..."
The CLI automatically fetches the cloud ID and configures api.atlassian.com as the gateway.
Atlassian Cloud — Scoped API Token (manual gateway configuration):
Scoped tokens restrict access to specific Atlassian products and permissions, following the principle of least privilege. They use a different API gateway (api.atlassian.com) instead of your site domain.
- Create a scoped token in your Atlassian Admin settings
- Find your Cloud ID by visiting
https://<your-site>.atlassian.net/_edge/tenant_info - Configure with:
- Domain:
api.atlassian.com - API path:
/ex/confluence/<your-cloud-id>/wiki/rest/api - Auth type:
basic(email + scoped token)
- Domain:
Required scopes for service accounts and scoped API tokens:
When creating a scoped token, select the following classic scopes based on your needs:
| Scope | Required for |
|-------|-------------|
| read:confluence-content.all | Reading pages and blog posts (read, info) |
| read:confluence-content.summary | Reading content summaries and metadata (read, info) |
| read:confluence-space.summary | Listing spaces (spaces) |
| search:confluence | Searching content (search) |
| readonly:content.attachment:confluence | Downloading attachments (attachments --download) |
| write:confluence-content | Creating and updating pages (create, update) |
| write:confluence-file | Uploading attachments (attachments --upload) |
| write:confluence-space | Managing spaces |
For read-only usage, select at minimum: read:confluence-content.all, read:confluence-content.summary, read:confluence-space.summary, and search:confluence.
On-premise / Data Center: Use your Confluence username and password for basic authentication.
mTLS-protected Confluence APIs: Some self-hosted or reverse-proxied deployments authenticate at the TLS layer with a client certificate instead of sending an application-level token. In these environments, configure authType=mtls and provide certificate paths via CLI flags or environment variables. No Authorization header will be sent in mTLS mode.
Enterprise SSO with Cookie Authentication: For Confluence instances behind Enterprise SSO (SAML, OAuth, Okta, etc.) where API tokens or Basic/Bearer auth are not available, you can authenticate using session cookies. After logging in through your browser, extract the session cookie (typically JSESSIONID or similar) from your browser's dev tools and configure it via the --cookie flag or CONFLUENCE_COOKIE environment variable. The cookie is sent in the Cookie header instead of an Authorization header. Note that session cookies typically expire, so you'll need to refresh them periodically. For security, prefer CONFLUENCE_COOKIE env var or interactive prompt over --cookie flag since command-line arguments may be visible in shell history and process listings.
Usage
Read a Page
# Read by page ID
confluence read 123456789
# Read native Confluence storage content
confluence read 123456789 --format storage
# Read in markdown format
confluence read 123456789 --format markdown
# Read by URL (must contain pageId parameter)
confluence read "https://your-domain.atlassian.net/wiki/viewpage.action?pageId=123456789"Use --format storage when you need Confluence's native storage representation, especially for macros and other Confluence-specific markup.
Get Page Information
confluence info 123456789
# Emit machine-readable metadata
confluence info 123456789 --format jsonExample JSON shape:
{
"id": "123456789",
"title": "Architecture Overview",
"type": "page",
"status": "current",
"spaceKey": "ENG",
"parentId": "100200300",
"version": 7,
"url": "https://your-domain.atlassian.net/wiki/spaces/ENG/pages/123456789/Architecture+Overview"
}Search Pages
# Basic search
confluence search "search term"
# Limit results
confluence search "search term" --limit 5
# Filter by space
confluence search "search term" --space MYSPACE
# Filter by content type
confluence search "search term" --type blog
# JSON output
confluence search "search term" --jsonList or Download Attachments
# List all attachments on a page
confluence attachments 123456789
# Filter by filename and limit the number returned
confluence attachments 123456789 --pattern "*.png" --limit 5
# Show download URLs for matching attachments
confluence attachments 123456789 --pattern "*.png" --download
# JSON output with download URLs
confluence attachments 123456789 --download --format json⚠️ Service account limitation: When using a service account or scoped API token,
--downloaddisplays resolved download URLs instead of fetching files. Atlassian's download endpoints return 401 for scoped tokens regardless of granted scopes. Open the URLs in a browser (where you're logged in) or use a personal API token (auth-type: basic) to download files directly.
Upload Attachments
# Upload a single attachment
confluence attachment-upload 123456789 --file ./report.pdf
# Upload multiple files with a comment
confluence attachment-upload 123456789 --file ./a.pdf --file ./b.png --comment "v2"
# Replace an existing attachment by filename
confluence attachment-upload 123456789 --file ./diagram.png --replaceDelete Attachments
# Delete an attachment by ID
confluence attachment-delete 123456789 998877
# Skip confirmation
confluence attachment-delete 123456789 998877 --yesContent Properties
# List all properties on a page
confluence property-list 123456789
# Get a specific property
confluence property-get 123456789 my-key
# Set a property (creates or updates with auto-versioning)
confluence property-set 123456789 my-key --value '{"color":"#ff0000"}'
# Set a property from a JSON file
confluence property-set 123456789 my-key --file ./property.json
# Delete a property
confluence property-delete 123456789 my-key
# Skip confirmation on delete
confluence property-delete 123456789 my-key --yesComments
# List all comments (footer + inline)
confluence comments 123456789
# List inline comments as markdown
confluence comments 123456789 --location inline --format markdown
# Create a footer comment
confluence comment add 123456789 --content "Looks good to me!"
# Create an inline comment
confluence comment add 123456789 \
--location inline \
--content "Consider renaming this" \
--inline-selection "foo" \
--inline-original-selection "foo"
# Reply to a comment
confluence comment add 123456789 --parent 998877 --content "Agree with this"
# Delete a comment
confluence comment-delete 998877Inline comment creation note (Confluence Cloud): Creating inline comments requires editor-generated highlight metadata (matchIndex, lastFetchTime, serializedHighlights, plus the selection text). The public REST API does not provide these fields, so inline creation and inline replies can fail with a 400 unless you supply the full --inline-properties payload captured from the editor. Footer comments and replies are fully supported.
Blog Posts
# List blog posts in a space
confluence blog list MYSPACE
# Get blog post details
confluence blog get 123456789
confluence blog get 123456789 --json
# Read blog post body content
confluence blog read 123456789
confluence blog read 123456789 --format markdown
confluence blog read 123456789 --format text
# Create a blog post
confluence blog create "Release Notes" MYSPACE --content "# v2.0" --format markdown
# Update a blog post
confluence blog update 123456789 --content "Updated content" --format markdown
confluence blog update 123456789 --title "New Title" --content "Updated content"
# Delete a blog post
confluence blog delete 123456789
confluence blog delete 123456789 --yesLabels
# List labels on a page
confluence label list 123456789
confluence label list 123456789 --json
# Add a label
confluence label add 123456789 meeting-notes
# Delete a label
confluence label delete 123456789 meeting-notesDiagnostics
# Check configuration, auth, and connectivity
confluence doctor
# Also verify access to a specific space
confluence doctor --space MYSPACE
# JSON output
confluence doctor --jsonExport a Page with Attachments
# Export page content (markdown by default) and all attachments
confluence export 123456789 --dest ./exports
# Custom content format/filename and attachment filtering
confluence export 123456789 --format html --file content.html --pattern "*.png"
# Skip attachments if you only need the content file
confluence export 123456789 --skip-attachmentsList Spaces
# List all spaces
confluence space list
# Alias
confluence spacesGet Space Details
confluence space get ENG
confluence space get ENG --jsonList Child Pages
# List direct child pages
confluence children 123456789
# List all descendants recursively
confluence children 123456789 --recursive
# Display as tree structure
confluence children 123456789 --recursive --format tree
# Show page IDs and URLs
confluence children 123456789 --show-id --show-url
# Limit recursion depth
confluence children 123456789 --recursive --max-depth 3
# Output as JSON for scripting
confluence children 123456789 --recursive --format json > children.jsonchildren --format json returns structured metadata for each page, including id, title, type, status, spaceKey, parentId, version, and url. Recursive output also includes depth, and when available, ancestors.
Example recursive JSON item:
{
"pageId": "123456789",
"childCount": 2,
"children": [
{
"id": "200300400",
"title": "Child Page",
"type": "page",
"status": "current",
"spaceKey": "ENG",
"parentId": "123456789",
"version": 4,
"url": "https://your-domain.atlassian.net/wiki/spaces/ENG/pages/200300400/Child+Page",
"depth": 1,
"ancestors": [
{
"id": "123456789",
"type": "page",
"title": "Architecture Overview"
}
]
}
]
}Find a Page by Title
# Find page by title
confluence find "Project Documentation"
# Find page by title in a specific space
confluence find "Project Documentation" --space MYTEAMCreate a New Page
# Create with inline content and markdown format
confluence create "My New Page" SPACEKEY --content "**Hello** World!" --format markdown
# Create from a file
confluence create "Documentation" SPACEKEY --file ./content.md --format markdownCreate a Child Page
# Create child page with inline content
confluence create-child "Meeting Notes" 123456789 --content "This is a child page"
# Create child page from a file
confluence create-child "Tech Specs" 123456789 --file ./specs.md --format markdownCopy Page Tree
# Copy a page and all its children to a new location
confluence copy-tree 123456789 987654321 "Project Docs (Copy)"
# Copy with maximum depth limit (only 3 levels deep)
confluence copy-tree 123456789 987654321 --max-depth 3
# Exclude pages by title (supports wildcards * and ?; case-insensitive)
confluence copy-tree 123456789 987654321 --exclude "temp*,test*,*draft*"
# Control pacing and naming
confluence copy-tree 123456789 987654321 --delay-ms 150 --copy-suffix " (Backup)"
# Dry run (preview only)
confluence copy-tree 123456789 987654321 --dry-run
# Quiet mode (suppress progress output)
confluence copy-tree 123456789 987654321 --quietNotes:
- Preserves the original parent-child hierarchy when copying.
- Continues on errors: failed pages are logged and the copy proceeds.
- Exclude patterns use simple globbing:
*matches any sequence,?matches any single character, and special regex characters are treated literally. - Large trees may take time; the CLI applies a small delay between sibling page creations to avoid rate limits (configurable via
--delay-ms). - Root title suffix defaults to
(Copy); override with--copy-suffix. Child pages keep their original titles. - Use
--fail-on-errorto exit non-zero if any page fails to copy.
Update an Existing Page
# Update title only
confluence update 123456789 --title "A Newer Title for the Page"
# Update content only from a string
confluence update 123456789 --content "Updated page content."
# Update content from a file
confluence update 123456789 --file ./updated-content.md --format markdown
# Update both title and content
confluence update 123456789 --title "New Title" --content "And new content"Move a Page to New Parent
# Move page by ID
confluence move 123456789 987654321
# Move page and rename it
confluence move 123456789 987654321 --title "Relocated Page"
# Move using URLs (for convenience)
confluence move "https://domain.atlassian.net/wiki/viewpage.action?pageId=123456789" \
"https://domain.atlassian.net/wiki/viewpage.action?pageId=987654321"Note: Pages can only be moved within the same Confluence space. Cross-space moves are not supported.
Delete a Page
# Delete by page ID (prompts for confirmation)
confluence delete 123456789
# Delete by URL
confluence delete "https://your-domain.atlassian.net/wiki/viewpage.action?pageId=123456789"
# Skip confirmation (useful for scripts)
confluence delete 123456789 --yesEdit Workflow
The edit and update commands work together to create a seamless editing workflow.
# 1. Export page content to a file (in Confluence storage format)
confluence edit 123456789 --output ./page-to-edit.xml
# 2. Edit the file with your preferred editor
vim ./page-to-edit.xml
# 3. Update the page with your changes
confluence update 123456789 --file ./page-to-edit.xml --format storageProfile Management
# List all profiles and see which is active
confluence profile list
# Switch the active profile
confluence profile use staging
# Add a new profile interactively
confluence profile add staging
# Add a new profile non-interactively
confluence profile add staging --domain "staging.example.com" --auth-type bearer --token "xyz"
# Add a read-only profile (blocks all write operations)
confluence profile add agent --domain "company.atlassian.net" --auth-type basic --email "[email protected]" --token "xyz" --read-only
# Remove a profile
confluence profile remove staging
# Use a specific profile for a single command
confluence --profile staging spacesRead-Only Mode
Read-only mode blocks all write operations at the CLI level, making it safe to hand the tool to AI agents (Claude Code, Copilot, etc.) without risking accidental edits.
Enable via profile:
# During init
confluence init --read-only
# When adding a profile
confluence profile add agent --domain "company.atlassian.net" --token "xyz" --read-onlyEnable via environment variable:
export CONFLUENCE_READ_ONLY=true # overrides profile settingWhen read-only mode is active, any write command (create, create-child, update, delete, move, edit, comment, attachment-upload, attachment-delete, property-set, property-delete, comment-delete, copy-tree) exits with code 1 and prints an error message.
confluence profile list shows a [read-only] badge next to protected profiles.
View Usage Statistics
confluence statsCommands
Commands are organized as grouped subcommands (<resource> <action>) with flat aliases for backward compatibility.
| Command | Description | Options |
|---|---|---|
| init | Initialize CLI configuration | --read-only |
| doctor | Validate configuration, auth, and connectivity | --space <key>, --json |
| read <pageId_or_url> | Read page content | --format <html\|text\|storage\|markdown> |
| info <pageId_or_url> | Get page information | --format <text\|json> |
| search <query> | Search for pages | --limit <number>, --space <key>, --type <page\|blog>, --cql, --json |
| space list | List all available spaces | --json |
| space get <key> | Get space details | --json |
| spaces | Alias for space list | |
| find <title> | Find a page by its title | --space <spaceKey> |
| page list <space> | List pages in a space | --json |
| page get <id> | Get page details | --json |
| page tree <id> | Get page hierarchy | |
| children <pageId> | List child pages of a page | --recursive, --max-depth <number>, --format <list\|tree\|json>, --show-url, --show-id |
| create <title> <spaceKey> | Create a new page | --content <string>, --file <path>, --format <storage\|html\|markdown>|
| create-child <title> <parentId> | Create a child page | --content <string>, --file <path>, --format <storage\|html\|markdown> |
| copy-tree <sourcePageId> <targetParentId> [newTitle] | Copy page tree with all children | --max-depth <number>, --exclude <patterns>, --delay-ms <ms>, --copy-suffix <text>, --dry-run, --fail-on-error, --quiet |
| update <pageId> | Update a page's title or content | --title <string>, --content <string>, --file <path>, --format <storage\|html\|markdown> |
| move <pageId_or_url> <newParentId_or_url> | Move a page to a new parent location | --title <string> |
| delete <pageId_or_url> | Delete a page by ID or URL | --yes |
| edit <pageId> | Export page content for editing | --output <file> |
| blog list <space> | List blog posts in a space | --limit <number>, --json |
| blog get <id> | Get blog post details | --json |
| blog read <id> | Read blog post body content | --format <storage\|html\|text\|markdown> |
| blog create <title> <space> | Create a blog post | --content <string>, --file <path>, --format <storage\|html\|markdown> |
| blog update <id> | Update a blog post | --title <string>, --content <string>, --file <path>, --format <storage\|html\|markdown> |
| blog delete <id> | Delete a blog post | --yes |
| label list <pageId> | List labels on a page | --json |
| label add <pageId> <name> | Add a label to a page | |
| label delete <pageId> <name> | Delete a label from a page | |
| attachments <pageId_or_url> | List or download attachments for a page | --limit <number>, --pattern <glob>, --download, --dest <directory> |
| attachment-upload <pageId_or_url> | Upload attachments to a page | --file <path>, --comment <text>, --replace, --minor-edit |
| attachment-delete <pageId_or_url> <attachmentId> | Delete an attachment from a page | --yes |
| comment list <pageId> | List comments for a page | --format <text\|markdown\|json>, --limit <number>, --start <number>, --location <inline\|footer\|resolved>, --depth <root\|all>, --all |
| comment add <pageId> | Create a comment on a page | --content <string>, --file <path>, --format <storage\|html\|markdown>, --parent <commentId>, --location <inline\|footer>, --inline-selection <text>, --inline-original-selection <text>, --inline-marker-ref <ref>, --inline-properties <json> |
| comment delete <commentId> | Delete a comment by ID | --yes |
| comments <pageId> | Alias for comment list | (same options) |
| comment-delete <commentId> | Alias for comment delete | --yes |
| attachment list <pageId> | List attachments | --limit, --pattern, --json |
| attachment upload <pageId> | Upload attachments | --file, --comment, --replace |
| attachment download <pageId> | Download all attachments | --dest |
| attachment delete <pageId> <attId> | Delete an attachment | --yes |
| property list <pageId> | List all content properties | --format <text\|json>, --limit <number>, --start <number>, --all |
| property get <pageId> <key> | Get a content property by key | --format <text\|json> |
| property set <pageId> <key> | Set a content property (create or update) | --value <json>, --file <path>, --format <text\|json> |
| property delete <pageId> <key> | Delete a content property by key | --yes |
| property-list <pageId> | Alias for property list | (same options) |
| property-get <pageId> <key> | Alias for property get | (same options) |
| property-set <pageId> <key> | Alias for property set | (same options) |
| property-delete <pageId> <key> | Alias for property delete | --yes |
| export <pageId_or_url> | Export a page to a directory with its attachments | --format <html\|text\|markdown>, --dest <directory>, --file <filename>, --attachments-dir <name>, --pattern <glob>, --referenced-only, --skip-attachments |
| profile list | List all configuration profiles | |
| profile use <name> | Set the active configuration profile | |
| profile add <name> | Add a new configuration profile | -d, --domain, -p, --api-path, -a, --auth-type, -e, --email, -t, --token, --protocol, --read-only |
| profile remove <name> | Remove a configuration profile | |
| convert | Convert between content formats locally (no server required) | --input-file <path>, --output-file <path>, --input-format <markdown\|storage\|html>, --output-format <markdown\|storage\|html\|text> |
| stats | View your usage statistics | |
Global option: --profile <name> — Use a specific profile for any command (overrides CONFLUENCE_PROFILE env var and active profile).
Examples
# Setup
confluence init
# Verify configuration
confluence doctor
# Read a page as text
confluence read 123456789
# Read a page as HTML
confluence read 123456789 --format html
# Get page details
confluence info 123456789
# Search with limit and space filter
confluence search "API documentation" --limit 3 --space MYSPACE
# Search for blog posts only
confluence search "release" --type blog --json
# List all spaces
confluence space list
# Get space details
confluence space get ENG
# Move a page to a new parent
confluence move 123456789 987654321
# Move and rename
confluence move 123456789 987654321 --title "New Title"
# Upload and delete an attachment
confluence attachment-upload 123456789 --file ./report.pdf
confluence attachment-delete 123456789 998877 --yes
# Blog posts
confluence blog list MYSPACE
confluence blog create "Release Notes" MYSPACE --content "# v2.0" --format markdown
confluence blog delete 123456789 --yes
# Labels
confluence label list 123456789
confluence label add 123456789 documentation
confluence label remove 123456789 outdated
# View usage statistics
confluence stats
# Profile management
confluence profile list
confluence profile use staging
confluence --profile staging space list
# Convert markdown to Confluence storage format (no server required)
confluence convert --input-file doc.md --input-format markdown --output-format storage
# Pipe conversion via stdin/stdout
echo "# Hello" | confluence convert --input-format markdown --output-format storage
# Convert storage format back to markdown
confluence convert -i page.xml -o page.md --input-format storage --output-format markdownDevelopment
# Clone the repository
git clone https://github.com/S2P2/confluence-cli.git
cd confluence-cli
# Install dependencies
bun install
# Run locally (TypeScript, no build step)
bun dev -- --help
bun dev read 123456789
# Build
bun run build
# Run tests
bun test
# Lint code
bun run lint
# Type check
bun run typecheckKnown Limitations
- Attachment downloads with service accounts: Atlassian Cloud's attachment download endpoints (
/wiki/download/attachments/...and/wiki/rest/api/content/{id}/download) return 401 for service account and scoped API tokens, regardless of granted scopes. The CLI displays resolved download URLs instead. Use a personal API token (Basic auth) to enable direct file downloads. (Atlassian Developer Community thread)
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Roadmap
- [x] Create and update pages
- [x] Page attachments management (list, download, upload, delete)
- [x] Comments (list, create, delete)
- [x] Blog posts (list, get, create, update, delete)
- [x] Labels (list, add, remove)
- [x] Diagnostics (
doctorcommand) - [x] TypeScript rewrite with strict mode
- [x] Grouped commands (
space get,blog list,label add, etc.) - [ ] Page templates
- [ ] Bulk operations
- [ ] Reviews
- [ ] Integration with other Atlassian tools (Jira)
Support & Feedback
💬 We'd love to hear from you!
Your feedback helps make confluence-cli better for everyone. Here's how you can share your thoughts:
🐛 Found a bug?
- Check the Issues page
- Create a new bug report
💡 Have a feature idea?
- Create a feature request
- Join our Discussions to chat with the community
📝 General feedback?
- Share your experience with a feedback issue
- Rate us on NPM
- Star the repo if you find it useful! ⭐
🤝 Want to contribute?
Check out our Contributing Guide - all contributions are welcome!
📈 Usage Analytics
confluence-cli tracks command usage statistics locally on your machine (~/.confluence-cli/stats.json). No data is sent to any external server. This includes:
- Command usage counts (success/error)
You can view your stats with confluence stats, or disable tracking by setting: export CONFLUENCE_CLI_ANALYTICS=false
Acknowledgments
This project is a fork of pchuri/confluence-cli, rewritten from JavaScript to TypeScript with additional features. The original JS CLI by @pchuri provides the core page, attachment, comment, and property operations.
New features (blog posts, labels, diagnostics, grouped commands) were inspired by rvben/confluence-cli (Rust). The grouped command convention (space get, blog list, label add, etc.) follows the Rust CLI's design.
Made with ❤️ for the Confluence community
