npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@knpkv/confluence-to-markdown

v0.4.2

Published

Sync Confluence Cloud pages to local GitHub Flavored Markdown files

Readme

@knpkv/confluence-to-markdown

Warning This package is experimental and in early development. Code is primarily AI-generated and not yet publicly published. For preview, use snapshot releases.

Sync Confluence Cloud pages to local GitHub Flavored Markdown files with built-in git version tracking.

Installation

npm install @knpkv/confluence-to-markdown effect

CLI Usage

Core Commands

# Clone pages with full version history
confluence clone --root-page-id <ID> --base-url <URL>

# Pull pages from Confluence
confluence pull
confluence pull -f, --force           # overwrite local changes
confluence pull --replay-history      # replay each version as separate git commit

# Push local changes to Confluence
confluence push
confluence push -n, --dry-run         # preview changes without applying

# Delete a page (interactive selector, deletes local file)
confluence delete

# Check sync status
confluence status

Authentication Commands

# Create OAuth app (opens browser to Atlassian Developer Console)
confluence auth create

# Configure OAuth credentials
confluence auth configure --client-id <ID> --client-secret <SECRET>

# Login via browser
confluence auth login
confluence auth login --site <URL>    # for accounts with multiple sites

# Check auth status
confluence auth status

# Logout
confluence auth logout

Page Creation

# Create a new page (interactive parent selector)
confluence new

# Workflow:
# 1. Create new page: confluence new
# 2. Edit the file
# 3. Commit: confluence commit -m "Add new page"
# 4. Push to Confluence: confluence push

Page Deletion

# Delete a page (interactive selector)
confluence delete

# Workflow:
# 1. Delete page: confluence delete (or rm <file>)
# 2. Commit: confluence commit -m "Delete page"
# 3. Push to Confluence: confluence push  # deletes from Confluence

Git Commands

# Commit current changes
confluence commit
confluence commit -m "message"

# Show commit history
confluence log
confluence log -n 5               # last 5 commits
confluence log --oneline          # compact format
confluence log --since 2024-01-01 # since date

# Show changes in working directory
confluence diff
confluence diff --staged          # staged changes only
confluence diff --commit HEAD~1   # compare with commit

How It Works

  1. confluence clone creates .confluence/ directory, initializes git, and pulls pages with full version history
  2. confluence pull downloads pages and auto-commits changes
  3. confluence pull --replay-history replays each Confluence version as a separate git commit with original author/date
  4. Version messages from Confluence are preserved in markdown front-matter
  5. Use standard git commands in .confluence/ for advanced operations

Git Implementation

Two-Branch Model

The CLI uses a two-branch model to track sync state:

  • local (current branch): Your working branch for edits
  • origin/confluence: Tracks the remote Confluence state
Clone:
  Confluence ──pull──> local + origin/confluence (both at same commit)

Pull:
  Confluence ──pull──> origin/confluence ──merge──> local

Push:
  local ──push──> Confluence
    │
    └──> origin/confluence (updated to HEAD)

Commit Behavior

When you commit:

  1. Sync external docs (if configured): Copies files from external docsPath to .confluence/
  2. Stage all changes: Runs git add -A
  3. Create commit: Records changes with your message

Note: Front-matter (contentHash, version) is not updated at commit time. Changes are detected by comparing actual content hash vs stored hash.

Push Behavior

When you push:

  1. Detect changes: Compares content hash vs stored contentHash in front-matter
  2. Push to Confluence: Uploads markdown converted to Confluence storage format
  3. Fetch canonical content: Downloads what Confluence actually stored (may differ slightly)
  4. Amend commit: Updates local file with canonical content so future clones match exactly
  5. Update tracking branch: Moves origin/confluence to HEAD

