# Citation CLI

Version 0.1.0. Node.js 22 or later. This local package has not been published to npm. It uses the existing Citation MCP server and official MCP client SDK. It does not add a second API or server.

## Install

Download `citation-cli-0.1.0.tgz` from your Citation application's `/ai/cli` page. From its download folder:

```sh
npm install --global ./citation-cli-0.1.0.tgz
citation --help
citation --version
```

Or, from the Citation repository root:

```sh
npm pack ./packages/cli --ignore-scripts
npm install --global ./citation-cli-0.1.0.tgz
```

Installation needs npm access to the package's MCP client dependency. To use a project installation instead of a global one, run `npm install ./citation-cli-0.1.0.tgz` in that project and invoke `./node_modules/.bin/citation`.

## Connect

Activate the existing MCP server with its migration and `MCP_ORIGIN`. Open Citation `/settings/mcp`, create a personal token for the intended workspace, and choose only the required scopes. The CLI supports these existing personal credentials. It does not invent a device code flow or perform interactive OAuth.

Set `CITATION_TOKEN` through a secret environment or pass it via private stdin. Never type a token as a literal command argument. Do not commit token files. Replace the reserved example origin with the exact endpoint from settings:

```sh
citation auth login --endpoint https://citation.example/mcp
citation auth status --json
citation workspace list --json
```

Login reads `CITATION_TOKEN`, verifies access, and saves a private configuration file. For a secret piped from a password manager, append `--token-stdin`; it reads at most 200 bytes. Tokens must be Citation MCP tokens, not Supabase credentials. Only HTTPS endpoints are accepted, except HTTP loopback addresses. Redirects are refused. Saved tokens cannot be sent to a different endpoint.

Configuration defaults to `$XDG_CONFIG_HOME/citation/config.json`, or `~/.config/citation/config.json`. `--config FILE` and `CITATION_CONFIG` select an isolated file. The config directory must be private (700 on Unix); the file is written atomically with mode 600. Symbolic config files are refused. Windows file ACLs must be managed by the operating system; Unix mode checks are skipped there. The saved credential is a private plaintext file, not an OS keychain.

For an ephemeral environment, set `CITATION_ENDPOINT` and `CITATION_TOKEN` and run commands without login. The environment token takes precedence. `--workspace UUID` checks the intended workspace before any workflow operation. `workspace use UUID` verifies and persists that selection. The server grants one workspace per token; another workspace needs a separate token. Switching with an environment token drops an unrelated saved credential rather than binding it to a new workspace.

```sh
citation config show --json
citation workspace use WORKSPACE_ID --json
citation auth logout --json
```

`config show` never returns credentials. Logout removes only the saved token. It cannot revoke a personal token remotely through the current MCP surface. Revoke it in Citation MCP settings, and clear `CITATION_TOKEN` separately. Expired, revoked, or removed workspace access fails with exit code 3 or 4.

## Read and search

```sh
citation documents list --query "research" --limit 20 --json
citation documents list --limit 20 --after NEXT_CURSOR --json
citation documents list --all --json
citation documents read DOCUMENT_ID --content --all --json
citation sources list DOCUMENT_ID --query "evidence" --all --json
citation sources read DOCUMENT_ID --source SOURCE_ID --json
citation tools list --json
```

Replace uppercase placeholders with actual returned values. Lists contain `items`, `has_more`, and `next_cursor`. Text reads contain `text`, `version`, and `next_offset`. Text offsets count Unicode code points. `--limit` accepts 1 to 50. Text `--length` accepts 1 to 20000. `--all` reads remaining pages from the supplied cursor/offset; a changing document version aborts a combined text read. List pagination is ordered by ID, not a transactional snapshot, so concurrent inserts can change the result set. Reference formatting and check pagination also run against the current saved data; review again if the document changes.

## Create and revise

```sh
citation documents create --title "Research notes" --text-file draft.txt --json
citation documents read DOCUMENT_ID --content --json
citation request-id
citation documents update DOCUMENT_ID --version VERSION \
  --content-file revised-content.json --request-id REQUEST_UUID --json
```

Content input is the editor object itself, not the entire `documents read` response:

```json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "A requested revision." }]
    }
  ]
}
```

