@contextq/cli 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -5
- package/dist/index.js +105 -393
- package/package.json +9 -5
- package/dist/desktop-guide.d.ts +0 -8
- package/dist/desktop-guide.js +0 -40
- package/dist/desktop-guide.js.map +0 -1
- package/dist/detect.d.ts +0 -42
- package/dist/detect.js +0 -70
- package/dist/detect.js.map +0 -1
- package/dist/index.d.ts +0 -17
- package/dist/index.js.map +0 -1
- package/dist/mcp-config.d.ts +0 -17
- package/dist/mcp-config.js +0 -79
- package/dist/mcp-config.js.map +0 -1
- package/dist/platform-cred.d.ts +0 -105
- package/dist/platform-cred.js +0 -210
- package/dist/platform-cred.js.map +0 -1
- package/dist/prompt.d.ts +0 -8
- package/dist/prompt.js +0 -53
- package/dist/prompt.js.map +0 -1
- package/dist/session-hook.d.ts +0 -95
- package/dist/session-hook.js +0 -217
- package/dist/session-hook.js.map +0 -1
- package/dist/skills-sync.d.ts +0 -62
- package/dist/skills-sync.js +0 -129
- package/dist/skills-sync.js.map +0 -1
- package/dist/slug.d.ts +0 -48
- package/dist/slug.js +0 -62
- package/dist/slug.js.map +0 -1
- package/dist/tasks-init.d.ts +0 -14
- package/dist/tasks-init.js +0 -51
- package/dist/tasks-init.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @contextq/cli
|
|
2
2
|
|
|
3
|
-
One-command installer for [ContextQ](https://github.com/HENIART/contextq). It wires the ContextQ MCP server
|
|
3
|
+
One-command installer for [ContextQ](https://github.com/HENIART/contextq). It wires the ContextQ MCP server and the contextq SessionStart boot hook into a project, and gitignores the read-only render of its cloud task board — or prints a manual connect guide when the surface is Claude Desktop or Cowork, which have no project files to write into.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -15,21 +15,72 @@ npm install -g @contextq/cli
|
|
|
15
15
|
contextq init
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
## `contextq login`
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @contextq/cli login [--url <url>]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Prints a link and a short code, then waits while you approve this machine in the browser (sign in to the dashboard, open the link, confirm the code). The CLI fetches the key, checks it against `GET /api/workspaces`, and only then saves it to the platform credential file (`~/Library/Application Support/contextq/credentials` on macOS, `${XDG_CONFIG_HOME:-~/.config}/contextq/credentials` on Linux, mode 600, the previous file backed up first). You never type or paste the key. Ctrl-C, a denial, an expired code or a key that does not verify leave any stored credential byte-identical.
|
|
25
|
+
|
|
26
|
+
## `contextq local start|status|stop`
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @contextq/cli local start [--port 47321]
|
|
30
|
+
npx @contextq/cli local status
|
|
31
|
+
npx @contextq/cli local stop
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Runs ContextQ memory on this machine with no account (local mode, contract: `docs/arch/edge-local-only-contract.md`). `start` installs the pinned `@contextq/edge` into a private runtime directory, checks that Node is 22 or newer and that `better-sqlite3` loads (macOS arm64 and Linux x64 with npm prebuilt binaries; anything else gets one sentence and nothing is started), then starts `contextq-edge serve` in the background on `127.0.0.1` and records its pid. Data, keys, the local token and the runtime live in `~/Library/Application Support/contextq/local/` on macOS and `${XDG_DATA_HOME:-~/.local/share}/contextq/local/` on Linux, never in the plugin cache or the repo. `start` and `stop` are idempotent; a process on the port that this CLI did not start is reported and left alone. Nothing starts at login. If `sqlite-vec` does not load, search runs keyword-only and `start` says so.
|
|
35
|
+
|
|
36
|
+
## `contextq init --local` and `contextq attach`
|
|
37
|
+
|
|
38
|
+
`contextq init --local [--workspace <slug>] [--port <n>]` turns local mode on for the repo you are in: it runs `local start`, installs the ContextQ plugin from the public marketplace (or switches an installed one) pointed at the local server with its local token, binds `.contextq/config.json` with `mode: local`, and checks that a memory read and the boot pack answer. It needs no account, makes no authenticated call and writes no secret or machine path into tracked files; a re-run changes nothing.
|
|
39
|
+
|
|
40
|
+
`contextq attach [--url <url>]` moves local memory to an account in two journaled phases (`<state dir>/attach-journal.json`, mode 600): sign in (browser, or `--key-stdin` for automation), map each local workspace to the slug the server returns, upload every pending note with per-note acknowledgements; then lock local writes, switch the plugin and the repo binding to the cloud, and verify the cloud boot and a read before reporting success. A failure at any step rolls back to local with writes unlocked; run it again to resume (nothing is sent twice). `--leave-denied` keeps refused notes local-only, `--restart` discards an unfinished journal, `--abort` rolls back an interrupted switch.
|
|
41
|
+
|
|
18
42
|
## `contextq init`
|
|
19
43
|
|
|
20
|
-
Detects which agent surfaces the current directory
|
|
44
|
+
Detects which agent surfaces the current directory and machine are set up for (Claude Code, Codex, Gemini CLI, Cursor, Copilot CLI — often several at once) and writes the wiring each one needs.
|
|
21
45
|
|
|
22
46
|
| Option | Meaning |
|
|
23
47
|
|---|---|
|
|
24
|
-
| `--key <sk_live_...>` | API key. Falls back to `CONTEXT_API_KEY` / `CTQ_API_KEY` in the environment, then
|
|
48
|
+
| `--key <sk_live_...>` | API key. Falls back to the stored credential, then `CONTEXT_API_KEY` / `CTQ_API_KEY` in the environment, then (from an interactive terminal) the same browser approval as `contextq login`. |
|
|
25
49
|
| `--url <url>` | ContextQ API URL. Defaults to `https://app.contextq.dev`; point it at your own instance when self-hosting. |
|
|
26
50
|
| `--workspace <slug>` | Workspace the boot hook reads from. Defaults to the repo basename, sanitized. Lowercase letters, digits, `-` and `_`; must start with a letter or digit; 64 chars max. Case is folded to lowercase, since workspace slugs always are. |
|
|
27
51
|
| `--agent <slug>` | Agent identity the session boots and checkpoints under. Same defaulting and same character rules as `--workspace`. |
|
|
28
52
|
| `--embed-key` | Write the literal API key into `.mcp.json` instead of the `${CONTEXT_API_KEY}` placeholder. Opt-in on purpose: it trades a secret sitting on disk for not having to export the variable. |
|
|
29
|
-
| `--surface <s>` | Force detection to exactly one of `claude-code` or `
|
|
53
|
+
| `--surface <s>` | Force detection to exactly one of `claude-code`, `codex`, `gemini`, `cursor` or `copilot`, skipping autodetection. |
|
|
54
|
+
| `--no-plugin` | Wire Claude Code through `.mcp.json` even when Claude Code 2.1.281+ is installed. |
|
|
30
55
|
| `-h`, `--help` | Show usage. |
|
|
31
56
|
|
|
32
|
-
The API key is a ContextQ key in the form `sk_live_<40 hex
|
|
57
|
+
The API key is a ContextQ key in the form `sk_live_<40 hex>`: a new account's first key is shown once on the dashboard's Connect an Agent page, and more are created at API Keys. Every plan can create keys up to its active-key cap: Free 3, Pro 20, Team and Enterprise unlimited (keys that back MCP OAuth connectors do not count). Without `--embed-key`, the generated config references `${CONTEXT_API_KEY}` and the key never lands in a file.
|
|
58
|
+
|
|
59
|
+
### Claude Code: plugin first, `.mcp.json` as the fallback
|
|
60
|
+
|
|
61
|
+
When a `claude` binary of version 2.1.281 or newer is on `PATH`, `init` installs the ContextQ Claude Code plugin at **project** scope instead of writing `.mcp.json`: it declares the marketplace and enables `contextq@contextq-plugins` in the repo's `.claude/settings.json`, and hands the key to Claude Code through `claude plugin install --config apiKey=...`, so it lands in Claude Code's own store rather than in a file or your shell profile. The plugin carries the MCP server and the SessionStart / PreCompact / SessionEnd hooks, so `init` writes no hook of its own on this path. Finish by running `/contextq:init` in a Claude Code session to bind the repo to a workspace and project; until then the hooks stay silent and say so.
|
|
62
|
+
|
|
63
|
+
`init` falls back to `.mcp.json` when the binary is missing or older, when the install reports a failure, or when `.mcp.json` already wires contextq (installing the plugin on top would register the same MCP server twice). Running `init` in a second repo with a different key replaces the key the first repo's plugin uses, because the plugin's `apiKey` is stored once per machine, not per repo.
|
|
64
|
+
|
|
65
|
+
`init` checks the key against `GET /api/workspaces` before it writes anything. A key the server refuses with 401 or 403 is never saved and nothing is wired: from a terminal `init` runs the browser approval to replace it (also when the refused key is the one already stored), otherwise it exits 1 and names `init --key`. A browser-approved key that cannot be verified is never saved. A server that cannot be reached is not treated as a bad key: the key is saved with a `could not verify` warning, and the host configs that would carry it are skipped.
|
|
66
|
+
|
|
67
|
+
### Gemini CLI, Cursor and Copilot CLI: remote MCP in the host's own config
|
|
68
|
+
|
|
69
|
+
A host is detected when its user config directory exists: `~/.gemini/`, `~/.cursor/` (Cursor and `cursor-agent` share it), or `~/.copilot/` (`$COPILOT_HOME` when set). `init` adds a `contextq` entry pointing at `<url>/mcp` to `~/.gemini/settings.json` (`httpUrl`), `~/.cursor/mcp.json` (`url`) or `~/.copilot/mcp-config.json` (`type: http`), leaves every other key in the file alone, and sets the file to mode 600. The key goes into the `Authorization` header as a literal, because Gemini CLI does not expand variables in headers and the other two would need the variable in the GUI app's environment. An existing `contextq` entry is left as it is.
|
|
70
|
+
|
|
71
|
+
It refuses, and changes nothing, when the file is not valid JSON, or when it sits in a git work tree without being gitignored (some people track `~/.gemini/` in git), since the key would end up in a commit. It also skips all three when the key fails the connection check. Gemini CLI loads user-level MCP servers only in a trusted folder.
|
|
72
|
+
|
|
73
|
+
### The SessionStart boot hook (`--no-plugin` and Codex)
|
|
74
|
+
|
|
75
|
+
Without the plugin, `init` writes a SessionStart hook to `.claude/settings.local.json` (Claude Code) and `.codex/hooks.json` (Codex, gitignored by `init`). The hook runs `npx -y --prefer-offline @contextq/cli hook boot --format <host>`, which reads the key from the credentials file `init` wrote (or `CONTEXT_API_KEY`), resolves the repo from the session's working directory, and asks `POST /api/agent/hooks/session-start` for the boot pack: the same endpoint and output the plugin hook uses. A refused key or an unreachable server prints one line saying so instead of nothing. `init` refuses, and changes nothing, when the hook file is not valid JSON or is tracked by git. Codex runs a project hook only after you trust it: start `codex` in the repo and approve it at the hook-trust prompt.
|
|
76
|
+
|
|
77
|
+
### Gemini CLI, Cursor and Copilot CLI: user-level boot hooks
|
|
78
|
+
|
|
79
|
+
Next to the MCP entry, `init` adds a session-start hook to the host's user-level config: `hooks.SessionStart` in `~/.gemini/settings.json`, `hooks.sessionStart` in `~/.cursor/hooks.json`, and its own `~/.copilot/hooks/contextq.json` (`$COPILOT_HOME/hooks/` when set). The hook runs `npx -y --prefer-offline @contextq/cli hook boot --format <host> --require-config`: it takes the repo from the session's working directory and stays silent in any repo without a `.contextq/config.json`, so one user-level hook serves every bound repo and nothing else. `init` writes that `.contextq/config.json` for the current repo when it is missing (commit it). The same refusals apply as for the MCP entry (invalid JSON, a git-tracked config). Cursor runs `sessionStart` without waiting for it, so the first turn may start before the pack arrives.
|
|
80
|
+
|
|
81
|
+
### Codex: remote MCP in the project's `.codex/config.toml`
|
|
82
|
+
|
|
83
|
+
`init --surface codex` (or a detected Codex) adds `[mcp_servers.contextq]` with `url = "<url>/mcp"` and an `[mcp_servers.contextq.http_headers]` table carrying `Authorization = "Bearer <key>"` to the repo's `.codex/config.toml`, appends `.codex/config.toml` to `.gitignore`, and sets the file to mode 600. Existing content is kept byte for byte and an existing `contextq` entry is left alone. It refuses, and changes nothing, when the file is not valid TOML, when `mcp_servers` is an inline table the new block cannot extend, or when the file is tracked by git. Codex reads a project config only in a trusted project: run `codex` once in the repo and accept the trust prompt, then `codex mcp list` shows `contextq`. If no surface ends up with an MCP connection, `init` says so and exits 1 instead of printing `Done`.
|
|
33
84
|
|
|
34
85
|
## `contextq skills sync <dir>`
|
|
35
86
|
|
|
@@ -50,3 +101,7 @@ Node 18 or newer, and a reachable ContextQ instance — the hosted one at `app.c
|
|
|
50
101
|
## License
|
|
51
102
|
|
|
52
103
|
MIT. Source lives in the [contextq](https://github.com/HENIART/contextq) repository under `cli/`.
|
|
104
|
+
|
|
105
|
+
## Releasing
|
|
106
|
+
|
|
107
|
+
Whoever publishes runs `bash scripts/check-npm-pack.sh cli` from the repo root and publishes the `tarball=` file it prints, never a bare `npm publish` in this directory: the check refuses sourcemaps, TypeScript source and tests in the real tarball (T922).
|