confluence-cli

pchuriMIT活跃维护

用命令行直接操作 Atlassian Confluence 的 CLI 工具,支持创建、更新、搜索页面等操作,方便把文档维护和自动化流程接进脚本里。

A powerful command-line interface for Atlassian Confluence

v2.31.0发布于 2026-10-31 05:16 UTC325star +1 / 7 天72fork同步于 2026-11-10 06:04 UTC

怎么上手

从 README 代码块原样提取,可能是其中一种安装方式
brew install pchuri/tap/confluence-cli
brew trust pchuri/tap
npm install -g confluence-cli
硬件要求

README 没有说明硬件要求。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

这个项目的说明还在生成中,先参考下面「最近发版」和 README。

最近发版

5 个版本v2.31.0
  1. v2.31.0最新正式版2026-10-31 · 2026-10-31 05:16 UTC

    2.31.0 (2026-10-31)

    Features

    • support Server/Data Center tiny links (#284) (7ffb799)
  2. v2.30.62026-10-31 · 2026-10-31 05:07 UTC
    查看更新说明

    2.30.6 (2026-10-31)

    Bug Fixes

    • deps: bump follow-redirects to 1.16.2 for GHSA-mrwp-f3q8-3g9p (#294) (6a63b93)
  3. v2.30.52026-10-28 · 2026-10-28 13:55 UTC
    查看更新说明

    2.30.5 (2026-10-28)

    Bug Fixes

    • only resolve tiny links on the configured origin (#288) (22e4780)
  4. v2.30.42026-10-21 · 2026-10-21 09:09 UTC
    查看更新说明

    2.30.4 (2026-10-21)

    Bug Fixes

    • deps: bump follow-redirects to 1.16.1 (df0ea25)
  5. v2.30.32026-10-17 · 2026-10-17 12:11 UTC
    查看更新说明

    2.30.3 (2026-10-17)

    Bug Fixes

    • validate comment deletion and follow version pagination (b34c20d)

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Confluence CLI

    npm downloads

    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, HTML, storage, or Markdown format
    • 🔍 Search - Find pages using Confluence's powerful search
    • ℹ️ Page info - Get detailed information about pages
    • 🏠 List spaces - View available Confluence spaces
    • ✏️ 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
    • 🏷️ Properties - List, get, set, and delete content properties (key-value metadata)
    • 💬 Comments - List, create, and delete page comments (footer or inline)
    • 📦 Export - Save a page and its attachments to a local folder, or a whole page tree/space with --recursive
    • 🛠️ 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
    • 🌐 Raw API requests - Make arbitrary authenticated requests to any Confluence endpoint (like gh api)
    • 🔄 Format conversion - Convert between Markdown, HTML, Storage, and text formats locally (no server required)
    • 🔧 Easy setup - Simple configuration with environment variables or interactive setup

    Installation

    Homebrew (macOS/Linux)

    brew install pchuri/tap/confluence-cli
    

    Homebrew 5.1.15+ warns that third-party taps are "not trusted". To trust the tap and silence the warning (required in a future Homebrew release):

    brew trust pchuri/tap
    

    npm

    npm install -g confluence-cli
    

    Or run directly with npx:

    npx confluence-cli
    

    Note: npm does not automatically install the optional typebox dependency. Loading the bundled Pi extension from an npm-installed copy requires installing typebox alongside confluence-cli; the documented local-checkout npm ci already includes it.

    Pi Coding Agent: local package with protected writes

    Install this local checkout into Pi without globally installing confluence. Install the clone's dependencies first because Pi does not install dependencies for local-path packages:

    cd /absolute/path/to/confluence-cli
    npm ci
    pi install /absolute/path/to/confluence-cli
    

    For a Server/Data Center instance at confluence.example.com, start Pi from a shell configured like this when protected writes are intended:

    export CONFLUENCE_DOMAIN=confluence.example.com
    export CONFLUENCE_API_PATH=/rest/api
    export CONFLUENCE_AUTH_TYPE=bearer
    export CONFLUENCE_API_TOKEN='<personal-access-token>'
    export CONFLUENCE_READ_ONLY=false
    export CONFLUENCE_PI_WRITES=true
    export CONFLUENCE_PI_WRITE_SPACES='SAFE1,SAFE2'
    pi
    

    The package does not persist these values in Pi settings or session files. Changing registration variables (CONFLUENCE_PI_WRITES or CONFLUENCE_PI_WRITE_SPACES) after Pi starts requires /reload so the extension can re-register the correct tool set. Leaving writes disabled exposes read tools only.

    Write tool registration depends only on CONFLUENCE_PI_WRITES=true plus a valid non-empty CONFLUENCE_PI_WRITE_SPACES allowlist. CONFLUENCE_READ_ONLY=true does not hide registered write tools; it blocks every write execution even if those tools remain visible.

    Pi read tools are: confluence_read, confluence_search, confluence_info, confluence_spaces, confluence_children, confluence_export, confluence_convert, confluence_find, confluence_versions, confluence_comments, confluence_attachments, confluence_property_list, and confluence_property_get.

    When CONFLUENCE_PI_WRITES=true and CONFLUENCE_PI_WRITE_SPACES is a non-empty comma-separated allowlist without wildcards, Pi also registers these protected mutation tools: confluence_create, confluence_create_child, confluence_update, confluence_move, confluence_delete, confluence_copy_tree_preview, confluence_copy_tree, confluence_comment_create, confluence_comment_delete, confluence_property_set, confluence_property_delete, confluence_attachment_upload, confluence_attachment_delete, confluence_version_delete, confluence_versions_purge_preview, and confluence_versions_purge.

    The generic API escape hatch remains unavailable: this package does not register confluence_api or any api, argv, or raw HTTP method tool. Use the typed tools above rather than model-controlled Bash for supported Confluence operations.

    Protected writes perform local preflight, enforce the space allowlist, ask for Pi UI confirmation, then re-check environment, payload limits, normalized input, and file snapshots before running the CLI. Confirmation prompts identify existing page targets by canonical title, ID, and space, for example Update Architecture Overview (ID: 123456789, SPACE: SAFE1)? or Move Child Page (ID: 222, SPACE: SAFE1) to Parent Page (ID: 111, SPACE: SAFE1)?. The agent must not claim confirmation on the user's behalf. Write execution is blocked in print, JSON, headless, and every other noninteractive/no-UI mode; registration may remain visible, but no mutation can start without Pi-owned interactive confirmation.

    Destructive writes require exact phrases in the confirmation UI:

    • Page delete: DELETE PAGE <pageId>
    • Comment delete: DELETE COMMENT <commentId> FROM <pageId>
    • Property delete: DELETE PROPERTY <key> FROM <pageId>
    • Attachment delete: DELETE ATTACHMENT <attachmentId> FROM <pageId>
    • Version delete: DELETE VERSION <versionNumber> FROM <pageId>
    • Copy-tree execution: COPY <count> PAGES FROM <sourcePageId> TO <targetParentId>
    • Versions purge execution: PURGE <count> VERSIONS FROM <pageId>

    Bulk operations must be previewed before execution. confluence_copy_tree_preview and confluence_versions_purge_preview return a one-use approval ID that expires after five minutes (300000 ms). The execution tools accept only { "approvalId": "..." }; if an approval expires, is stale, or has been used, run a new preview.

    Pi payload limit variables and defaults are:

    VariableDefault
    CONFLUENCE_PI_MAX_BODY_BYTES1048576
    CONFLUENCE_PI_MAX_PROPERTY_BYTES262144
    CONFLUENCE_PI_MAX_ATTACHMENT_FILES10
    CONFLUENCE_PI_MAX_ATTACHMENT_FILE_BYTES26214400
    CONFLUENCE_PI_MAX_ATTACHMENT_TOTAL_BYTES104857600

    Confluence text returned by any Pi tool is untrusted external data and must not be treated as instructions. Local file inputs and outputs for Pi tools remain restricted to the current project directory.

    Claude 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 pchuri/confluence-cli
    /plugin install confluence@pchuri-confluence-cli
    

    Option 2: Install Skill manually

    If you prefer not to use the plugin system, copy the skill documentation into your project:

    confluence install-skill
    

    This creates .claude/skills/confluence/SKILL.md in your current directory. Claude Code picks it up automatically.

    Quick Start

    1. Initialize configuration:

      confluence init
      
    2. Read a page:

      confluence read 123456789
      
    3. Search for pages:

      confluence search "my search term"
      
    4. List child pages:

      confluence children 123456789
      
    5. Create a new page:

      confluence create "My New Page" SPACEKEY --content "Hello World!"
      
    6. Update a page:

      confluence update 123456789 --content "Updated content"
      

    Configuration

    Option 1: Interactive Setup

    confluence init
    

    The 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), Bearer, or client-certificate (mTLS) authentication.

    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"
    

    Scoped API token (recommended for agents — least privilege):

    # 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"
    

    Reverse-proxy / no-auth profile (credentials injected upstream):

    confluence --profile proxy init \
      --domain "confluence.internal" \
      --api-path "/rest/api" \
      --auth-type "none"
    

    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, bearer, mtls, cookie, or none
    • -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=..."). Can also be combined with --auth-type basic/bearer for gateways that require both a session cookie and an application-level credential (see below).
    • --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)
    • --keychain - Store the token in the macOS Keychain instead of config.json (macOS only, see Option 5)
    • --allow-insecure-http - Allow --protocol http to actually use HTTP for this profile (see HTTP transport below). Without it, http silently falls back to HTTPS.

    ⚠️ Security note: While flags work, storing tokens in shell history is risky. Prefer environment variables (Option 3) for production environments, or the macOS Keychain (Option 5) for a workstation.

    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 instances
    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"  # optional
    

    Cookie 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..."
    

    Reverse-proxy / no-auth environment variables:

    export CONFLUENCE_DOMAIN="confluence.internal"
    export CONFLUENCE_API_PATH="/rest/api"
    export CONFLUENCE_AUTH_TYPE="none"
    

    Scoped API token (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="basic"
    export CONFLUENCE_EMAIL="[email protected]"
    export CONFLUENCE_API_TOKEN="your-scoped-token"
    

    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.

    Option 4: .netrc file

    To keep your API token out of config.json on any platform, store it in a standard .netrc file (the same mechanism used by curl and Git). Configure a profile as usual but omit the token, then add an entry to your ~/.netrc:

    machine your-domain.atlassian.net
      login [email protected]
      password your-api-token
    
    • The machine must match the profile's domain, and login must match the profile's email (basic auth). For bearer auth (no email), only the machine is matched.
    • The token is resolved with this precedence: environment variable / --token → profile token in config.json → macOS Keychain → .netrc. A token from a higher-priority source wins.
    • .netrc supplies the token for basic and bearer auth only (not mtls, cookie, or none).
    • The file location is ~/.netrc (~/_netrc on Windows), or the path in the NETRC environment variable if set.
    • Note that .netrc is still plaintext on disk. On macOS, prefer the Keychain (Option 5).

    Option 5: macOS Keychain

    On macOS you can keep the API token in the login Keychain instead of config.json. Pass --keychain to confluence init (or answer yes to the Keychain prompt in interactive mode):

    confluence init \
      --domain "your-domain.atlassian.net" \
      --auth-type basic \
      --email "[email protected]" \
      --token "your-api-token" \
      --keychain
    

    The profile is written without a token field, and every command reads the token from the Keychain instead.

    • Items are generic passwords named confluence-cli:<host>; the account is your email for basic auth or the literal bearer for bearer auth. You can inspect them in Keychain Access.app or with security find-generic-password -s confluence-cli:<host> -a <account>.
    • The CLI talks to the Keychain through the built-in /usr/bin/security tool (the same approach as jira-cli), so there is no native dependency. The token is passed to security -i on stdin, never on the command line.
    • Values are stored as b64: + base64 so that non-ASCII tokens round-trip. Entries added by hand with a plain value are read as-is and must be printable ASCII (otherwise security prints them as hex). Profiles on the same host with the same auth type share one item.
    • Re-running confluence init --keychain replaces both the profile and the Keychain item. Changing the host or email creates a new item and leaves the old one in place; remove items with security delete-generic-password -s confluence-cli:<host> -a <account>.
    • Set CONFLUENCE_KEYCHAIN=off to skip Keychain lookups (for example on a headless Mac where the login Keychain is locked and an access prompt would block). Lookups time out after 30 seconds and fall back to .netrc.
    • Not available on Linux or Windows; --keychain is rejected there and lookups are skipped.

    Config file location:

    confluence-cli supports the XDG Base Directory Specification. The config directory is resolved in this order:

    1. CONFLUENCE_CONFIG_DIR env var — explicit override (e.g., /custom/path)
    2. Legacy ~/.confluence-cli/ — if it already exists (backwards compatibility)
    3. $XDG_CONFIG_HOME/confluence-cli/ — defaults to ~/.config/confluence-cli/

    New installations go to ~/.config/confluence-cli/ by default. Existing users at ~/.confluence-cli/ are unaffected — the CLI continues to use the legacy location until you move it. To migrate, simply move the directory:

    mkdir -p ~/.config/confluence-cli
    mv ~/.confluence-cli/* ~/.config/confluence-cli/
    rmdir ~/.confluence-cli
    

    The stats file (stats.json) follows the same resolution and lives alongside config.json in the same directory.

    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 identify it as a Server/Data Center instance and use standard links instead of Cloud smart links. Set CONFLUENCE_FORCE_CLOUD=true to override the automatic detection:

    export CONFLUENCE_FORCE_CLOUD=true
    

    Or add "forceCloud": true to your profile in the config file (see Config file location):

    {
      "profiles": {
        "default": {
          "domain": "wiki.example.org",
          "forceCloud": true
        }
      }
    }
    

    HTTP transport (allowInsecureHttp):

    HTTPS is used by default even if a profile or CONFLUENCE_PROTOCOL requests http — connecting over plain HTTP sends your credentials (basic auth header, bearer token, cookie) in plaintext, including through transparent corporate proxies. Setting protocol: "http" without an explicit opt-in prints a warning and silently falls back to HTTPS.

    If you genuinely need HTTP — for example a local reverse-authentication proxy on 127.0.0.1 or an internal network you trust — opt in explicitly via any of:

    # 1. CLI flag on init / profile add
    confluence init --domain "127.0.0.1:8080" --protocol http --allow-insecure-http ...
    
    # 2. Environment variable (overrides the profile's allowInsecureHttp setting)
    export CONFLUENCE_ALLOW_INSECURE_HTTP=true
    

    Or set "allowInsecureHttp": true directly in the profile:

    {
      "profiles": {
        "local-proxy": {
          "domain": "127.0.0.1:8080",
          "protocol": "http",
          "allowInsecureHttp": true
        }
      }
    }
    

    Link rendering (linkStyle):

    External links use Cloud smart links (<a data-card-appearance="inline">) on Cloud and standard <a href> tags on Server/Data Center and local conversions. Some Cloud instances — particularly custom-domain Cloud setups — fail to render smart links and show "Cannot handle: DefaultLink" errors instead. If you hit this, set linkStyle to plain:

    export CONFLUENCE_LINK_STYLE=plain
    

    Or per-profile:

    {
      "profiles": {
        "default": {
          "domain": "wiki.example.org",
          "forceCloud": true,
          "linkStyle": "plain"
        }
      }
    }
    

    Valid values: smart (Cloud smart links), plain (standard <a href>), auto (smart links for links into your own Confluence site, plain links for everything else), and wiki (legacy ac:link + ri:url output for explicit backward compatibility). When unset, the CLI picks smart for Cloud and plain for Server/Data Center and local conversions. New configurations should not use wiki for external links.

    A Cloud smart link is rendered from the target page's own title and discards the link text you wrote, which suits links to other Confluence pages but not links to external sites. auto gives each link the right treatment:

    See [ACME](https://example.atlassian.net/wiki/spaces/DEVOPS/pages/1346144034/acme)
    and [Let's Encrypt FAQ](https://letsencrypt.org/docs/faq/).
    

    becomes a smart link for ACME and a plain <a href> that keeps the text Let's Encrypt FAQ. A link counts as internal when its parsed origin matches siteUrl (or the configured domain when unset) and its path is inside the site's context path (/wiki on Cloud), so look-alike hosts such as example.atlassian.net.evil.test stay plain. Relative links are rendered plain, and so is every link when no site is configured (for example in library use of the converter without buildUrl). Only the written storage differs: read --format markdown returns the same [text](https://github.com/pchuri/confluence-cli/blob/HEAD/href) under every style.

    Smart links are a Cloud feature, so on Server/Data Center auto would emit smart-link markup for internal links that those sites do not render; keep plain there. With a scoped API token the CLI talks to the api.atlassian.com gateway. Set your actual Confluence site URL separately to enable internal link detection:

    export CONFLUENCE_SITE_URL=https://example.atlassian.net
    export CONFLUENCE_LINK_STYLE=auto
    

    Alternatively, save "siteUrl": "https://example.atlassian.net" in the profile, or pass --site-url https://example.atlassian.net to confluence init or confluence profile add <name>. Use an absolute HTTP(S) URL without credentials, query, or fragment; a /wiki context path and trailing slash are supported. When loading a profile, a nonempty CONFLUENCE_SITE_URL overrides its siteUrl; an empty value uses the saved setting. This setting only supplies the web URL for conversion and internal link detection; API requests and authentication still use domain and apiPath. When unset, detection uses the API domain as before, so scoped gateway profiles render site links plain under auto.

    PlantUML macro format (plantumlFormat):

    ```plantuml fences become the plain plantuml macro by default. Sites running the PlantUML Diagrams for Confluence app need the plantumlcloud macro (URI-encoded, deflated and base64-encoded data parameter) — select it with CONFLUENCE_PLANTUML_FORMAT=plantumlcloud, the profile field "plantumlFormat": "plantumlcloud", or --plantuml-format plantumlcloud on convert, create, create-child and update:

    export CONFLUENCE_PLANTUML_FORMAT=plantumlcloud
    confluence convert --input-format markdown --output-format storage --plantuml-format plantumlcloud -i page.md
    

    Valid values: plantuml (default — <ac:plain-text-body> CDATA) and plantumlcloud (compressed data parameter). Flag > environment variable > profile; convert runs locally without loading a profile, so the profile field only applies to create, create-child and update. Values are case-insensitive. See Programmatically adding PlantUML diagrams.

    Note: plantumlcloud renders from <filename>.svg / .png attachments (plantuml-diagram-1.svg, … in document order) produced by a PlantUML server you operate. This CLI emits the macro only; upload those attachments separately. Both formats read back as the same ```plantuml fence.

    Read-only mode (recommended for AI agents):

    export CONFLUENCE_READ_ONLY=true
    

    When 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:

    1. Go to Atlassian Account Settings
    2. Click "Create API token"
    3. Give it a label (e.g., "confluence-cli")
    4. Copy the generated token

    Atlassian Cloud — Scoped API Token (recommended for agents and automation):

    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.

    1. Create a scoped token in your Atlassian Admin settings
    2. Find your Cloud ID by visiting https://<your-site>.atlassian.net/_edge/tenant_info
    3. Configure with:
      • Domain: api.atlassian.com
      • API path: /ex/confluence/<your-cloud-id>/wiki/rest/api
      • Auth type: basic (email + scoped token)

    Required scopes for scoped API tokens:

    When creating a scoped token, select the following classic scopes based on your needs:

    ScopeRequired for
    read:confluence-content.allReading pages and blog posts (read, info)
    read:confluence-content.summaryReading content summaries and metadata (read, info)
    read:confluence-space.summaryListing spaces (spaces)
    search:confluenceSearching content (search)
    readonly:content.attachment:confluenceDownloading attachments (attachments --download)
    write:confluence-contentCreating and updating pages (create, update)
    write:confluence-fileUploading attachments (attachments --upload)
    write:confluence-spaceManaging spaces

    For read-only usage, select at minimum the classic scopes read:confluence-content.all, read:confluence-content.summary, read:confluence-space.summary, and search:confluence. Listing folders with children --type folders/all additionally requires the granular scope read:hierarchical-content: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.

    Reverse-proxy injected authentication: For deployments where a local reverse proxy injects credentials on the wire (e.g. SPNEGO/Kerberos, mTLS terminated at the proxy edge, or header injection), set authType=none. In this mode the CLI sends no Authorization or Cookie header — authentication is entirely the proxy's responsibility. Point CONFLUENCE_DOMAIN at the proxy and ensure no credentials are configured on the CLI side.

    Combining a gateway cookie with Bearer/Basic auth: Some corporate reverse-proxy/SSO gateways (e.g. F5 BIG-IP APM) terminate the connection with their own access-policy session cookie and still forward the request to Confluence, which then requires its own application-level credential (a Personal Access Token or Basic auth) on top. Neither authType=cookie (sends only Cookie) nor a plain authType=bearer/basic (sends only Authorization) covers this by itself. Set --cookie (or CONFLUENCE_COOKIE) alongside --auth-type bearer (or basic) and both headers are sent together:

    confluence --profile gateway init \
      --domain "confluence.company.com" \
      --api-path "/rest/api" \
      --auth-type "bearer" \
      --token "your-personal-access-token" \
      --cookie "MRHSession=abc123..."
    

    The gateway's session cookie is typically short-lived and will need refreshing periodically (re-extract it from your browser's dev tools and update the profile), independently of the token/password, which does not expire the same way.

    Usage

    JSON output (for scripting / jq)

    Pass the global --json flag to make a command emit raw JSON to stdout, so you can pipe it to tools like jq:

    confluence search "release notes" --json | jq '.results[].title'
    confluence spaces --json | jq -r '.spaces[].key'
    confluence info 123456789 --json | jq '.version'
    confluence create "Notes" ENG --content "hi" --json | jq -r '.id'   # capture the new page id
    

    --json works on read commands (info, search, spaces, find, children, versions, comments, attachments, property-list/-get/-set) and write commands (create, create-child, update, move, delete, copy-tree, comment, comment-resolve, comment-delete, property-delete, attachment-upload/-delete, version-delete, versions-purge). For destructive commands, --json requires --yes — it will not prompt interactively. Passing --json to a command that doesn't support it (e.g. init, convert, export, edit) is rejected with an error rather than silently ignored. Human-readable messages and warnings go to stderr, so stdout stays valid JSON.

    Deprecation: the per-command --format json form is deprecated in favor of the global --json flag. It still works but prints a warning to stderr and will be removed in a future major version.

    Structured errors

    When --json is active, command failures are machine-parseable: the command prints exactly one JSON object to stderr (stdout stays empty) and, except as noted below, exits with status 1. This lets scripts and agents branch on failures without scraping prose. The shape is:

    {
      "error": "Authentication failed (401 Unauthorized).",
      "code": "AUTH_FAILED",
      "status": 401,
      "details": { "message": "...", "status-code": 401 }
    }
    
    • error — the human-readable message.
    • code — a stable machine code, one of AUTH_FAILED, NOT_FOUND, VALIDATION, API_ERROR, NETWORK, UNKNOWN.
    • status — the HTTP status when the failure came from the server, otherwise null.
    • details — the raw API response body when present, otherwise null.
    ## Read errors from stderr and inspect the code
    confluence info 123 --json 2> >(jq -r '.code') 1>/dev/null
    

    Without --json, error output is unchanged (human-readable prose on stderr).

    Exceptions: api failures caused by missing jq or a failing --jq expression still use the structured stderr format but preserve exit status 2. Partial failures from copy-tree --fail-on-error and versions-purge emit their result JSON to stdout and signal the partial failure with exit status 1 instead of a structured error on stderr.

    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.

    Markdown reads resolve accessible Confluence page links, including links that omit a space key because they target the same space, to absolute URLs. Custom link text and inline formatting are preserved. Markdown exports use the same link resolution.

    Reading requires content with a storage body. Folders and other bodyless content return Page <id> has no readable body (it may be a folder or an unsupported content type).; use confluence info <id> to inspect their metadata.

    Get Page Information

    confluence info 123456789
    
    ## Emit machine-readable metadata
    confluence info 123456789 --json
    

    info can inspect folders and other bodyless content because it only reads metadata.

    Example 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
    
    ## Paginate results
    confluence search "search term" --limit 5 --start 5
    

    List 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
    
    ## Download matching attachments to a directory
    confluence attachments 123456789 --pattern "*.png" --download --dest ./downloads
    

    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 --replace
    

    --replace adds a new version to the attachment with the same filename, and uploads the file as a new attachment when the page has none. It works on Confluence Cloud and on Server/Data Center. Without --replace, Confluence rejects a filename that already exists on the page with HTTP 400.

    Delete Attachments

    ## Delete an attachment by ID
    confluence attachment-delete 123456789 998877
    
    ## Skip confirmation
    confluence attachment-delete 123456789 998877 --yes
    

    Content 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 --yes
    

    Content properties in Markdown front matter

    Markdown files can carry selected content properties (for example page width) in YAML front matter, so property changes can be reviewed in git and applied through the normal upload workflow.

    ---
    properties:
      content-appearance-published: full-width
    ---
    
    ## Page title
    
    ## Export a page with the listed properties as front matter
    ## (keys that do not exist on the page are omitted, in the order given)
    confluence read 123456789 --format markdown --front-matter content-appearance-published > page.md
    
    ## Upload the body and apply the front matter properties
    confluence update 123456789 --file ./page.md --format markdown --front-matter
    confluence create "Page title" MYSPACE --file ./page.md --format markdown --front-matter
    confluence create-child "Page title" 123456789 --file ./page.md --format markdown --front-matter
    
    • Front matter is only processed with --front-matter; without it, a leading --- stays part of the Markdown body (a thematic break), as before.
    • Only the properties map is used; other top-level keys are ignored (a warning is printed if the block has no properties map). Properties not listed are left untouched, and properties whose value already matches are not rewritten.
    • On Confluence Cloud the editor also keeps a content-appearance-draft property; set it alongside content-appearance-published so the width survives the next edit in the browser.
    • Front matter is parsed before anything is uploaded, so invalid YAML fails without changing the page.
    • The body is saved first, then the properties. If a property fails (for example because the token lacks the needed scope), the command exits non-zero and reports that the body was saved and which keys failed. With --json, the result on stdout includes properties: { applied, unchanged, failed } and stderr carries a PARTIAL_FAILURE error. Re-running update is safe: properties that already match are skipped. For create and create-child, the error names the update command that retries the properties on the new page (re-running create would try to make another page).
    • read → edit → update round trips keep the selected properties. Markdown output is stable and normalized, not byte-identical to the original file.

    Comments

    ## 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 123456789 --content "Looks good to me!"
    
    ## Create an inline comment (Confluence Cloud: no editor metadata needed)
    confluence comment 123456789 \
      --location inline \
      --content "Consider renaming this" \
      --inline-selection "foo"
    
    ## Highlight the second occurrence of the selected text instead of the first
    confluence comment 123456789 \
      --location inline \
      --content "Consider renaming this one too" \
      --inline-selection "foo" \
      --match-index 2
    
    ## Reply to a comment (inline or footer thread)
    confluence comment 123456789 --parent 998877 --content "Agree with this"
    
    ## Resolve or reopen an inline comment thread (Confluence Cloud)
    confluence comment-resolve 998877
    confluence comment-resolve 998877 --reopen
    
    ## Delete a comment
    confluence comment-delete 998877
    

    Inline comment creation (Confluence Cloud): comment --location inline --inline-selection "<text on the page>" creates a new inline thread through the v2 API, without any editor-generated highlight metadata. The CLI reads the page, counts how many times the selection text occurs, and fails with a clear error if the text is not on the page. When the text occurs more than once, --match-index <n> picks which occurrence to highlight (1-based: 1 is the first, the default). On Server/Data Center — and when --inline-properties, --inline-original-selection, or --inline-marker-ref is supplied — creation still goes through the v1 POST /content API, which does require editor highlight metadata (matchIndex, lastFetchTime, serializedHighlights, plus the selection text); supply the full --inline-properties payload captured from the editor there, or it can fail with a 400. Footer comments are fully supported everywhere.

    Replies and resolution (Confluence Cloud): --parent <commentId> posts through the v2 comment API, which needs no highlight metadata, so replies to inline and footer threads both work. The reply goes to the same kind of thread as its parent (any --location or --inline-* option is ignored for replies), and the command fails before posting if the parent belongs to a different page. Replying does not change whether a thread is resolved. comment-resolve <commentId> resolves a top-level inline thread and --reopen reopens it; asking for the state the thread already has changes nothing, and a dangling thread (its highlighted text was removed) cannot be updated. Server/Data Center keeps the v1 reply behavior, and comment-resolve requires Cloud. API tokens with granular scopes need the v2 comment scopes (read:comment:confluence and write:comment:confluence) for replies and comment-resolve; a token with only the classic content scopes gets a 401/403 on a reply that used to work through v1. Comment IDs must be numeric.

    Export 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"
    
    ## Exclude matching attachments (comma-separated globs)
    confluence export 123456789 --exclude-attachments "*.mp4,*.mov"
    
    ## Exclusions are applied after --pattern or --referenced-only when combined
    
    ## Skip attachments if you only need the content file
    confluence export 123456789 --skip-attachments
    

    Export a Whole Page Tree (or Space)

    Add --recursive to export a page together with all of its descendants. Each page becomes a folder (named after the page title) containing page.md and its attachments/, nested to mirror the page hierarchy. Point it at a space's homepage to export the whole space:

    ## Export a page and all descendants
    confluence export 123456789 -r --dest ./my-space
    
    ## Preview which pages would be exported, without writing files
    confluence export 123456789 -r --dry-run
    
    ## Limit depth, skip pages by title glob, and slow down between requests
    confluence export 123456789 -r --max-depth 3 --exclude "Archive*,Draft*" --delay-ms 500
    
    ## Re-export over a previous run (replaces content, removes stale files)
    confluence export 123456789 -r --overwrite
    

    List Spaces

    ## Default: up to 500 spaces (paginated automatically across requests)
    confluence spaces
    
    ## Increase the cap when your tenant has more than 500 spaces
    confluence spaces --limit 2000
    
    ## Fetch every space, regardless of how many pages it takes
    confluence spaces --all
    

    List Children

    ## List direct child pages
    confluence children 123456789
    
    ## List descendant pages recursively
    confluence children 123456789 --recursive
    
    ## List child folders instead of pages (Confluence Cloud only)
    confluence children 123456789 --type folders
    
    ## List both pages and folders; each item shows its content type
    confluence children 123456789 --type all
    
    ## Display as tree structure
    confluence children 123456789 --recursive --format tree
    
    ## Show child IDs and available URLs
    confluence children 123456789 --show-id --show-url
    
    ## Limit page recursion depth
    confluence children 123456789 --recursive --max-depth 3
    
    ## Output as JSON for scripting
    confluence children 123456789 --recursive --json > children.json
    

    children --json returns structured metadata for each child, including id, title, type, status, spaceKey, parentId, version, and url. Recursive page entries also include depth, and when available, ancestors.

    Use --type to choose what is listed: pages (default, unchanged behavior), folders, or all. The type field on each item distinguishes page from folder; when folders can appear, the human-readable list marks every item with [page] or [folder], and tree output uses distinct page and folder icons. Folders are a Confluence Cloud concept; on Server/Data Center, --type folders/all prints a warning and skips folders instead of failing, while all still lists pages. When pages are included, --recursive lists their descendants as before, but folders remain limited to direct children of the requested page.

    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 MYTEAM
    

    Create 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 markdown
    
    ## Auto-detect: keeps storage XHTML as-is, converts plain text/Markdown
    confluence create "My New Page" SPACEKEY --content "**Hello** World!" --format auto
    

    For create, create-child, update, and comment, --format auto detects the content type: it preserves content that starts with markup such as <p>...</p> or <ac:structured-macro ...>, and converts plain text or Markdown to Confluence storage XHTML. This is useful for older Confluence Server/Data Center versions that reject bare text in a body.storage.value.

    Create 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 markdown
    

    Copy 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 --quiet
    

    Notes:

    • 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).
    • If the server answers 429 (for example a Data Center instance limited to a few requests per second), the CLI paces its requests: a positive Retry-After makes every request wait, and requests are spaced further apart until the server accepts them, then speeded up again. Traversals such as copy-tree, export and children --recursive therefore finish under a low shared limit instead of failing after a few retries, and a server that keeps refusing still fails after about as long as before. Without throttling nothing is slowed down. A 503 on a read is retried per request, as before.
    • Root title suffix defaults to (Copy); override with --copy-suffix. Child pages keep their original titles.
    • Use --fail-on-error to 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"
    

    Title-only updates reuse the target's existing storage body. Folders and other bodyless content cannot be updated this way and return Page <id> has no readable body (it may be a folder or an unsupported content type)..

    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 --yes
    

    Edit 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 storage
    

    Only content with a storage body can be exported for editing. Folders and other bodyless content return Page <id> has no readable body (it may be a folder or an unsupported content type)..

    Profile 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 spaces
    

    Read-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-only
    

    Enable via environment variable:

    export CONFLUENCE_READ_ONLY=true   # overrides profile setting
    

    When read-only mode is active, any write command (create, create-child, update, delete, move, edit, comment, comment-resolve, 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.

    Raw API Requests

    Make arbitrary authenticated requests to any Confluence REST endpoint, modeled after gh api. Useful for endpoints the CLI hasn't wrapped yet (labels, restrictions, groups, audit, v2 API, …) without falling back to curl.

    Endpoint resolution:

    • Relative path (no leading slash) → resolved against the configured apiPath (the default for most calls).
    • Absolute path (leading /) → bypasses apiPath; resolved against the host. On Confluence Cloud, apiPath is typically /wiki/rest/api, so absolute endpoints must include the /wiki prefix.
    • Full URL (https://…) → used as-is, but only when it is same-origin with the configured host. A full URL pointing at a different origin (or an http:// downgrade of an https host) is refused, so your credentials are never sent to an unexpected server.
    ## List labels on a page (relative — uses apiPath)
    confluence api content/123456789/label
    
    ## Same call written as an absolute path on Confluence Cloud
    confluence api /wiki/rest/api/content/123456789/label
    
    ## Add a label to a page (relative form)
    confluence api content/123456789/label --input - <<< '[{"name":"reviewed"}]'
    
    ## Remove a label from a page
    confluence api content/123456789/label/reviewed -X DELETE
    
    ## View page restrictions
    confluence api content/123456789/restriction
    
    ## List groups
    confluence api group
    
    ## Check long-running task status
    confluence api longtask/123
    
    ## Query the v2 API (absolute path required, since v2 lives outside apiPath)
    confluence api /wiki/api/v2/pages -f spaceKey=DEV -f limit=10 -X GET
    
    ## Filter response with jq
    confluence api group --jq '.results[].name'
    
    ## Include response status and headers
    confluence api audit -i
    
    ## Read request body from a file
    confluence api content/123456789/restriction --input ./restrictions.json
    
    ## Suppress success output (useful in scripts that only care about exit code)
    confluence api content/123456789/label --input - --silent <<< '[{"name":"approved"}]'
    

    Read-only profiles block write methods (POST, PUT, PATCH, DELETE) while allowing GET and HEAD. --jq requires jq to be installed and available in PATH.

    View Usage Statistics

    confluence stats
    

    Commands

    CommandDescriptionOptions
    initInitialize CLI configuration--read-only, --keychain
    read <pageId_or_url>Read page content--format <html|text|storage|markdown>, --front-matter <keys>
    info <pageId_or_url>Get page information--json
    search <query>Search for pages--json, --limit <number>, --start <number>
    spacesList available spaces--json, --limit <number>, --all
    find <title>Find a page by its title--space <spaceKey>, --json
    children <pageId>List child pages and folders of a page--recursive, --max-depth <number>, --type <pages|folders|all>, --format <list|tree>, --json, --show-url, --show-id
    create <title> <spaceKey>Create a new page or folder--content <string>, --file <path>, --format <auto|storage|html|markdown>, --type <page|folder>, --front-matter, --json
    create-child <title> <parentId>Create a child page or folder--content <string>, --file <path>, --format <auto|storage|html|markdown>, --type <page|folder>, --front-matter, --json
    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, --json
    update <pageId>Update a page's title or content--title <string>, --content <string>, --file <path>, --format <auto|storage|html|markdown>, --front-matter, --json
    move <pageId_or_url> <newParentId_or_url>Move a page to a new parent location--title <string>, --json
    delete <pageId_or_url>Delete a page by ID or URL--yes, --json
    versions <pageId_or_url>List historical versions of a page--json
    version-delete <pageId_or_url> <versionNumber>Delete a single non-current version of a page--yes, --json
    versions-purge <pageId_or_url>Delete every non-current historical version of a page--yes, --throttle <seconds>, --json
    edit <pageId>Export page content for editing--output <file>
    attachments <pageId_or_url>List or download attachments for a page--json, --limit <number>, --pattern <glob>, --download, --dest <directory>
    attachment-upload <pageId_or_url>Upload attachments to a page--file <path>, --comment <text>, --replace, --minor-edit, --json
    attachment-delete <pageId_or_url> <attachmentId>Delete an attachment from a page--yes, --json
    comments <pageId_or_url>List comments for a page--format <text|markdown>, --json, --limit <number>, --start <number>, --location <inline|footer|resolved>, --depth <root|all>, --all
    comment <pageId_or_url>Create a comment on a page--content <string>, --file <path>, --format <auto|storage|html|markdown>, --parent <commentId>, --location <inline|footer>, --inline-selection <text>, --inline-original-selection <text>, --inline-marker-ref <ref>, --inline-properties <json>, --match-index <n>, --json
    comment-resolve <commentId>Resolve (or reopen) an inline comment thread (Cloud)--reopen, --json
    comment-delete <commentId>Delete a comment by ID--yes, --json
    property-list <pageId_or_url>List all content properties for a page--json, --limit <number>, --start <number>, --all
    property-get <pageId_or_url> <key>Get a content property by key--json
    property-set <pageId_or_url> <key>Set a content property (create or update)--value <json>, --file <path>, --json
    property-delete <pageId_or_url> <key>Delete a content property by key--yes, --json
    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>, --exclude-attachments <patterns>, --referenced-only, --skip-attachments, -r, --recursive, --max-depth <depth>, --exclude <patterns>, --delay-ms <ms>, --dry-run, --overwrite
    profile listList 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, --allow-insecure-http, --read-only, --keychain
    profile remove <name>Remove a configuration profile
    api <endpoint>Make an authenticated API request (relative path uses apiPath; absolute path bypasses it; full URL must be same-origin)-X, --method <method>, -f, --field <key=value>, -H, --header <key:value>, --input <file>, --jq <expression>, -i, --include, --silent
    convertConvert between content formats locally (no server required)--input-file <path>, --output-file <path>, --input-format <markdown|storage|html>, --output-format <markdown|storage|html|text>
    statsView 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
    
    ## 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
    confluence search "API documentation" --limit 3
    
    ## List spaces
    confluence spaces
    
    ## 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
    
    ## Create a folder (no content body required)
    confluence create "Engineering Docs" MYSPACE --type folder
    confluence create-child "Sub-folder" 123456789 --type folder
    
    ## View usage statistics
    confluence sta