Preserve existing nodes, marks, attributes and citation IDs. Use `--text-file` only when replacing rich formatting and citations is intended. Use `-` as the input path for piped text or JSON. Drafts have a limit of 100000 text characters and 1000000 bytes of editor JSON. Documents containing attachments or mentions must be edited in Citation.

Every mutation accepts `--request-id UUID`. If omitted, the CLI generates an ID and includes it in the result or in a connection/service error. It never retries writes automatically. A timeout can occur after a real commit. Retry the same command with the same inputs and request ID; use a new ID only for a new intentional change. Conflicts use exit code 5. A stale document version requires reading and reviewing the new state before preparing a new save. Source writes use the source's own version hash.

## Add and edit sources

Source files use the existing source contract. This example is synthetic test metadata, not a real publication:

```json
{
  "title": "Evidence and writing",
  "type": "article-journal",
  "doi": "10.1234/cli-fixture",
  "csl": {
    "type": "article-journal",
    "title": "Evidence and writing",
    "author": [{ "family": "Example", "given": "Ada" }],
    "issued": { "date-parts": [[2025]] },
    "container-title": "Fixture Journal"
  },
  "excerpt": "Synthetic evidence for testing only."
}
```

Optional fields include `url`, `doi`, and `excerpt`. Publication details go inside `csl`. Preserve unknown details as missing. Metadata is saved without fetching its URL. Source input is bounded to 60000 bytes. Matching DOI, URL or metadata identity reuses an existing source; adding a source does not insert a citation node.

```sh
citation sources add DOCUMENT_ID --file source.json --request-id REQUEST_UUID --json
citation sources read DOCUMENT_ID --source SOURCE_ID --json
citation sources update DOCUMENT_ID --source SOURCE_ID --version SOURCE_VERSION \
  --file source.json --request-id NEW_REQUEST_UUID --json
```

## Format, check and export

```sh
citation references format DOCUMENT_ID --style apa --all --json
citation citations check DOCUMENT_ID --all --json
citation documents export DOCUMENT_ID --format bibtex --output references.bib --json
```

Supported styles: `apa`, `modern-language-association`, `chicago-author-date`, `chicago-notes-bibliography`, `harvard-cite-them-right`, `ieee`, `nlm-citation-sequence`, `american-medical-association`, and `american-chemical-society`. Omit `--style` to use the document's style. Reference output has `bibliography` and `in_text` entries with `id`, `text`, and `html`. Inline examples are individually formatted; numeric and note sequence must be rendered in document context.

Insert saved source IDs into an editor citation node inside a paragraph:

```json
{
  "type": "citation",
  "attrs": {
    "id": "unique-cluster-id",
    "sourceIds": ["SAVED_SOURCE_UUID"],
    "text": "Formatted inline text",
    "label": "page",
    "locator": "12"
  }
}
```

Use a real source ID from that document and only a verified locator. The server checks source ownership. Save the revised editor content with the current document version, then read it again to verify persistence.

Citation checks are deterministic metadata and link checks, not plagiarism scans or comprehensive factual review. Formatting/checks support at most 200 saved sources per document. Exports support TXT, BibTeX and RIS, with all chunks read and the same snapshot ID required across chunks. `--length` selects a chunk size. Without `--output`, the result includes the complete `text`; with it, the CLI writes a private file and returns its path and snapshot details. It refuses to overwrite an existing file.

## Automation contract

`--json` returns compact JSON on stdout, and errors as `{ "error": { "code", "message", ... } }` on stderr. Save errors include `request_id` after the operation has been prepared. Normal output is indented JSON. No token is printed in auth/config/error output. Document content is user data; handle command results as confidential when appropriate.

| Exit | Meaning                                             |
| ---- | --------------------------------------------------- |
| 0    | Success                                             |
| 1    | Unexpected service or local failure                 |
| 2    | Invalid input or configuration                      |
| 3    | Authentication failure                              |
| 4    | Insufficient permissions or inaccessible data       |
| 5    | Version, source, export or request ID conflict      |
| 6    | Network, timeout, rate limit or server availability |

Use `--timeout` from 100 to 120000 milliseconds per request (default 35000). Cancellation or a failed connection does not prove a save was rolled back. Keep retry IDs. Authentication, permissions and rate limits come from the same existing MCP service.

This CLI does not expose deletion, sharing, invitations, uploads, public links, AI review or external web research. Revocation is in Citation settings. No npm publication, account configuration or deployment is part of installing the source package.
