CLI Reference¶
This page is a user reference for commands and options. The stable machine interface is defined only by the CLI and output contract; synchronization behavior is defined by the synchronization contract.
Global conventions:
--json: deterministic machine-readable envelope on stdout; logs and diagnostics go to stderr. No ANSI codes in JSON. Keys are sorted.--verbose/--quietcontrol stderr logging;--log-file PATHadds a debug log file. The token is redacted from all channels.- Connection options (where relevant):
--base-url URL,--port N,--token-file PATH,--timeout SECONDS,--allow-remote-api. Without any of them (and without env/workspace overrides) the built-in defaulthttp://127.0.0.1:41184is used when it answers/ping, with a fallback scan of ports 41184-41194. Only the token must be configured. - The Joplin token comes from exactly one source:
--token-file PATHor theJOPLIN_TOKENenvironment variable. Setting both is an error that names both sources; an emptyJOPLIN_TOKENcounts as unset. The token file must be private: one line in a regular file (not a symlink) owned by you, with mode0600on Linux, and on Windows owned by you with no access for other accounts, for example aftericacls FILE /inheritance:r /grant:r "%USERNAME%:(R)". Files that others can read or change are rejected without echoing their content. - Workspace commands take
--root PATH(default: current directory). --helpprints the parser reference; top-level--versionprints the package version without the richerversioncommand envelope.
JSON envelope¶
For example, a successful push --json response begins with the common fields
owned by CLI-001:
{
"schema_version": 1,
"command": "push",
"success": true,
"exit_code": 0,
"code": "OK",
"tool_version": "1.7.0",
"workspace": "/abs/path/notes"
}
Command-specific fields include summary, items, execution,
planned_operations, checks, and conflicts. Read exit_code and code
together instead of parsing human-readable diagnostics.
Exit codes¶
The complete stable mapping and evidence are in
CLI-002.
Clients can discover the same public surface with capabilities --json.
Commands¶
version, capabilities, update-check¶
version --json→ tool, python, protocol/state/output schema versions, distribution kind (standalone/wheel/zipapp/source).capabilities --json→ command list, feature flags, exit-code table.update-check --json [--include-prerelease] [--offline]→ queries the GitHub Releases API. Exit 0 current, 8 outdated (code: VERSION_OUTDATED, with an exactupdate_command), 4 when the check cannot be completed (code: UPDATE_CHECK_FAILED), 0 withcode: UPDATE_CHECK_SKIPPEDfor--offline. It never self-updates. Use--include-prereleaseonly when preview releases are relevant.
init --root PATH [--mode remote-first|local-first]¶
Creates .joplin-sync/ (state DB, config, journal/backup/conflict dirs)
and a .gitignore. remote-first (default) refuses to run when unmanaged
*.md files already exist (exit 7, listing them). local-first adopts
them: files without a Joplin id are pushed as new notes, and the first real
push requires a preceding push --dry-run.
--mode selects the initialization policy.
doctor --root PATH [--offline]¶
Checks python version, workspace integrity, state DB, incomplete runs, open conflicts, invalid files, lock availability, Joplin ping + token. Exit code = severity of the first problem (3/6/2/4/5), 0 when healthy.
status --root PATH¶
Offline: local files vs base snapshot only (remote_state: "unknown").
Reports tracked counts, local changes, open conflicts, incomplete runs.
pull / push / sync --root PATH [--dry-run] [--propagate-deletes]¶
Scan → classify → plan → journal → apply (guard, apply, verify, commit
base per operation). --dry-run prints planned_operations and exits
1 when work is pending (0 when clean, 2 when conflicts exist), mutating
nothing. Deletions are only reported unless --propagate-deletes.
diff --root PATH [modes]¶
Never mutates. Modes: --summary (default), --name-status, --unified,
--three-way, --against remote|base, --note ID_OR_PATH, --offline.
Exit code is always 0 unless --exit-code is passed (then 1 = differences,
2 = conflicts). Unified diff labels: joplin/<note-id>,
local/<relative-path>, base/<note-id>.
recover --root PATH¶
Settles incomplete journals: verifies which operations completed (base snapshots are committed before an op is marked applied, so current state is the witness), marks the rest "not applied; rerun", removes stray temp files, and unblocks the workspace.
conflicts list | show ID | resolve ID MODE | discard ID¶
See CONFLICTS.md.
note set-title PATH TITLE, note set-tags PATH [TAG...], note validate PATH¶
Safe header editing (atomic rewrite; adds a header to plain files) and validation (exit 3 for a malformed header).
resources pull --root PATH¶
Downloads every :/resource-id referenced by managed notes into
.joplin-sync/resources/<id>[.ext]. Markdown links are never rewritten.
mcp stdio [--token-file PATH | --token TOKEN] [--port PORT]¶
Runs a local MCP server over stdin/stdout for an IDE or agent that launches the
executable directly. Joplin Desktop must already be running locally with Web
Clipper enabled. --port PORT selects its Data API port on 127.0.0.1
(default 41184). No network MCP listener or Markdown workspace is created.
The Joplin token comes from exactly one of two paths:
- the command line:
--token-file PATH, the recommended form, or the compatibility--token TOKEN; the two options are mutually exclusive; - the
JOPLIN_TOKENenvironment variable, for launchers that export it.
A command-line option together with a non-empty JOPLIN_TOKEN is a
configuration error that names both sources; neither silently wins, and the
check runs before the file is read or Joplin is contacted. An empty or
whitespace-only JOPLIN_TOKEN counts as unset. With no source the command
fails and names both paths. These errors exit with code 4 and write only to
stderr, so the protocol stream on stdout stays clean.
--token-file PATH follows the same private-file rules as every other command:
a regular file, not a symlink, holding one line with the token, mode 0600 on
Linux or restricted to your account on Windows. Oversized, empty, multi-line,
or non-ASCII files are rejected without echoing their content. Create it once
outside synchronized folders:
install -d -m 0700 ~/.config/joplin-md-sync
(umask 077; read -rs -p 'Joplin token: ' token &&
printf '%s\n' "$token" > ~/.config/joplin-md-sync/token)
--token TOKEN remains for existing IDE configurations only. IDE configuration
persists command arguments, other processes of the same user can list them,
and some editors forward the MCP configuration to agents on their command
lines, so prefer the token file.
This mode does not expose /mcp, GPT Actions, /healthz, or /readyz and
does not accept --auth-token-file, --gpt-actions, or
--gpt-actions-token-file. Those bearer credentials protect HTTP interfaces
that do not exist in stdio mode; only the Joplin token is used.
The optional --timeout SECONDS, --retry-timeout SECONDS, and
--retry-delay SECONDS settings have the same call behavior as mcp serve.
The process reads one JSON-RPC message per stdin line, writes only JSON-RPC to
stdout, and exits when the client closes stdin. --verbose, --quiet, and
--log-file PATH affect diagnostics on stderr or in the selected log file.
mcp serve [connection and server options]¶
Runs a foreground MCP Streamable HTTP server at
http://127.0.0.1:8765/mcp by default. It exposes note, notebook, tag, and
binary-resource CRUD, trash/restore where Joplin supports it, Markdown/HTML
content, attachments, relationship traversal, and full-text search. No
workspace is required.
This remains the network listener mode. Without the separate mcp stdio
subcommand, the HTTP listener and its existing MCP/Actions options behave as
before.
For note creation, pass an existing parent_id or a notebook_title to
find/create a root notebook. With neither, MCP Notes is found or created.
Explicit create tools reject an occupied natural identity; see
Create conflicts for the comparison keys and
recovery workflow.
Joplin connection options are the normal --base-url, --port,
--token-file, --timeout, and --allow-remote-api. Server options:
--host HOST,--mcp-port PORT,--mcp-path PATH--retry-timeout SECONDS,--retry-delay SECONDS,--discovery-timeout SECONDS--auth-token-file PATHto enable MCP pre-shared bearer authorization; the protected file must contain a URL-safe Base64 token encoding at least 32 bytes generated by a cryptographically secure random generator- repeatable
--allowed-origin ORIGIN --allow-remote-mcpfor an explicit non-loopback bind; this also requires--auth-token-file--gpt-actionsto add authenticated/api/gpt/v1/tools/*routes to the same listener--gpt-actions-token-file PATH(required with--gpt-actions)--gpt-actions-max-request-bytes N,--gpt-actions-max-response-chars N,--gpt-actions-max-concurrency N, and--gpt-actions-rate-limit REQUESTS_PER_MINUTE
The command intentionally stays in the foreground. Full protocol behavior, security guidance, MCP client configuration, and service-manager examples are split by purpose between MCP API and Joplin API Service.
Actions-only options are rejected unless --gpt-actions is present. The
Actions token file is required, re-read on each request, protected like every
token file (POSIX mode or Windows ACL), and must differ from the Joplin and MCP
credentials.
gpt-actions export-openapi --server-url URL --output PATH¶
Generates deterministic OpenAPI 3.1 JSON from the shared tool registry without
contacting Joplin. --server-url must receive an HTTPS origin on port 443 with
no path, query, fragment, or credentials. --output selects the destination
JSON file. The result reports operation_count, registry_hash, server_url,
and output.
The repository does not store a generated contract. Export it with the real public hostname immediately before importing or updating a Custom GPT. See ChatGPT Actions end-to-end setup.