Skip to main content

joplin-cli

Agent-friendly CLI and Python SDK for controlling a running local Joplin desktop instance through the Joplin Clipper REST API.

中文

joplin-cli is designed for humans and coding agents that need predictable, single-shot commands. It does not provide a REPL or TUI. Every command starts, does one thing, prints useful output or a structured error, and exits.

What It Does

  • Connects to the local Joplin desktop Web Clipper service, usually at http://127.0.0.1:41184.
  • Auto-discovers the local desktop profile token from Joplin's settings.json when Joplin is already configured on the machine.
  • Exposes note, notebook, search, tag, todo, resource, diagnostic, config, and batch operations.
  • Works as both an installable CLI and an importable Python SDK.
  • Keeps token values out of normal output, diagnostics, error messages, and object representations.
  • Returns agent-recoverable errors with Error, Cause, Try, and Examples sections where applicable.

Installation

Install the published CLI from PyPI:

uv tool install joplin-cli

Upgrade an existing installation:

uv tool upgrade joplin-cli

Run directly from a checkout during development:

uv run joplin-cli --help

The package installs the joplin-cli command. It does not install a joplin command by default, because that name may already belong to another Joplin tool. Check the optional alias workflow with:

joplin-cli alias status

Quick Start

uv tool install joplin-cli
joplin-cli doctor
joplin-cli notebooks list
joplin-cli notes list limit=10
joplin-cli search query="meeting notes" --json

doctor is the best first command. It checks whether the local Joplin server is reachable, whether a token can be found, and what to run next.

Agent Usage

Every command is single-shot. Use --json for machine-readable output.

joplin-cli notes read id=<note-id> --json
joplin-cli notes create title="Draft" body=@./draft.md
joplin-cli notes append id=<note-id> content="- [ ] Follow up"
joplin-cli batch delete query="tag:temporary" dry-run

For long Markdown content, write it to a UTF-8 file and pass the file as a text parameter. body=@./draft.md reads the note body from disk, and content=@./section.md does the same for append/prepend content. Use body=@@literal when the literal value must start with @.

Design rules that matter for agents:

  • Use key=value arguments for predictable shell generation.
  • Prefer --json when another tool will parse the result.
  • Use @file for long body or content values instead of putting large Markdown blocks directly in the shell command.
  • Use joplin-cli help or joplin-cli <group> --help to discover commands.
  • Errors explain the likely cause and a concrete next command.
  • Validation errors exit with code 2; connection, auth, not-found, and conflict errors use distinct exit codes.

Authentication

Default behavior is intentionally low-friction for local use. If Joplin desktop is already running and the Web Clipper service is enabled, joplin-cli tries to:

  1. Connect to 127.0.0.1:41184.
  2. Find the Joplin desktop profile.
  3. Read api.token from the profile settings.json.
  4. Use the token without printing it.

Override discovery when needed:

$env:JOPLIN_TOKEN="..."; joplin-cli notes list
joplin-cli config set token=...
joplin-cli config set port=41184
joplin-cli config path

Supported environment variables:

  • JOPLIN_TOKEN
  • JOPLIN_HOST
  • JOPLIN_PORT
  • JOPLIN_PROFILE
  • JOPLIN_TIMEOUT
  • JOPLIN_CLI_CONFIG

Token precedence is: CLI option, environment variable, joplin-cli config, auto-discovered Joplin profile.

Common Commands

Notes:

joplin-cli notes list limit=20
joplin-cli notes read id=<note-id>
joplin-cli notes create title="Draft" body="# Draft"
joplin-cli notes create title="Draft" body=@./draft.md
joplin-cli notes update id=<note-id> title="New title"
joplin-cli notes update id=<note-id> body=@./draft.md
joplin-cli notes append id=<note-id> content="- [ ] Follow up"
joplin-cli notes append id=<note-id> content=@./section.md
joplin-cli notes delete id=<note-id>

Notebooks:

joplin-cli notebooks list
joplin-cli notebooks tree
joplin-cli notebooks create title="Projects"
joplin-cli notebooks rename id=<notebook-id> title="Archive"

Search, tags, and todos:

joplin-cli search query="meeting notes" --json
joplin-cli tags list
joplin-cli tags add note=<note-id> tag=<tag-id>
joplin-cli todos list open
joplin-cli todos done id=<todo-id>

