# QMind CLI for Qoder Global

[简体中文](./README.zh-CN.md)

The QMind command-line interface for Qoder Global lets you sign in, manage knowledge bases and sources, retrieve content, run RAG and task workflows, and synchronize local directories.

Package: `@qoder-ai/qmind-cli` · command: `qmind`

## Install

Node.js `>=22.19.0` is required.

```sh
npm install --global @qoder-ai/qmind-cli
qmind version
qmind --help
```

Upgrade and uninstall through npm. `qmind self-update` only prints the npm upgrade command and never modifies npm-managed files.

```sh
npm update --global @qoder-ai/qmind-cli
npm uninstall --global @qoder-ai/qmind-cli
```

The Native standalone CLI uses the verified Global release channel instead. An installer-managed
Native executable can check or apply the latest release without Node.js or npm:

```sh
qmind update --check
qmind update
```

`self-update` remains an alias for `update`. The updater rejects channel/URL overrides, downgrades,
unowned executables, release checksum mismatches, and modified installer bytes. Windows schedules
replacement after the running executable exits and records details beside the executable.

## Quick start

```sh
qmind login
qmind notebook list
qmind source list --nb <notebook-id>
qmind retrieve --nb <notebook-id> "What must be checked before release?"
```

Interactive login opens a browser and stores the session in a local file vault. For CI and agents, prefer an environment variable and structured output:

```sh
export QMIND_TOKEN='<token>'
qmind notebook list --non-interactive --format json
qmind retrieve --nb <notebook-id> --format agent "What is the deployment process?"
```

Do not put tokens in command arguments, repositories, or logs. Run `qmind logout` to remove the current local session.

## Commands

| Command                  | Purpose                                  |
| ------------------------ | ---------------------------------------- |
| `login` / `logout`       | Sign in or remove local credentials      |
| `notebook`               | Manage knowledge bases                   |
| `source`                 | Manage knowledge-base sources            |
| `retrieve`               | Retrieve context without invoking an LLM |
| `rag`                    | Ask questions using a knowledge base     |
| `task`                   | Manage task runs                         |
| `scheduled-task`         | Manage notebook schedule configurations  |
| `upload-folder` / `sync` | Synchronize a local directory            |
| `image`                  | Obtain image upload or access URLs       |
| `version`                | Print version and build information      |
| `update` / `self-update` | Update an installer-managed Native CLI   |

`task create` does not start `compilation` or `lint` runs; `task list` and `task get` can still inspect historical runs for those scenes. `source import-site` does not provide an automatic compilation option.

Run `qmind <command> --help` for complete options. Domain commands support formats such as `table`, `json`, `agent`, and `ndjson`. stdout contains results; progress and diagnostics go to stderr. Exit codes are `0` for success, `1` for runtime failure/partial success/cancellation, and `2` for invalid usage.

## Multi-notebook retrieval

`retrieve --nb` accepts comma-separated or repeated Notebook IDs, deduplicating up to 5 distinct notebooks:

```sh
qmind retrieve --nb nb-1,nb-2 "What is the deployment process?" --format json
qmind retrieve --nb nb-1 --nb nb-2 "What is the deployment process?" --format agent
```

- Selection is explicit; the CLI never defaults to all accessible notebooks.
- Multiple notebooks use one unified retrieval request. The server jointly retrieves and reranks Source chunks; output retains server ranking and each chunk/citation's `notebookId` and `notebookTitle`.
- `--top-k` controls the joint recall candidate budget per route/query/channel; it is not multiplied by notebook count. `--max-results` limits the final results across all selected notebooks. Zero uses server defaults.
- `--sources` requires a single notebook. A single deduplicated notebook keeps the existing retrieval endpoint. All retrieval output formats expose chunks and citations without knowledge cards.
- Multi-notebook JSON returns `{ chunks, citations, promptContext, total, reranked }`. NDJSON emits one `kind: "chunk"` record per returned chunk, in server order; zero hits emit no records. Table and agent output also identify each evidence item's notebook.
- Unified retrieval fails as one request when a target is invalid or inaccessible. The CLI reports the error without retrying notebooks individually or constructing partial-success results. Retrieval results no longer contain a `cards` field.

## Directory synchronization

Review the plan before allowing remote deletions:

```sh
qmind upload-folder --nb <notebook-id> --dir ./docs --mode if-changed --dry-run
```

