CLI Reference¶
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. - Workspace commands take
--root PATH(default: current directory).
JSON envelope¶
Every --json response contains:
{
"schema_version": 1,
"command": "push",
"success": true,
"exit_code": 0,
"code": "OK",
"tool_version": "1.5.3",
"workspace": "/abs/path/notes"
}
plus command-specific fields (summary, items, execution,
planned_operations, checks, conflicts, ...). success is true for
exit codes 0, 1, 2, 8 (the command completed; the code describes the
outcome) and false for operational errors (3–7, 9).
Exit codes¶
See the table in AGENTS.md; it is part of
the public contract. Priority when several apply to one run:
5 (concurrent) > 6 (partial failure) > 2 (conflicts) > 0.
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.
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.
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 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.
For note creation, pass an existing parent_id or a notebook_title to
find/create a notebook. With neither, MCP Notes is found or created.
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 by strict
POSIX permissions, 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. URL must be an HTTPS origin on port 443 with no path,
query, fragment, or credentials. The JSON 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.