Metadata-Version: 2.4
Name: confluence-cli-rs
Version: 0.1.27
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 |
| Proof Desk TUI browse and sync review | Shared verified APIs | Shared verified APIs | Deterministic wide, medium, compact, and no-color render tests |
| `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.

## Proof Desk TUI

Open the read-only interactive navigator on the first visible space, or choose a
space explicitly:

```bash
confluence tui
confluence tui --space DOCS
```

Add an existing pulled Markdown directory to start in the sync-review workspace:

```bash
confluence tui --space DOCS --path ./docs/parent-page
confluence tui --path ./docs/parent-page --delete-remote
```

Browse mode presents the page hierarchy, a readable Markdown proof, and an
outer margin for metadata, labels, attachments, comments, and content
properties. Review mode uses the same layout for the local sync plan and real
unified body diffs. It is intentionally local-only: it does not contact
Confluence to detect drift and never applies changes. `confluence apply` remains
the separate command that preflights remote versions before writing.
Remote attachment deletions are omitted by default; `--delete-remote` includes
them in the local Review plan without deleting anything.

Use arrow keys or `j`/`k` to move, `Enter` to unfold a proof, `Tab` to switch
between Browse and Review, `1` through `4` to change margin evidence, `s` to
choose a space, `p` to choose a local sync directory, `o` to open the selected
page in Confluence, and `?` for the complete keyboard map. Wide terminals show
all three regions; compact terminals reveal complete proofs and margins on
demand. The TUI requires interactive stdin and stdout and honors `--no-color`.

## `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`
- `tui`
- `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.
- TUI sync review is deliberately local-only; remote drift remains an `apply` preflight responsibility.

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