Removing `--dry-run` enables writes. `--delete` treats the remote source root as a mirror of the local directory and removes extra remote entries. Concurrency must be between `1` and `10`.

## Configuration and authentication

This package has a fixed Qoder Global identity. Renaming the executable, changing its install path, or setting product-selection environment variables cannot switch products. Production is the default; `--env test` and `--env daily` select supported debug presets. A custom target requires both `--sash` and `--dashboard` and cannot be combined with an explicit `--env`.

```sh
qmind login --env test
QMIND_DEBUG_TOKEN='<debug-token>' qmind notebook list --env test --non-interactive --format json
qmind login --sash http://localhost:8080 --dashboard http://localhost:3000
```

Production token priority is `--token > QMIND_TOKEN > current production vault`. Debug token priority is `--token > QMIND_DEBUG_TOKEN > current debug vault`; credentials are never borrowed across targets.

State is stored under `<state-root>/cli/global/<target>/`, where the state root is `QMIND_HOME` or `~/.qmind`. The CLI does not install, load, or access the OS Keyring. Credential files are plaintext JSON, not encrypted storage. On POSIX, partition directories use mode `0700` and files use `0600`; these modes do not represent Windows ACLs. Writes use atomic replacement, file locking, and compare-and-swap protection for refreshes.

After upgrading from the legacy unpartitioned store, sign in again. Root-level config/credential files, `~/.qmind-env`, and old Keyring entries are not read, imported, or deleted automatically.

The shared 3.x Global/CN release is a breaking upgrade from Global 2.x. Upgrade this package with npm, then run `qmind login`; do not copy legacy credentials into the new partition. Existing versions before the shared release describe the Global/shared implementation only and do not imply a historical CN publication.

Common variables include `QMIND_TOKEN`, `QMIND_DEBUG_TOKEN`, `QMIND_HOME`, `QMIND_CLIENT`, `QMIND_NON_INTERACTIVE`, `QMIND_REQUEST_TIMEOUT_MS`, `QMIND_STREAM_IDLE_TIMEOUT_MS`, and `QMIND_TLS_CA_FILE`. `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` are supported. TLS verification is strict by default, and credentials are not forwarded to signed object-storage URLs.

## Shared notebook discovery and access

```sh
qmind notebook list --shared --page 1 --page-size 20
qmind notebook list --shared --format json
qmind notebook get <notebook-id> --format json
```

Both notebook collections support `--page` and `--page-size`. `--shared` cannot be combined with `--filter-client`. Shared results use the same flat `notebooks` output as the ordinary list and preserve the membership `permission`. JSON/NDJSON preserve server-provided `access` (current role, member count and action permissions); Agent output expands these fields. Table lists show role and member count, while details show action permissions. Missing permissions are not inferred and display as `unknown` in tables.

## Commands aligned with Agent tools

Core-backed workflows (`notebook discover`, `source import-url/read/delete-batch`, `mkdir --derive-path`, `mv --to/--to-root`, unified retrieval, and `scheduled-task`) return `{ ok, data/error, meta }` after entering Agent Core, with `meta.operationId` identifying the operation. `--format ndjson` emits one complete result per line; `table` and `agent` also use this JSON result. CLI validation and host/credential failures before Core keep the existing CLI error format: `{ error }` on stdout for JSON/NDJSON, or text on stderr otherwise. Command usage errors and declined confirmations go to stderr. `source list --parent` keeps the existing Source-list output. Exit codes are 0 for success, 1 for partial success/runtime failure/cancellation, and 2 for invalid arguments. A successful write does not mean Source ingestion or a scheduled run has completed.

```sh
# Select retrieval-eligible owned/shared notebooks; continue with nextCursor when hasMore is true
qmind notebook discover --relationship all --page-size 20
qmind notebook discover --relationship all --cursor '<nextCursor>'

# Import a single page; inspect ingestion and content with source get / source read
qmind source import-url --nb <notebook-id> --url https://example.com/guide
qmind source list --nb <notebook-id> --parent <directory-id>
qmind source read <source-id> --nb <notebook-id> --offset 0 --max-chars 20000

# Derive paths from the actual parent and preserve the original basename when moving
qmind source mkdir --nb <notebook-id> --title guides --parent <directory-id> --derive-path
qmind source mv <source-id> --nb <notebook-id> --to <directory-id>
qmind source mv <source-id> --nb <notebook-id> --to-root

# 1..100 distinct IDs; confirm interactively or explicitly pass --force
qmind source delete-batch <source-id-1> <source-id-2> --nb <notebook-id> --force
```