Resources:

joplin-cli resources list
joplin-cli resources attach note=<note-id> path="./file.pdf"
joplin-cli resources download id=<resource-id> output="./file.pdf"

Output Formats

Text output is compact by default. Use JSON for automation:

joplin-cli notes list limit=10 --json

Other tabular formats are available where the output is list-like:

joplin-cli notes list limit=10 --format tsv
joplin-cli notes list limit=10 --format csv

Batch Delete Safety

Batch delete is intentionally two-step. First run a dry run:

joplin-cli batch delete query="tag:temporary" dry-run

The dry run prints:

  • The number of matching notes.
  • A preview containing note IDs and titles.
  • A confirmation token shaped like delete-2-notes-<hash>.

Only then run the destructive command:

joplin-cli batch delete query="tag:temporary" confirm=delete-2-notes-<hash>

The confirmation token is bound to the query and matched note IDs, not just the count. A token from one query cannot confirm another query that happens to match the same number of notes.

For automation that has already done its own safety checks, yes bypasses the confirmation token:

joplin-cli batch delete query="tag:temporary" yes

Python SDK

The SDK is the core layer; the CLI is a thin wrapper around it.

from joplin_cli import JoplinClient

with JoplinClient.auto() as client:
    notes = client.notes.list(limit=10)
    first = notes[0]
    print(first.id, first.title)

Explicit connection:

from joplin_cli import JoplinClient

client = JoplinClient(host="127.0.0.1", port=41184, token="...")
try:
    notebooks = client.notebooks.list()
finally:
    client.close()

Main SDK services:

  • client.notebooks
  • client.notes
  • client.search
  • client.tags
  • client.todos
  • client.resources
  • client.batch

Error Model

CLI errors are intended to be actionable without reading source code:

Error: Parameter limit must be an integer.
Try: Use limit=5.

Exit codes:

  • 0: success
  • 1: general API/output error
  • 2: validation or CLI usage error
  • 3: local Joplin connection error
  • 4: authentication error
  • 5: not found
  • 6: conflict or destructive action not confirmed

Development

Install the current checkout as a tool while testing packaging:

uv tool install . --force

Install dependencies and run checks:

uv sync
uv run pytest -v
uv run ruff check .
uv run ty check

Optional live smoke test against a running local Joplin desktop:

$env:JOPLIN_CLI_LIVE="1"; uv run pytest tests/live/test_live_joplin.py -v

The live test only reads notebooks. It does not create, edit, or delete Joplin data.

Release

PyPI publishing is configured through GitHub Actions trusted publishing. Create and publish a GitHub Release from this repository; the release.yml workflow will run tests, linting, type checks, build the distributions, and publish them to PyPI without a stored PyPI token.

Before creating a release, update version in pyproject.toml and verify the package locally:

uv run pytest -q
uv run ruff check .
uv run ty check
uv build

Troubleshooting

If doctor says the server is offline:

joplin-cli doctor

Check that Joplin desktop is running and that the Web Clipper service is enabled.

If token discovery fails, inspect configuration:

joplin-cli auth
joplin-cli config path
joplin-cli config get token

Token values are redacted in command output.

Release files for joplin-cli 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for joplin-cli 0.1.4
File Size Uploaded
joplin_cli-0.1.4.tar.gz 36.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for joplin-cli 0.1.4
File Interpreter ABI Platform
joplin_cli-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 69.5 kB

Release files / joplin_cli-0.1.4.tar.gz

Download URL joplin_cli-0.1.4.tar.gz
Size 36.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e1481c6bbf43e42988552077fd08e5d6fbd6f5b717f448dd30c05ae7adabef45
BLAKE2b-256 checksum
How to use checksums
1eb8f6e69382f4f6664d8c05160b11fc309626db1ab8c9317663804c373c760e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / joplin_cli-0.1.4-py3-none-any.whl

Download URL joplin_cli-0.1.4-py3-none-any.whl
Size 32.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ba28c0f995743ff4de17892505a280dd4fb11fe9a2b0ca15808e581a283a1b46
BLAKE2b-256 checksum
How to use checksums
431f4a98cd0bcbc09011b06959639ac6a122b560800ae96ba0dbbd5c597fd565
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page