Multiple local commits combine into a single Confluence version (uses last commit's message).

Content Hash Tracking

Each markdown file has front-matter with a contentHash field:

---
pageId: "123456"
version: 42
title: My Page
contentHash: 7a8b9c... # SHA-256 of markdown content
---
  • After clone/pull: contentHash matches the actual content
  • After local edit: content differs from contentHash → detected as "needs push"
  • After push: contentHash updated to match canonical Confluence content

Why Canonical Content?

Confluence may transform your content (normalize whitespace, reorder attributes, etc.). By fetching and storing the canonical content after push:

  • clone on another machine produces identical files
  • Git history shows exactly what Confluence has
  • No false "modified" status from round-trip differences

Authentication

OAuth (recommended)

1. Create OAuth App

  1. Go to Atlassian Developer Console
  2. Click CreateOAuth 2.0 integration
  3. Enter app name (e.g., "Confluence CLI")
  4. Configure permissions in Permissions tab:
    • Add Confluence API with scopes:
      • read:page:confluence - read pages
      • write:page:confluence - push changes
      • delete:page:confluence - delete pages
    • Add User Identity API:
      • read:me - get current user info
  5. In Authorization tab, set callback URL: http://localhost:8585/callback
  6. In Settings tab, copy Client ID and Secret

2. Configure and Login

# Configure with your client ID and secret
confluence auth configure --client-id <ID> --client-secret <SECRET>

# Login via browser
confluence auth login

# Check login status
confluence status

# Logout
confluence auth logout

API Token (alternative)

export CONFLUENCE_API_KEY=your-api-token
export [email protected]

Generate API token at Atlassian Account Settings.

Security Notes

  • OAuth credentials stored in ~/.confluence/ with restricted permissions (0600)
  • Treat these files as sensitive - do not share or commit
  • Create separate OAuth apps per developer for team projects
  • Tokens auto-refresh; if refresh fails, re-run confluence auth login

Configuration

Initialize configuration with confluence clone:

confluence clone --root-page-id 123456 --base-url https://yoursite.atlassian.net

This creates .confluence/config.json in your project root:

{
  "rootPageId": "123456",
  "baseUrl": "https://yoursite.atlassian.net",
  "docsPath": ".confluence/docs",
  "excludePatterns": [],
  "saveSource": false,
  "trackedPaths": ["**/*.md"]
}

Configuration Options

| Option | Description | Default | | ----------------- | ------------------------------------- | ------------------ | | rootPageId | Confluence page ID to sync from | Required | | baseUrl | Confluence Cloud URL | Required | | spaceKey | Optional space key | - | | docsPath | Local path for markdown files | .confluence/docs | | excludePatterns | Glob patterns to exclude | [] | | saveSource | Save original HTML alongside markdown | false | | trackedPaths | Glob patterns for git tracking | ["**/*.md"] |

Directory Structure

project/
├── .confluence/
│   ├── config.json      # Configuration file
│   ├── .git/            # Git repository for version tracking
│   └── docs/            # Synced markdown files
│       ├── page1.md
│       ├── page1/       # Children of page1
│       │   └── child.md
│       └── subdir/
│           └── page2.md
└── ...

Page Hierarchy Rules

Directory structure determines Confluence page hierarchy:

  • Files in docs/ root → children of root page
  • foo.md → page "foo"
  • foo/ directory → contains children of "foo.md"
  • foo/bar.md → child page of "foo.md"

Example structure:

docs/
├── guide.md           # Child of root
├── guide/             # Children of guide.md
│   ├── getting-started.md
│   └── advanced.md
└── reference.md       # Child of root

New Page Front-matter

New pages require only a title in front-matter:

---
title: "My New Page"
---
Page content here...

After pushing, the file is updated with full metadata:

---
pageId: "123456"
version: 1
title: "My New Page"
updated: 2024-01-15T10:30:00.000Z
parentId: "789012"
contentHash: "7a8b9c..."
---

Known Limitations

  • Attachments: Image and file attachments are not synced
  • Comments: Page comments are not preserved

License

MIT