`notebook list/get` JSON/NDJSON preserve the server's overview, sourceCount and materialCount. Agent output expands summary/topics; table lists include summaries and Source counts. `discover` supports owned/shared/all and cursors, defaults to all, and lists retrieval-eligible notebooks; use `list` for the management collection. An empty page may still have `hasMore:true`; continue with the same relationship.

`source read` checks ingestion status and returns `content/contentType/truncated/nextOffset`. It still fetches the entire body before slicing, so only output size is bounded. Existing `source content` full-text/download behavior is unchanged. `source list --parent` cannot be combined with `--all`.

`mkdir --derive-path` conflicts with `--path`. `mv --to/--to-root` conflicts with the legacy parent/path/rename/status options and only moves eligible leaf documents within one notebook, preserving the basename. Existing low-level mkdir/mv patch operations remain available.

Batch deletion returns the submitted sourceIds and successCount/failureCount; sourceIds is not a list of successfully deleted IDs. Partial failure exits 1. Reconcile current state before another call; do not guess failed IDs or replay the entire batch.

## Precise and unified retrieval

Existing `retrieve --nb` defaults and output remain unchanged. Explicit `--unified` or `--targets` selects the same unified retrieval workflow used by Agent tools, including notebook identity in single-notebook chunks:

```sh
qmind retrieve --nb <notebook-id> --unified --score-threshold 0.6 'Deployment process'
qmind retrieve --targets '[{"notebookId":"nb-1","sourceIds":["source-1"]},{"notebookId":"nb-2","sourceIds":["source-2"]}]' --max-results 8 'Deployment process'
```

`--targets` conflicts with `--nb` and `--sources` and supports independent Source filters per notebook. Unified retrieval defaults to maxResults=8 (1..50), with optional topK (1..100); zero selects the workflow default. There may be at most five unique targets. Results use the envelope above: read `data.chunks/data.promptContext`. `--score-threshold` accepts 0..1 and also works on the existing retrieval path. Zero budgets on the existing path still use server defaults; scripts are not silently migrated.

## Scheduled task configuration

```sh
qmind scheduled-task create --nb <notebook-id> --scene source_refresh --schedule 'CRON_TZ=Asia/Shanghai 0 9 * * *'
qmind scheduled-task list --nb <notebook-id> --enabled true --page 1 --page-size 20
qmind scheduled-task update <task-id> --nb <notebook-id> --schedule 'CRON_TZ=Asia/Shanghai 0 10 * * *'
qmind scheduled-task pause <task-id> --nb <notebook-id>
qmind scheduled-task resume <task-id> --nb <notebook-id>
qmind scheduled-task delete <task-id> --nb <notebook-id>
```

`update --enabled false/true` also pauses/resumes. Creation defaults to enabled with empty config; arbitrary prompt/config inputs are not accepted. Updates only change schedule or enabled. Scenes are compilation, condensation, lint, source_refresh and source_binding_sync; the server decides actual availability and full Cron validity. An explicit IANA timezone is required. Compilation may be retired; source_binding_sync is currently a per-notebook singleton with a minimum five-minute interval. `list` supports `--task/--scene/--enabled`, with pageSize at most 20; the backend still reads all configurations for the notebook. Oversized config is marked `configTruncated:true`.

Configuration is separate from execution: use `task list --scheduled-task <task-id>` for run history. Pausing/deleting does not cancel dispatched runs; resuming an overdue schedule may trigger a run immediately. Execution retains the original creator identity; revoking membership does not guarantee schedules stop automatically.

## Unconfirmed writes

When a new command returns `error.code=outcome_unknown` and `retryable:false`, inspect current state before deciding what to do next; do not retry automatically. Existing direct-write commands also distinguish this state in JSON/NDJSON errors and retain the original causeCode/requestId. Unknown outcomes do not prove a request reached the server; a same-name resource does not prove this call created it.

`notebook delete` and `source delete` support JSON/NDJSON success receipts. Single-Source deletion stops if preflight cannot read the Source; only explicit `--force` skips directory confirmation. Default text output remains `deleted`.
