@khotan/cli 0.1.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.
Files changed (3) hide show
  1. package/README.md +215 -0
  2. package/dist/khotan.js +2491 -0
  3. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # Khotan CLI & MCP server
2
+
3
+ `@khotan/cli` is the first-party command-line interface and Model Context
4
+ Protocol (MCP) server for the Khotan API. Both surfaces are thin adapters over
5
+ the public `/api/v1` HTTP API, driven by the shared capability catalog in
6
+ [`@khotan/core`](../khotan-core). They add nothing the API cannot do — they make
7
+ the same operations ergonomic for humans (CLI) and agents (MCP).
8
+
9
+ ## Install & run
10
+
11
+ The published CLI is a self-contained Node.js binary (no Bun required). Install
12
+ or invoke it with standard npm tooling:
13
+
14
+ ```bash
15
+ npx @khotan/cli --help # zero-install
16
+ npm i -g @khotan/cli # global `khotan` binary
17
+ # or: bun add -g @khotan/cli / pnpm add -g @khotan/cli
18
+ khotan --help
19
+ ```
20
+
21
+ From this repository (contributors), run it from source on Bun:
22
+
23
+ ```bash
24
+ bun run khotan -- --help # via the root script
25
+ bun packages/khotan-cli/src/bin/khotan.ts --help # directly
26
+ ```
27
+
28
+ ## Scaffold a workspace
29
+
30
+ `khotan init` writes Khotan agent integration into the current directory so your
31
+ own agents (Cursor, Devin, …) can drive setup. It is non-destructive and
32
+ re-runnable, and never writes secrets.
33
+
34
+ ```bash
35
+ khotan init # Cursor: .cursor/mcp.json + .cursor/rules/khotan.mdc
36
+ khotan init --client generic # root mcp.json + khotan-agents.md
37
+ khotan init --force # regenerate managed assets, overwriting edits
38
+ khotan init --json # machine-readable summary on stdout
39
+ ```
40
+
41
+ It writes an MCP config wired to `khotan mcp serve` (credentials referenced by
42
+ `KHOTAN_API_URL` / `KHOTAN_API_KEY`, placeholders only) plus agent guidance. The
43
+ MCP config merges into an existing one, preserving any other servers. Authenticate
44
+ separately with `khotan auth set-key` or environment variables — never commit a key.
45
+
46
+ ## Authentication & profiles
47
+
48
+ The CLI authenticates with an organization-scoped **API key**. Credentials are
49
+ stored in an owner-only file at `${XDG_CONFIG_HOME:-~/.config}/khotan/profiles.json`
50
+ (`0600`, in a `0700` directory). You can keep several named profiles.
51
+
52
+ ### Store an existing API key
53
+
54
+ Create a key in the dashboard, then:
55
+
56
+ ```bash
57
+ khotan auth set-key --api-url https://app.example.com --api-key khk_live_...
58
+ khotan whoami # verifies the key via GET /api/v1/me
59
+ ```
60
+
61
+ ### Exchange credentials for a key
62
+
63
+ ```bash
64
+ khotan login \
65
+ --api-url https://app.example.com \
66
+ --email you@example.com \
67
+ --password '••••••' \
68
+ --organization-id org_123
69
+ ```
70
+
71
+ `login` calls `POST /api/v1/api-keys`, stores the minted key once, and verifies
72
+ it. The key itself is never printed to stdout.
73
+
74
+ ### Profiles
75
+
76
+ ```bash
77
+ khotan auth set-key --profile staging --api-url https://staging.example.com --api-key ...
78
+ khotan auth use staging # switch the active profile
79
+ khotan auth list # list profiles (never prints keys)
80
+ khotan apps list --profile staging # one-off override
81
+ ```
82
+
83
+ ### Environment variables (CI & agents)
84
+
85
+ Environment variables take precedence over stored profile values, so no on-disk
86
+ state is needed in CI or sandboxes:
87
+
88
+ | Variable | Purpose |
89
+ | ----------------- | ----------------------------------------- |
90
+ | `KHOTAN_API_URL` | API origin (e.g. `https://app.example.com`) |
91
+ | `KHOTAN_API_KEY` | Organization-scoped API key |
92
+ | `KHOTAN_PROFILE` | Select a stored profile by name |
93
+
94
+ ```bash
95
+ export KHOTAN_API_URL=https://app.example.com
96
+ export KHOTAN_API_KEY=khk_live_...
97
+ khotan apps list --json | jq '.apps[].id'
98
+ ```
99
+
100
+ ## Command surface
101
+
102
+ Commands are grouped by domain and derived from the capability catalog, so the
103
+ documented surface and the executable surface cannot drift. Run `khotan help` or
104
+ `khotan <command> --help` for details.
105
+
106
+ | Domain | Examples |
107
+ | --------- | -------- |
108
+ | Apps | `apps list`, `apps get <id>`, `apps create --name web --env KEY=VALUE`, `apps delete <id>`, `apps redeploy <id>` |
109
+ | App env | `apps env list <id>`, `apps env set <id> <KEY> --value V`, `apps env reveal <id> <KEY>`, `apps env unset <id> <KEY>`, `apps env bulk-set <id> --var A=1 --var B=2` |
110
+ | Pipelines | same shape as apps under `pipelines …` |
111
+ | Databases | `databases list`, `databases create --name db`, `databases connection <id>`, `databases rotate-credentials <id>`, `databases delete <id>` |
112
+ | Files | `files list`, `files get <id>`, `files upload <path>`, `files download <id> --output <path>`, `files update <id> --name new.txt`, `files delete <id>` |
113
+ | Folders | `folders list`, `folders create --name docs`, `folders rename <id> --name new`, `folders delete <id>` |
114
+ | Context | `context list`, `context get <slug>`, `context raw <slug>`, `context create --title T --kind knowledge --content '...'`, `context update <slug> --expected-revision 3 --content '...'`, `context delete <slug>` |
115
+
116
+ ### Output modes
117
+
118
+ - Human-readable tables/detail by default.
119
+ - `--json` emits the API-shaped JSON to **stdout**.
120
+ - Results go to **stdout**; diagnostics, prompts, and progress go to **stderr**,
121
+ so `khotan ... --json | jq` stays clean.
122
+
123
+ ### Safety
124
+
125
+ Each capability has a safety class (`read`, `write`, `destructive`, `secret`):
126
+
127
+ - **Destructive** commands (`delete`, `env unset`) prompt for confirmation in a
128
+ terminal and **refuse** in non-interactive sessions unless you pass `--yes`.
129
+ - **Secret** values (`env reveal`, `databases connection`,
130
+ `databases rotate-credentials`) are only available via explicit commands and
131
+ are never included in list/table output.
132
+
133
+ ### File transfer
134
+
135
+ Uploads and downloads move bytes directly between your machine and object
136
+ storage using presigned URLs:
137
+
138
+ ```bash
139
+ khotan files upload ./report.pdf --folder-path /reports/2026
140
+ khotan files download file_123 --output ./report.pdf
141
+ ```
142
+
143
+ ## MCP server
144
+
145
+ `khotan mcp serve` starts a local stdio MCP server that reuses the same profile,
146
+ environment overrides, API client, and catalog as the CLI. It advertises
147
+ **tools** (operations) and **resources** (URI-addressed read data) during
148
+ initialization.
149
+
150
+ - Operations become tools (e.g. `khotan_apps_create`). Destructive tools require
151
+ `{ "confirm": true }`; secret tools are labelled `[secret]`. The password-bearing
152
+ credential exchange is **not** exposed as a tool.
153
+ - Durable read data is exposed as resource templates: `khotan://apps/{appId}`,
154
+ `khotan://pipelines/{pipelineId}`, `khotan://databases/{databaseId}`,
155
+ `khotan://files/{fileId}`, `khotan://context/{slug}`.
156
+ - Secret-bearing values (env var values, connection URIs) are never resources.
157
+ - stdout carries JSON-RPC only; all logs go to stderr.
158
+
159
+ Example MCP client configuration:
160
+
161
+ ```json
162
+ {
163
+ "mcpServers": {
164
+ "khotan": {
165
+ "command": "khotan",
166
+ "args": ["mcp", "serve"],
167
+ "env": {
168
+ "KHOTAN_API_URL": "https://app.example.com",
169
+ "KHOTAN_API_KEY": "khk_live_..."
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ ## Catalog ↔ OpenAPI consistency
177
+
178
+ `@khotan/core` validates that every catalog operation maps to a real `/api/v1`
179
+ operation (method, path, operationId) using a snapshot of the OpenAPI document at
180
+ [`packages/khotan-core/src/catalog/__fixtures__/openapi.snapshot.json`](../khotan-core/src/catalog/__fixtures__/openapi.snapshot.json).
181
+
182
+ Regenerate the snapshot when the API surface changes:
183
+
184
+ ```bash
185
+ curl -s "$KHOTAN_API_URL/api/v1/openapi.json" \
186
+ | jq '{openapi, info, paths: (.paths | map_values(map_values({operationId})))}' \
187
+ > packages/khotan-core/src/catalog/__fixtures__/openapi.snapshot.json
188
+ ```
189
+
190
+ ## Development
191
+
192
+ ```bash
193
+ bun run khotan:typecheck # typecheck both packages
194
+ bun run khotan:test # run all Khotan tests
195
+ bun run khotan -- <args> # run the CLI from source
196
+ bun run khotan:build # bundle the publishable dist/khotan.js (Node target)
197
+ ```
198
+
199
+ The build bundles `@khotan/core` into a single Node-executable ESM file at
200
+ `packages/khotan-cli/dist/khotan.js`. `@khotan/core` stays a private workspace
201
+ package; only the bundled `@khotan/cli` is published, so the published manifest
202
+ has no `workspace:*` dependencies.
203
+
204
+ ## Release
205
+
206
+ Versioning and publishing use [changesets](https://github.com/changesets/changesets):
207
+
208
+ ```bash
209
+ bun run changeset # author a changeset describing the change
210
+ bun run release:version # apply changesets: bump version + update changelog
211
+ bun run release:publish # build, then publish @khotan/cli to npm (public)
212
+ ```
213
+
214
+ `prepublishOnly` rebuilds the bundle, so the published `bin` always matches
215
+ source. Publishing requires the `@khotan` npm org and a publish token.