Skip to main content

Agent-friendly CLI and SDK for local Joplin desktop

Project description

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 append id=<note-id> content="- [ ] Follow up"
joplin-cli batch delete query="tag:temporary" dry-run

Design rules that matter for agents:

  • Use key=value arguments for predictable shell generation.
  • Prefer --json when another tool will parse the result.
  • 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 update id=<note-id> title="New title"
joplin-cli notes append id=<note-id> content="- [ ] Follow up"
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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

joplin_cli-0.1.1.tar.gz (34.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

joplin_cli-0.1.1-py3-none-any.whl (31.6 kB view details)

Uploaded Python 3

File details

Details for the file joplin_cli-0.1.1.tar.gz.

File metadata

  • Download URL: joplin_cli-0.1.1.tar.gz
  • Upload date:
  • Size: 34.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","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}

File hashes

Hashes for joplin_cli-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b13f65625e30d0199c6c2be9404506ebd01f48c278b806b830213545ed4b4860
MD5 57d29bcf72f15e2cd621209807c944fb
BLAKE2b-256 3bbc247dc1d8bb5c61d7b84780973333c7e0f6ec65f4c756cd0bfa349fc0206a

See more details on using hashes here.

File details

Details for the file joplin_cli-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: joplin_cli-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 31.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","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}

File hashes

Hashes for joplin_cli-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e85a5edbf9168af7f9dca4459de5c89cdd5be8a5bad54b71a7f5aee67d78a3a3
MD5 257279ca1ddfb00a785b3a1dfbcec704
BLAKE2b-256 6374505c883f2c28428d7279271f87728e13f168a8ce3016fd27c2c20575216a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page