@hlix/cli 0.2.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.
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ import "./chunk-FYS2JH42.js";
3
+
4
+ // package.json
5
+ var name = "@hlix/cli";
6
+ var version = "0.2.0";
7
+ var license = "Apache-2.0";
8
+ var description = "Command-line interface for the hlix control plane, built on @hlix/sdk.";
9
+ var keywords = [
10
+ "hlix",
11
+ "cli",
12
+ "agents"
13
+ ];
14
+ var homepage = "https://github.com/hlix-ai/hlix#readme";
15
+ var repository = {
16
+ type: "git",
17
+ url: "git+https://github.com/hlix-ai/hlix.git",
18
+ directory: "packages/cli"
19
+ };
20
+ var bugs = {
21
+ url: "https://github.com/hlix-ai/hlix/issues"
22
+ };
23
+ var type = "module";
24
+ var main = "./dist/index.js";
25
+ var bin = {
26
+ hlix: "./dist/index.js"
27
+ };
28
+ var files = [
29
+ "dist",
30
+ "skills",
31
+ "THIRD_PARTY_NOTICES"
32
+ ];
33
+ var engines = {
34
+ node: ">=20"
35
+ };
36
+ var publishConfig = {
37
+ access: "public"
38
+ };
39
+ var scripts = {
40
+ build: "tsup",
41
+ test: "bun test --isolate --timeout 20000",
42
+ typecheck: "tsc --noEmit",
43
+ prepublishOnly: "bun run typecheck && bun run build && bun test src/boundary.test.ts src/skill.test.ts src/binary.test.ts src/readme.test.ts"
44
+ };
45
+ var devDependencies = {
46
+ "@hlix/sdk": "^0.2.0",
47
+ ignore: "7.0.5",
48
+ tsup: "^8.5.0",
49
+ typescript: "^5.7.2",
50
+ "@types/bun": "latest"
51
+ };
52
+ var package_default = {
53
+ name,
54
+ version,
55
+ license,
56
+ description,
57
+ keywords,
58
+ homepage,
59
+ repository,
60
+ bugs,
61
+ type,
62
+ main,
63
+ bin,
64
+ files,
65
+ engines,
66
+ publishConfig,
67
+ scripts,
68
+ devDependencies
69
+ };
70
+ export {
71
+ bin,
72
+ bugs,
73
+ package_default as default,
74
+ description,
75
+ devDependencies,
76
+ engines,
77
+ files,
78
+ homepage,
79
+ keywords,
80
+ license,
81
+ main,
82
+ name,
83
+ publishConfig,
84
+ repository,
85
+ scripts,
86
+ type,
87
+ version
88
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@hlix/cli",
3
+ "version": "0.2.0",
4
+ "license": "Apache-2.0",
5
+ "description": "Command-line interface for the hlix control plane, built on @hlix/sdk.",
6
+ "keywords": [
7
+ "hlix",
8
+ "cli",
9
+ "agents"
10
+ ],
11
+ "homepage": "https://github.com/hlix-ai/hlix#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/hlix-ai/hlix.git",
15
+ "directory": "packages/cli"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/hlix-ai/hlix/issues"
19
+ },
20
+ "type": "module",
21
+ "main": "./dist/index.js",
22
+ "bin": {
23
+ "hlix": "./dist/index.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "skills",
28
+ "THIRD_PARTY_NOTICES"
29
+ ],
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "test": "bun test --isolate --timeout 20000",
39
+ "typecheck": "tsc --noEmit",
40
+ "prepublishOnly": "bun run typecheck && bun run build && bun test src/boundary.test.ts src/skill.test.ts src/binary.test.ts src/readme.test.ts"
41
+ },
42
+ "devDependencies": {
43
+ "@hlix/sdk": "^0.2.0",
44
+ "ignore": "7.0.5",
45
+ "tsup": "^8.5.0",
46
+ "typescript": "^5.7.2",
47
+ "@types/bun": "latest"
48
+ }
49
+ }
@@ -0,0 +1,194 @@
1
+ ---
2
+ name: hlix
3
+ description: Import and configure local projects, then inspect Hlix projects and tasks from the terminal. Use when asked to scan or import a folder, initialize it, list projects, look up a task, read review evidence, or watch task status.
4
+ ---
5
+
6
+ # hlix CLI
7
+
8
+ Project setup and inspection for a Hlix workspace. Every command below is registered in
9
+ the CLI — `skill.test.ts` compares this list against the command table and fails
10
+ if they disagree, so this file cannot advertise something that does not exist.
11
+
12
+ ## Authentication
13
+
14
+ ```bash
15
+ hlix auth login --workspace <id> [--base-url <url>]
16
+ hlix auth status [--json] # which credential, from where, does it work
17
+ hlix auth logout [--yes] [--json] # remove the stored credential file
18
+ ```
19
+
20
+ Reads the key from a hidden terminal prompt, verifies it against the API
21
+ **before** storing it, then writes it atomically to
22
+ `~/.config/hlix/credentials.json` with mode 0600. The key is never printed back.
23
+
24
+ `HLIX_API_KEY` overrides the stored file; `HLIX_BASE_URL` and
25
+ `HLIX_WORKSPACE_ID` set the target and workspace. Use those in CI rather than
26
+ running a login step.
27
+
28
+ `--workspace` is required at login: an API key authenticates a user but names
29
+ no workspace, so the caller states one. `hlix auth login` verifies the key
30
+ against a real call **before** writing it, so a key that does not work is never
31
+ stored.
32
+
33
+ `auth status` names the credential's **source** — the environment or the stored
34
+ file — and probes it against the API. It never prints the key, not even a
35
+ prefix. `auth logout` removes the credential **file** only; a key supplied
36
+ through `HLIX_API_KEY` is reported and left alone, because it belongs to the
37
+ shell that set it. Removal asks for confirmation unless `--yes` is given, and
38
+ refuses any path that is not a credential document this CLI wrote.
39
+
40
+ ## Where a command points
41
+
42
+ Every command resolves its workspace and API through one chain, highest first:
43
+
44
+ 1. an explicit flag (`--workspace`, `--base-url`)
45
+ 2. the `HLIX_*` environment
46
+ 3. the nearest `.hlix/config.json`, walking up from the working directory
47
+ 4. the stored credential
48
+ 5. the built-in default (`https://server.hlix.ai`)
49
+
50
+ The folder's binding therefore outranks the machine-wide credential: a folder
51
+ bound to workspace A is queried against workspace A even when the last login
52
+ named workspace B. A flag or environment variable that **contradicts** the
53
+ folder's binding is not resolved by precedence — it exits `workspace_mismatch`
54
+ naming both, because guessing which one was meant is how a push reaches the
55
+ wrong tenant. `hlix auth login` is deliberately outside the chain, so signing in
56
+ to a second workspace from inside a bound folder still works.
57
+
58
+ `--cwd <dir>` makes any command operate on another directory, including the
59
+ binding lookup. `hlix status` prints the resolved answer and the source that
60
+ decided it.
61
+
62
+ ## Commands
63
+
64
+ ```bash
65
+ hlix status [--json] # workspace, binding, local and cloud drift
66
+ hlix projects list [--json] # projects in the workspace
67
+ hlix projects get [project-id] [--json]
68
+ hlix init [folder] [--json] # create committed project configuration
69
+ hlix import [folder] [--dry-run] [--env-file <path>] [--history preserve] [--yes] [--json]
70
+ hlix sync [--dry-run] [--json] # push or pull when only one side changed
71
+ hlix pull [--force] [--yes] [--dry-run] [--json]
72
+ hlix push [--dry-run] [--json] # compare-and-swap a new immutable revision
73
+ hlix skill import <SKILL.md|folder> [--name <slug>] [--json]
74
+ hlix agent import <markdown-file> [--name <name>] [--runtime <runtime>] [--profile <profile>] [--json]
75
+ hlix mcp import <.mcp.json> [--server <name>] [--allow-stdio] [--json]
76
+ hlix tasks list [--project <id>] [--status <status>] [--json]
77
+ hlix tasks get <task-id> [--json] # one task
78
+ hlix tasks review <task-id> [--json] # the verified review evidence for a task
79
+ hlix tasks watch <task-id> [--json] # stream status changes until the task ends
80
+ ```
81
+
82
+ `hlix --help` lists them; `hlix <command> --help` shows its usage. Every command
83
+ also accepts `--cwd <dir>`.
84
+
85
+ `hlix status` answers "where am I" in one screen: the resolved workspace and API
86
+ with the source that decided each, the folder's binding and local revision, and
87
+ whether the working tree or the cloud head has moved since the last sync. It
88
+ reports rather than judges: a missing credential, an unreadable project file, a
89
+ contradicting override and an unreachable API are all lines in the output, and
90
+ the command itself always exits 0. An argument error — an unknown flag, a stray
91
+ positional, a `--cwd` that is not a directory — is still exit 2, because it is
92
+ rejected before `status` runs at all.
93
+
94
+ `tasks list` and `projects get` default to the project this folder is bound to,
95
+ so both are usable with no arguments inside an imported project.
96
+
97
+ Run `hlix import --dry-run` first. The report names secret **keys**, quarantined
98
+ agent/skill/MCP resources, and Git-history findings, but never secret values.
99
+ Hlix collects every project-local dotenv and credential file. It applies the
100
+ standard development dotenv precedence automatically and preserves every other
101
+ profile encrypted; `--env-file` is an explicit override.
102
+ The default history policy aborts on possible historical secrets. Explicit
103
+ `--history preserve` keeps the full Git history after showing the risk.
104
+ Current environment values are sent only in the authenticated finalization
105
+ request and stored encrypted; they are never placed in the Git bundle.
106
+
107
+ When the scan finds cloud setup commands, protected files, or quarantined
108
+ resources, interactive imports ask for one explicit trust decision before any
109
+ project is created or uploaded. Non-interactive and `--json` callers must first
110
+ review `--dry-run`, then pass `--yes`; it never bypasses a scan blocker. A
111
+ declined prompt exits as `cancelled`, while a caller that cannot prompt exits
112
+ as `approval_required`.
113
+
114
+ Agent, skill, and MCP files found during a project scan stay quarantined until
115
+ one of the explicit import commands above is run. Skill content and agents are
116
+ scoped to the bound project. MCP imports send environment key names only;
117
+ values remain in encrypted project secrets and the generated cloud config uses
118
+ `${KEY}` placeholders, including remote authentication headers such as
119
+ `Authorization: Bearer ${TOKEN}`. Literal-only headers are refused. Remote MCP URLs must use public HTTPS. Stdio servers
120
+ require `--allow-stdio` and run only through a validated direct executable,
121
+ never a shell.
122
+
123
+ `sync` never guesses through a two-sided conflict. If only local changed it
124
+ pushes; if only cloud changed it pulls; if both changed it exits with
125
+ `conflict`.
126
+
127
+ `push`, `pull` and `sync` accept `--dry-run`: it prints the divergence — each
128
+ side's generation, and how many files are local-only, cloud-only or differing —
129
+ takes no action, and reports the verdict the real command would reach. A dry run
130
+ that would end in `conflict` exits 1, as `import --dry-run` does for a blocker.
131
+
132
+ `pull --force` is the destructive override, and it now asks before replacing
133
+ local files: `--force` states "replace my changes", `--yes` states "do not ask".
134
+ A `--json` or non-interactive caller cannot answer, so it exits
135
+ `approval_required` pointing at `--dry-run`; a declined prompt exits `cancelled`.
136
+ `--force` without local changes replaces nothing and does not prompt.
137
+
138
+ ## Machine output
139
+
140
+ `--json` is a stable contract. Human output is not — do not parse it.
141
+
142
+ ```json
143
+ {
144
+ "schemaVersion": 1,
145
+ "command": "projects list",
146
+ "data": [ /* documented command result */ ]
147
+ }
148
+ ```
149
+
150
+ Failures use the same envelope with `error` instead of `data`:
151
+
152
+ ```json
153
+ {
154
+ "schemaVersion": 1,
155
+ "command": "tasks get",
156
+ "error": { "code": "not_found", "message": "Task not found", "status": 404 }
157
+ }
158
+ ```
159
+
160
+ Branch on `error.code`, never on `error.message`. Codes: `unauthenticated`,
161
+ `forbidden`, `not_found`, `conflict`, `invalid_request`, `bad_request`,
162
+ `rate_limited`, `not_implemented`, `server_error`, `unreachable`,
163
+ `missing_argument`, `invalid_usage`, `approval_required`, `cancelled`, `unknown_command`,
164
+ `workspace_mismatch`, `not_initialized`, `scan_blocked`, `already_imported`,
165
+ `workspace_required`, `invalid_base_url`, `missing_credential`, `unknown`.
166
+
167
+ That list is the complete set — `skill.test.ts` compares it against every code
168
+ the sources can emit in BOTH directions, so a code the CLI can return cannot go
169
+ undocumented and a documented code cannot be one the CLI never returns.
170
+
171
+ Transport-only inspection commands pass the API response through unchanged.
172
+ Local project commands such as `import`, `push`, `pull`, and `sync` return the
173
+ documented local result shape. The CLI selects columns for the human table only.
174
+
175
+ `tasks watch --json` is the one exception to "one document": it emits **one
176
+ envelope per line** (JSONL), because a live stream cannot be a single JSON
177
+ document. Read it line by line.
178
+
179
+ ## Exit codes
180
+
181
+ | Code | Meaning |
182
+ | --- | --- |
183
+ | 0 | Success |
184
+ | 1 | The command ran and failed |
185
+ | 2 | Usage error — unknown command, bad flags, missing argument |
186
+ | 3 | Authentication or permission failure |
187
+
188
+ ## Not available
189
+
190
+ - **No execution commands.** There is deliberately no way to start a run,
191
+ execute a cycle or dispatch a task from this CLI.
192
+ - **No `tasks logs`.** The log endpoint is not part of the published API
193
+ contract, and there is no log stream to follow. `tasks watch` streams task
194
+ *status*, which is a different thing and is named accordingly.