Metadata-Version: 2.4
Name: confluence-cli-rs
Version: 0.1.26
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Rust
Classifier: Topic :: Documentation
Classifier: Topic :: Utilities
License-File: LICENSE
Summary: Markdown-sync-first Confluence CLI in Rust
Keywords: confluence,cli,markdown,sync,atlassian
Home-Page: https://github.com/rvben/confluence-cli
License: MIT
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/rvben/confluence-cli/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/rvben/confluence-cli#readme
Project-URL: Homepage, https://github.com/rvben/confluence-cli
Project-URL: Repository, https://github.com/rvben/confluence-cli

# confluence-cli

[![codecov](https://codecov.io/gh/rvben/confluence-cli/graph/badge.svg)](https://codecov.io/gh/rvben/confluence-cli)

Markdown-sync-first Confluence CLI in Rust.

`confluence-cli` is built around a safe local workflow:

1. `pull` Confluence content into Markdown plus sidecar metadata.
2. `plan` changes against the pulled sidecar state without contacting Confluence.
3. `apply` only when the diff is correct; it rechecks remote versions before writing.

It also exposes direct page, blog, search, attachment, label, comment, and property commands for non-sync use cases.

## Status

Early release, but already live-verified against both Confluence Cloud and Confluence Data Center.

| Area | Cloud | Data Center | Notes |
| --- | --- | --- | --- |
| Auth, spaces, search, page/blog CRUD | Verified | Verified | Live e2e |
| Attachments, labels, properties, comments | Verified | Verified | Live e2e |
| `pull -> plan -> apply` sync flow | Verified | Verified | Includes drift refusal and noop checks |
| `doctor` environment/profile validation | Verified | Verified | Live checked |
| Markdown round-trip for common built-in macros | Verified | Verified | Unsupported cases preserve storage safely |

## Installation

From PyPI with `uv`:

```bash
uv tool install confluence-cli-rs
```

The PyPI distribution is named `confluence-cli-rs`; it installs the
`confluence` executable.

From crates.io:

```bash
cargo install confluence-cli
```

From Homebrew:

```bash
brew tap rvben/tap
brew install rvben/tap/confluence-cli
```

Prebuilt macOS and Linux archives for Intel and ARM are published on the [GitHub releases page](https://github.com/rvben/confluence-cli/releases).

## Quick Start

For guided setup, run `confluence auth login` (or `confluence init`) in a
terminal. The wizard opens Atlassian's token page when useful, discovers the
Cloud ID required by scoped tokens, hides credential entry, verifies access,
and stores the token in your operating-system keychain. Existing profiles are
offered as defaults. If no OS credential service is available, setup offers an
explicit protected-file fallback rather than silently weakening storage.

For Confluence Data Center, setup can create a dedicated PAT through the
official API using a one-time password or existing PAT; the bootstrap secret is
never saved. If automatic creation is unavailable, it opens
`https://<your-host>/plugins/personalaccesstokens/usertokens.action` (also
available under **Avatar → Settings → Personal access tokens**). Onboarding
never consumes accidental piped input as answers.

`init` is the short name for the guided `auth login` flow. Use
`auth login --profile NAME ...` for explicit scripted login, and use
`profile add --name NAME ...` as the explicit profile-management equivalent.

Cloud profile:

```bash
CONFLUENCE_API_TOKEN="$CONFLUENCE_API_TOKEN" confluence auth login \
  --profile cloud \
  --provider cloud \
  --domain your-site.atlassian.net \
  --auth-type basic \
  --username you@example.com \
  --non-interactive

confluence doctor --profile cloud --space SPACEKEY
```

Data Center profile:

```bash
printf '%s' "$CONFLUENCE_PAT" | confluence auth login \
  --profile dc \
  --provider data-center \
  --domain http://localhost:8090 \
  --auth-type bearer \
  --token-stdin \
  --non-interactive

confluence doctor --profile dc --space TEST
```

Environment-driven mode also works without a stored profile:

```bash
export CONFLUENCE_DOMAIN=https://your-site.atlassian.net
export CONFLUENCE_PROVIDER=cloud
export CONFLUENCE_AUTH_TYPE=basic
export CONFLUENCE_EMAIL=you@example.com
export CONFLUENCE_TOKEN="$CONFLUENCE_API_TOKEN"

confluence doctor --space SPACEKEY
```

Non-interactive login stores credentials in the OS keychain by default. For a
headless machine without a credential service, prefer environment-driven mode;
if persistent storage is necessary, explicitly accept the protected config-file
fallback with `--insecure-storage`. Existing inline-token profiles remain
readable and can be moved transactionally with `confluence auth migrate`.

## Markdown Sync Workflow

Pull a page tree:

```bash
confluence pull tree SPACE:ParentPage ./docs/parent-page
```

Pulls are staged beside the destination and installed as one snapshot. A pull
refuses to replace local Markdown changes or unmanaged files; inspect and apply
or preserve those files first. Use `--force` only when the remote snapshot
should replace the entire destination. Attachment names are confined to their
page's `attachments/` directory. Filtered `pull space --since ...` exports must
use a new or empty destination, because partial results cannot safely replace a
complete local snapshot.

Inspect the planned changes:

```bash
confluence plan ./docs/parent-page
```

`plan` validates the complete local tree and compares it with the sidecar state
captured by `pull`; it does not contact Confluence. `apply` validates every local
document and preflights every remote version before its first write. Versioned
updates still reject drift that occurs during the apply unless `--force` is
explicitly supplied. Partial remote mutations are reported in structured error
details so automation can reconcile them safely.

Apply the diff:

```bash
confluence apply ./docs/parent-page
```

Local content is stored as:

- `<slug>/index.md`
- `<slug>/.confluence.json`
- `<slug>/attachments/*`

The frontmatter carries editable metadata such as `title`, `type`, `labels`, `status`, and `properties`. `parent` is informational: move a page directory beneath its desired local parent to reparent it. The sidecar stores remote ids, versions, hashes, and attachment mappings used for safe sync and drift detection.

## `doctor`

Use `doctor` before a first sync, in CI, or when a profile behaves unexpectedly.

```bash
confluence doctor --profile cloud --space SPACEKEY --path ./docs/parent-page
```

It checks:

- config loading and profile resolution
- base URL and auth shape
- provider reachability
- optional space access
- optional local sync path planning

`doctor` exits non-zero on failures and supports `--json` for machine-readable checks.

## Commands

Top-level command groups:

- `auth login|status|logout|migrate`
- `profile add|list|use|remove`
- `space list|get`
- `search`
- `page list|get|tree|move|create|update|delete`
- `blog list|get|create|update|delete`
- `pull page|tree|space`
- `plan`
- `apply`
- `attachment list|download|upload|delete`
- `label list|add|remove`
- `comment list|add|update|delete`
- `property list|get|set|delete`
- `doctor`
- `completions`
- `schema`

All data commands accept the suite-wide `--output auto|text|json`, `--quiet`, and
`--no-color` flags. Auto output is readable text on a terminal and JSON when
piped; `--json` remains a hidden compatibility alias. Successful JSON-mode
commands always emit one JSON document. `completions` intentionally emits an
opaque shell script, while `schema` always emits JSON.

List commands consistently support `--limit`, `--offset`, and JSON-only
`--fields`. Search reports an exact `total` when Confluence supplies one and
`null` otherwise. Errors use the shared exit-code contract (input 2, auth 3,
not found 4, API/network 5, rate limit 6, conflict 7), and
`confluence schema --command 'page get'` returns one token-efficient command
contract. The response contract is versioned independently in the schema.

Where a command accepts `REFERENCE`, use a numeric content ID, a Confluence URL,
or `SPACE:Title`. Destructive operations require an interactive confirmation or
`--yes`; conditional overwrites additionally require `--force` or `--replace`.
For sensitive content, prefer `--body-file` or standard input over `--body`,
because command-line arguments can be visible to other local processes.

## Auth And Environment Overrides

Stored profiles live under the local config directory used by `directories::ProjectDirs`.

Supported environment overrides:

- `CONFLUENCE_PROFILE`
- `CONFLUENCE_DOMAIN`
- `CONFLUENCE_PROVIDER`
- `CONFLUENCE_API_PATH`
- `CONFLUENCE_AUTH_TYPE`
- `CONFLUENCE_EMAIL` or `CONFLUENCE_USERNAME`
- `CONFLUENCE_API_TOKEN`, `CONFLUENCE_TOKEN`, `CONFLUENCE_PASSWORD`, or `CONFLUENCE_BEARER_TOKEN`
- `CONFLUENCE_TOKEN_KIND` (`classic` or `scoped`)
- `CONFLUENCE_CLOUD_ID` (required for scoped Cloud tokens)
- `CONFLUENCE_READ_ONLY`

`CONFLUENCE_PROVIDER` must be `cloud` or `data-center`. `CONFLUENCE_AUTH_TYPE` must be `basic` or `bearer`.

## Shell Completions

```bash
confluence completions bash > /usr/local/etc/bash_completion.d/confluence
confluence completions zsh > ~/.zsh/completions/_confluence
confluence completions fish > ~/.config/fish/completions/confluence.fish
```

## Testing

`make test` runs unit tests and stateful process-level simulator tests. The simulator drives the compiled CLI through the same complete lifecycle for Cloud and Data Center: pages, blogs, hierarchy, labels, properties, comments, attachments, Markdown pull/plan/apply, macros, cleanup, and authentication failures. It binds only to localhost and never needs credentials.

Live provider checks remain separate:

- `e2e_cli_canary` is a small create/get/pull/plan/apply/delete smoke test.
- `e2e_cli_lifecycle` is the complete live provider suite.
- `.github/workflows/cloud-e2e.yml` runs the canary Monday through Saturday, the complete suite on Sunday, and either suite on demand through a protected GitHub Environment.

See [docs/testing.md](docs/testing.md) for the confidence model and Cloud automation setup.

## Local Data Center

The repo includes a local Confluence Data Center stack for integration testing.

```bash
make confluence-start
make confluence-wait
make test-e2e
```

The default e2e path targets the local `local-dc` profile and the `TEST` space.

Available helpers:

- `make confluence-backup`
- `make confluence-restore`
- `make confluence-reset`
- `make confluence-logs`

Backups are written to:

- `docker/backup/confluence-data.tar.gz`
- `docker/backup/postgres-data.tar.gz`

The first boot after `make confluence-restore` can take several minutes before HTTP responds.

To point the e2e suite at another instance:

```bash
CONFLUENCE_E2E_PROFILE=other-profile CONFLUENCE_E2E_SPACE=SPACE make test-e2e
```

Or run fully env-driven:

```bash
CONFLUENCE_E2E_PROFILE= \
CONFLUENCE_E2E_BASE_URL=http://localhost:8090 \
CONFLUENCE_E2E_TOKEN="$CONFLUENCE_PAT" \
CONFLUENCE_E2E_PROVIDER=data-center \
CONFLUENCE_E2E_SPACE=TEST \
make test-e2e
```

Env-driven Cloud tests also accept `CONFLUENCE_E2E_TOKEN_KIND` and, for scoped tokens, `CONFLUENCE_E2E_CLOUD_ID`.

## Release And CI

Local release gate:

```bash
make release-check
```

That runs formatting, clippy, tests, CLI smoke checks, and `cargo package`.

Local versioned releases use `vership`, matching the other CLI projects:

```bash
make release-patch
make release-minor
make release-major
```

`vership` uses `vership.toml` in this repo so `vership preflight` runs the stricter `make release-check` gate rather than the default Rust-only lint/test commands.

GitHub Actions is set up to:

- run CI on pushes and pull requests
- publish tagged releases to crates.io
- publish native macOS and Linux wheels to PyPI as `confluence-cli-rs`
- build tagged macOS and Linux release archives
- attach release archives and checksum files to GitHub releases
- update `rvben/tap` automatically on tagged releases when `HOMEBREW_TAP_TOKEN` is configured

## Markdown Fidelity

Remote canonical content stays in Confluence storage format. Markdown is the editable local representation.

The converter already handles a large set of common Confluence constructs directly, including:

- headings, lists, tables, code blocks, task lists, links, and attachments
- page links and typed page/user/space resource parameters
- layouts, panels, expand blocks, status, TOC-family macros, and search/navigation macros
- excerpt, excerpt-include, include-page, page-tree, page-tree-search, and page-index
- label/reporting/content-property/report-table/task-report families
- attachment preview and other common built-in macros

When a construct is unsupported or would be lossy, `confluence-cli` preserves the Confluence storage fragment instead of flattening the whole page.

## Known Limits

- Storage fidelity is strongest for supported built-in macros and generic resource-aware macro fallback. Unknown provider-specific macro behavior can still vary between Cloud and Data Center.
- Pull requests use the stateful simulator; live tenant checks run on the protected schedule and can also be dispatched manually.
- `apply` refuses remote version drift unless `--force` is used.

## License

MIT

## Releasing

Vership owns versioning, changelog generation, release commits, and tags. See
[the release runbook](docs/releases.md) for the verified workflow and recovery policy.

