@qodly/gentrace 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.
- package/README.md +324 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +149 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.js +69 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +162 -0
- package/dist/commands/hooks.d.ts +2 -0
- package/dist/commands/hooks.js +128 -0
- package/dist/commands/install-git-ai.d.ts +1 -0
- package/dist/commands/install-git-ai.js +41 -0
- package/dist/commands/publish.d.ts +1 -0
- package/dist/commands/publish.js +224 -0
- package/dist/commands/skip.d.ts +3 -0
- package/dist/commands/skip.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/config.js +50 -0
- package/dist/lib/debug.d.ts +8 -0
- package/dist/lib/debug.js +36 -0
- package/dist/lib/exec.d.ts +14 -0
- package/dist/lib/exec.js +26 -0
- package/dist/lib/git-ai-ingest-context.d.ts +23 -0
- package/dist/lib/git-ai-ingest-context.js +81 -0
- package/dist/lib/git-ai.d.ts +35 -0
- package/dist/lib/git-ai.js +105 -0
- package/dist/lib/git.d.ts +21 -0
- package/dist/lib/git.js +67 -0
- package/dist/lib/prompt.d.ts +2 -0
- package/dist/lib/prompt.js +45 -0
- package/dist/lib/skip.d.ts +6 -0
- package/dist/lib/skip.js +19 -0
- package/dist/lib/telemetry-post.d.ts +14 -0
- package/dist/lib/telemetry-post.js +60 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# Gentrace CLI (`gentrace`)
|
|
2
|
+
|
|
3
|
+
Command-line bridge between **[git-ai](https://github.com/git-ai/git-ai)** and the **Gentrace** API: after each commit it can send **`commit_attribution`** telemetry (AI vs human line stats, diff context, and optional prompts) to `POST /v1/telemetry`.
|
|
4
|
+
|
|
5
|
+
Package name on npm: **`@qodly/gentrace`** · binary: **`gentrace`**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
| Requirement | Purpose |
|
|
12
|
+
|-------------|---------|
|
|
13
|
+
| **Git** | Repository detection, hooks, diff, commit metadata. |
|
|
14
|
+
| **[git-ai](https://github.com/git-ai/git-ai)** | Records attribution for commits; the CLI reads git-ai output to build telemetry. |
|
|
15
|
+
| **[Bun](https://bun.sh)** | The published `gentrace` entrypoint (`dist/cli.js`) uses `#!/usr/bin/env bun` — install Bun and ensure it is on your `PATH`. |
|
|
16
|
+
| **Gentrace account** | Sign in to your Gentrace dashboard, create an **access token** with permission to ingest telemetry (see below). |
|
|
17
|
+
|
|
18
|
+
Optional:
|
|
19
|
+
|
|
20
|
+
- **curl** / **bash** — used by `gentrace install-git-ai` for the official git-ai installer on macOS/Linux.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
### From npm (recommended)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @qodly/gentrace
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Verify:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gentrace --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### One-off run with npx
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx @qodly/gentrace@latest doctor
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### From this monorepo (contributors)
|
|
45
|
+
|
|
46
|
+
From the repository root (requires [Bun](https://bun.sh)):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bun run --filter @qodly/gentrace install:global
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or from `apps/cli`:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd apps/cli && bun run install:global
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That script builds the CLI and links the `gentrace` command globally. See `scripts/install-global.sh` for flags (e.g. `--no-build`).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Getting started
|
|
63
|
+
|
|
64
|
+
### 1. Install git-ai
|
|
65
|
+
|
|
66
|
+
If `git-ai` is not installed:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
gentrace install-git-ai
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This runs the installer from [usegitai.com](https://usegitai.com). On Windows (native), the command prints a PowerShell one-liner; on WSL/macOS/Linux it offers the `curl … \| bash` flow. After installation, reload your shell or add `~/.git-ai/bin` to `PATH` if the binary is not found.
|
|
73
|
+
|
|
74
|
+
Confirm:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
gentrace doctor
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`doctor` checks `git`, `git-ai`, API configuration, and API reachability.
|
|
81
|
+
|
|
82
|
+
### 2. Create an API token in the dashboard
|
|
83
|
+
|
|
84
|
+
1. Open your Gentrace web app (for example `https://gentrace.4d-ps.com`) and sign in.
|
|
85
|
+
2. Go to **Settings** (personal access tokens), e.g. `https://gentrace.4d-ps.com/settings`.
|
|
86
|
+
3. Create **New access token**.
|
|
87
|
+
4. Grant at least **`telemetry:ingest`** (or **`*`**) so `gentrace publish` can send batches. Tokens used only for ingest often include `telemetry:ingest`; `gentrace doctor` also calls `GET /v1/auth/permissions`, which requires sufficient IAM on the token (see doctor output if something fails).
|
|
88
|
+
|
|
89
|
+
Copy the token **once** — it may not be shown again.
|
|
90
|
+
|
|
91
|
+
### 3. Configure the API key (and optional API URL)
|
|
92
|
+
|
|
93
|
+
**Interactive** (saved to `~/.config/gentrace/config.json`):
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
gentrace doctor
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If no key is set, `doctor` can prompt for it when a TTY is available.
|
|
100
|
+
|
|
101
|
+
**Explicit**:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
gentrace config set apiKey 'YOUR_TOKEN_HERE'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Default API base URL is `https://gentrace.4d-ps.com/api` (paths such as `/v1/telemetry` are appended to this base). Override if needed:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
gentrace config set apiUrl 'https://your-host.example.com/api'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or use environment variables (highest precedence for URL/key):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
export GENTRACE_API_KEY='YOUR_TOKEN_HERE'
|
|
117
|
+
export GENTRACE_API_URL='https://your-host.example.com/api'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 4. Verify the setup
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
gentrace doctor
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
You should see checks for git, git-ai, API key, HTTP health, and token IAMs for telemetry ingest.
|
|
127
|
+
|
|
128
|
+
### 5. Install the post-commit hook (per repository)
|
|
129
|
+
|
|
130
|
+
In each Git repo where you want automatic publishes after every commit:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
cd /path/to/your/repo
|
|
134
|
+
gentrace hooks install
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Optional second argument: path to the repo root:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gentrace hooks install /path/to/your/repo
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The hook runs **`gentrace publish --daemon`** in the background (`nohup`) so commits are not blocked. Logs go to `.git/gentrace-publish.log`.
|
|
144
|
+
|
|
145
|
+
Ensure **`gentrace`** is on `PATH` when Git runs hooks (same as in your interactive shell), or set **`GENTRACE_BIN`** to the full path of the binary in the environment used by GUI Git clients / CI if needed.
|
|
146
|
+
|
|
147
|
+
### 6. Manual publish (optional test)
|
|
148
|
+
|
|
149
|
+
From a repo with git-ai data for `HEAD`:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
gentrace publish
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Optional working directory:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
gentrace publish /path/to/repo
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Command reference
|
|
164
|
+
|
|
165
|
+
Global notes:
|
|
166
|
+
|
|
167
|
+
- **`gentrace --help`** / **`-h`** — short usage summary.
|
|
168
|
+
- **`gentrace --version`** / **`-V`** — CLI version string.
|
|
169
|
+
- **Verbose logging** — place **`--verbose`**, **`--debug`**, or **`-v`** before the subcommand (or on supported commands such as `publish` / `doctor`) to log HTTP details to stderr. Same effect: **`GENTRACE_DEBUG=1`** (or `true`).
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### `gentrace publish`
|
|
174
|
+
|
|
175
|
+
Collects Git AI attribution and git metadata for **HEAD** in a repository, builds a telemetry batch, and **POST**s it to **`{apiUrl}/v1/telemetry`**.
|
|
176
|
+
|
|
177
|
+
**Usage**
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
gentrace publish [--verbose|--debug|-v] [--daemon|--background] [cwd]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
| Argument / flag | Description |
|
|
184
|
+
|-----------------|-------------|
|
|
185
|
+
| **`cwd`** | Optional path to the repository root (defaults to current working directory). |
|
|
186
|
+
| **`--daemon`** / **`--background`** | After a delay, run collection in a style suited to hooks: waits **`GENTRACE_PUBLISH_DELAY_MS`** ms if set, otherwise **2500** ms, so git-ai can finish writing stats. Then collects and sends. |
|
|
187
|
+
| **Verbose flags** | Extra stderr logs (URL, redacted headers, body preview, response). |
|
|
188
|
+
|
|
189
|
+
**Behavior highlights**
|
|
190
|
+
|
|
191
|
+
- Skips the run if the repository id (origin URL, or path fallback) matches **`skipRepositories`** (see `gentrace skip`).
|
|
192
|
+
- Requires **git-ai** on PATH; exits with a hint to run **`gentrace install-git-ai`** if missing.
|
|
193
|
+
- Resolves API key from **`GENTRACE_API_KEY`** or config; may prompt once in a TTY.
|
|
194
|
+
- **200**: prints accepted count when present in JSON body.
|
|
195
|
+
- **409**: treated as already recorded (“Commit … already recorded”).
|
|
196
|
+
- **401** / **403**: auth error; suggests checking the token and **`telemetry:ingest`**.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### `gentrace doctor`
|
|
201
|
+
|
|
202
|
+
Validates local tools and API connectivity.
|
|
203
|
+
|
|
204
|
+
**Usage**
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
gentrace doctor [--verbose|--debug|-v]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Checks (in order)**
|
|
211
|
+
|
|
212
|
+
1. **`git`** on PATH.
|
|
213
|
+
2. **`git-ai`** on PATH.
|
|
214
|
+
3. **API key** — from env or config; may prompt and save in a TTY.
|
|
215
|
+
4. **`GET {apiUrl}/health`** — unauthenticated liveness.
|
|
216
|
+
5. **`GET {apiUrl}/v1/auth/permissions`** with **`X-API-Key`** — confirms token works and IAMs include **`telemetry:ingest`** or **`*`** for publish.
|
|
217
|
+
|
|
218
|
+
Exits **`0`** if all checks pass, **`1`** otherwise.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `gentrace install-git-ai`
|
|
223
|
+
|
|
224
|
+
If git-ai is already installed, prints the version and exits.
|
|
225
|
+
|
|
226
|
+
Otherwise (on Unix/WSL) asks for confirmation, then runs:
|
|
227
|
+
|
|
228
|
+
`curl -sSL https://usegitai.com/install.sh | bash`
|
|
229
|
+
|
|
230
|
+
On Windows (non-WSL), prints the recommended PowerShell install command instead.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### `gentrace hooks install` / `gentrace hooks uninstall`
|
|
235
|
+
|
|
236
|
+
Manage a **post-commit** shell hook under **`.git/hooks/post-commit`**.
|
|
237
|
+
|
|
238
|
+
**Usage**
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
gentrace hooks install [cwd]
|
|
242
|
+
gentrace hooks uninstall [cwd]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| Subcommand | Description |
|
|
246
|
+
|------------|-------------|
|
|
247
|
+
| **`install`** | Ensures `.git/hooks` exists, then appends or creates a block marked `# gentrace-cli post-commit hook` that runs **`nohup gentrace publish --daemon`** (with **`GENTRACE_BIN`** defaulting to `gentrace`). If an older gentrace hook exists, it may be replaced with the async version. May prompt for API key once. |
|
|
248
|
+
| **`uninstall`** | Removes only the gentrace-marked section; deletes the file if nothing else remains (except a bare `#!/bin/sh`). |
|
|
249
|
+
|
|
250
|
+
**`cwd`** — optional path to the repo root (default: current directory).
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### `gentrace config`
|
|
255
|
+
|
|
256
|
+
Read or write **`~/.config/gentrace/config.json`**.
|
|
257
|
+
|
|
258
|
+
**Usage**
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
gentrace config # print full JSON (apiKey masked)
|
|
262
|
+
gentrace config get [key] # get one key or all if omitted in some forms
|
|
263
|
+
gentrace config set <key> <value> # set scalar keys (see below)
|
|
264
|
+
gentrace config unset <key> # reset key to default
|
|
265
|
+
gentrace config <key> # same as: config get <key>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Keys**
|
|
269
|
+
|
|
270
|
+
| Key | Type | Description |
|
|
271
|
+
|-----|------|-------------|
|
|
272
|
+
| **`apiUrl`** | string | API base URL (default includes `/api` path; see source `DEFAULTS`). |
|
|
273
|
+
| **`apiKey`** | string | Secret token (`get` shows a masked value). |
|
|
274
|
+
| **`includePrompts`** | boolean | Set with `gentrace config set includePrompts true` or `false` — when true, publish may attach prompt payloads derived from the authorship log (heavier / more sensitive). |
|
|
275
|
+
| **`skipRepositories`** | string[] | Prefer managing via **`gentrace skip`**; patterns match repository id (origin URL or path), with simple `*` glob support. |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### `gentrace skip`
|
|
280
|
+
|
|
281
|
+
Manage the **skip list** so **`gentrace publish`** (and the hook) no-op for matching repositories.
|
|
282
|
+
|
|
283
|
+
**Usage**
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
gentrace skip add <pattern>
|
|
287
|
+
gentrace skip remove <pattern>
|
|
288
|
+
gentrace skip list
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
| Subcommand | Description |
|
|
292
|
+
|------------|-------------|
|
|
293
|
+
| **`add`** | Append a pattern if not already present. |
|
|
294
|
+
| **`remove`** | Remove an exact pattern entry. |
|
|
295
|
+
| **`list`** | Print all patterns (or a message if empty). |
|
|
296
|
+
|
|
297
|
+
**Matching** — `*` matches any repository; otherwise exact match, or glob if the pattern contains `*`.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Configuration file
|
|
302
|
+
|
|
303
|
+
- **Path:** `~/.config/gentrace/config.json` (or **`$XDG_CONFIG_HOME/gentrace/config.json`** when set).
|
|
304
|
+
- **Permissions:** written with mode **0600**.
|
|
305
|
+
- **Precedence:** **`GENTRACE_API_URL`** / **`GENTRACE_API_KEY`** override saved values when set.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Environment variables
|
|
310
|
+
|
|
311
|
+
| Variable | Purpose |
|
|
312
|
+
|----------|---------|
|
|
313
|
+
| **`GENTRACE_API_KEY`** | API token (overrides config file). |
|
|
314
|
+
| **`GENTRACE_API_URL`** | API base URL (overrides config file). |
|
|
315
|
+
| **`GENTRACE_DEBUG`** | Set to `1` or `true` for verbose stderr logs. |
|
|
316
|
+
| **`GENTRACE_PUBLISH_DELAY_MS`** | Milliseconds to wait before collecting when using **`--daemon`** (default **2500** when daemon; **`0`** when not daemon unless this env is set). |
|
|
317
|
+
| **`GENTRACE_BIN`** | Used by the post-commit hook: full path to **`gentrace`** if it is not on the default `PATH` for non-interactive Git. |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Related documentation
|
|
322
|
+
|
|
323
|
+
- Monorepo CLI overview: [`../../docs/cli.md`](../../docs/cli.md)
|
|
324
|
+
- API / webhooks / IAM concepts: repository root **`README.md`** and **`ARCHITECTURE.md`**
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { configGet, configSet, configUnset } from './commands/config.js';
|
|
3
|
+
import { doctor } from './commands/doctor.js';
|
|
4
|
+
import { hooksInstall, hooksUninstall } from './commands/hooks.js';
|
|
5
|
+
import { installGitAi } from './commands/install-git-ai.js';
|
|
6
|
+
import { publish } from './commands/publish.js';
|
|
7
|
+
import { skipAdd, skipList, skipRemove } from './commands/skip.js';
|
|
8
|
+
import { enableDebug, VERBOSE_FLAGS } from './lib/debug.js';
|
|
9
|
+
const VERSION = '2.0.0';
|
|
10
|
+
const HELP = `\
|
|
11
|
+
gentrace - Git AI → Gentrace telemetry bridge
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
gentrace <command> [options]
|
|
15
|
+
|
|
16
|
+
Commands:
|
|
17
|
+
publish Collect Git AI data for HEAD and send to Gentrace API
|
|
18
|
+
Use --daemon from hooks: non-blocking + delay before collect
|
|
19
|
+
doctor Check git, git-ai, API key, and API reachability
|
|
20
|
+
install-git-ai Install the git-ai CLI if not already present
|
|
21
|
+
|
|
22
|
+
hooks install Install post-commit hook in current repo
|
|
23
|
+
hooks uninstall Remove post-commit hook from current repo
|
|
24
|
+
|
|
25
|
+
config Show all configuration
|
|
26
|
+
config get <key> Show a config value
|
|
27
|
+
config set <key> <v> Set a config value
|
|
28
|
+
config unset <key> Reset a config value to default
|
|
29
|
+
|
|
30
|
+
skip add <pattern> Add repo to skip list
|
|
31
|
+
skip remove <pat> Remove repo from skip list
|
|
32
|
+
skip list List skipped repos
|
|
33
|
+
|
|
34
|
+
--version, -V Print version
|
|
35
|
+
--help, -h Print this help
|
|
36
|
+
|
|
37
|
+
Place --verbose, --debug, or -v before a command or on publish/doctor for HTTP
|
|
38
|
+
and payload traces on stderr. Same effect: GENTRACE_DEBUG=1.
|
|
39
|
+
|
|
40
|
+
Environment:
|
|
41
|
+
GENTRACE_API_KEY API key (overrides config file)
|
|
42
|
+
GENTRACE_API_URL API base URL (overrides config file)
|
|
43
|
+
GENTRACE_DEBUG Set to 1/true for verbose stderr logs
|
|
44
|
+
GENTRACE_PUBLISH_DELAY_MS Milliseconds to wait before reading git-ai (default 2500 with --daemon)
|
|
45
|
+
GENTRACE_BIN Used by post-commit hook; path to gentrace binary
|
|
46
|
+
|
|
47
|
+
Config file: ~/.config/gentrace/config.json
|
|
48
|
+
`;
|
|
49
|
+
async function main() {
|
|
50
|
+
let args = process.argv.slice(2);
|
|
51
|
+
while (args[0] && VERBOSE_FLAGS.has(args[0])) {
|
|
52
|
+
enableDebug();
|
|
53
|
+
args = args.slice(1);
|
|
54
|
+
}
|
|
55
|
+
const cmd = args[0];
|
|
56
|
+
if (!cmd || cmd === '--help' || cmd === '-h') {
|
|
57
|
+
console.log(HELP);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (cmd === '--version' || cmd === '-V') {
|
|
61
|
+
console.log(`gentrace ${VERSION}`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
switch (cmd) {
|
|
65
|
+
case 'publish':
|
|
66
|
+
await publish(args.slice(1));
|
|
67
|
+
break;
|
|
68
|
+
case 'doctor':
|
|
69
|
+
await doctor(args.slice(1));
|
|
70
|
+
break;
|
|
71
|
+
case 'install-git-ai':
|
|
72
|
+
await installGitAi();
|
|
73
|
+
break;
|
|
74
|
+
case 'hooks': {
|
|
75
|
+
const sub = args[1];
|
|
76
|
+
if (sub === 'install') {
|
|
77
|
+
await hooksInstall(args[2]);
|
|
78
|
+
}
|
|
79
|
+
else if (sub === 'uninstall') {
|
|
80
|
+
await hooksUninstall(args[2]);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.error('Usage: gentrace hooks install|uninstall');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'config': {
|
|
89
|
+
const sub = args[1];
|
|
90
|
+
if (!sub) {
|
|
91
|
+
configGet();
|
|
92
|
+
}
|
|
93
|
+
else if (sub === 'get') {
|
|
94
|
+
configGet(args[2]);
|
|
95
|
+
}
|
|
96
|
+
else if (sub === 'set') {
|
|
97
|
+
if (!args[2] || !args[3]) {
|
|
98
|
+
console.error('Usage: gentrace config set <key> <value>');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
configSet(args[2], args[3]);
|
|
102
|
+
}
|
|
103
|
+
else if (sub === 'unset') {
|
|
104
|
+
if (!args[2]) {
|
|
105
|
+
console.error('Usage: gentrace config unset <key>');
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
configUnset(args[2]);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Treat as `config get <key>`
|
|
112
|
+
configGet(sub);
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'skip': {
|
|
117
|
+
const sub = args[1];
|
|
118
|
+
if (sub === 'add') {
|
|
119
|
+
if (!args[2]) {
|
|
120
|
+
console.error('Usage: gentrace skip add <pattern>');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
skipAdd(args[2]);
|
|
124
|
+
}
|
|
125
|
+
else if (sub === 'remove') {
|
|
126
|
+
if (!args[2]) {
|
|
127
|
+
console.error('Usage: gentrace skip remove <pattern>');
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
skipRemove(args[2]);
|
|
131
|
+
}
|
|
132
|
+
else if (sub === 'list') {
|
|
133
|
+
skipList();
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
console.error('Usage: gentrace skip add|remove|list');
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
default:
|
|
142
|
+
console.error(`Unknown command: ${cmd}\nRun 'gentrace --help' for usage.`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
main().catch((err) => {
|
|
147
|
+
console.error(err instanceof Error ? err.message : err);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { loadConfig, saveConfig } from '../lib/config.js';
|
|
2
|
+
const VALID_KEYS = [
|
|
3
|
+
'apiUrl',
|
|
4
|
+
'apiKey',
|
|
5
|
+
'includePrompts',
|
|
6
|
+
'skipRepositories',
|
|
7
|
+
];
|
|
8
|
+
export function configGet(key) {
|
|
9
|
+
const cfg = loadConfig();
|
|
10
|
+
if (!key) {
|
|
11
|
+
const display = { ...cfg, apiKey: cfg.apiKey ? maskKey(cfg.apiKey) : '(not set)' };
|
|
12
|
+
console.log(JSON.stringify(display, null, 2));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (!isValidKey(key)) {
|
|
16
|
+
console.error(`Unknown config key: ${key}`);
|
|
17
|
+
console.error(`Valid keys: ${VALID_KEYS.join(', ')}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const val = cfg[key];
|
|
21
|
+
if (key === 'apiKey') {
|
|
22
|
+
console.log(val ? maskKey(val) : '(not set)');
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log(typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function configSet(key, value) {
|
|
29
|
+
if (!isValidKey(key)) {
|
|
30
|
+
console.error(`Unknown config key: ${key}`);
|
|
31
|
+
console.error(`Valid keys: ${VALID_KEYS.join(', ')}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const patch = {};
|
|
35
|
+
if (key === 'includePrompts') {
|
|
36
|
+
patch.includePrompts = value === 'true';
|
|
37
|
+
}
|
|
38
|
+
else if (key === 'skipRepositories') {
|
|
39
|
+
const current = loadConfig();
|
|
40
|
+
patch.skipRepositories = [...new Set([...current.skipRepositories, value])];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
patch[key] = value;
|
|
44
|
+
}
|
|
45
|
+
saveConfig(patch);
|
|
46
|
+
console.log(`Set ${key}`);
|
|
47
|
+
}
|
|
48
|
+
export function configUnset(key) {
|
|
49
|
+
if (!isValidKey(key)) {
|
|
50
|
+
console.error(`Unknown config key: ${key}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const defaults = {
|
|
54
|
+
apiUrl: 'https://gentrace.4d-ps.com/api',
|
|
55
|
+
apiKey: '',
|
|
56
|
+
includePrompts: false,
|
|
57
|
+
skipRepositories: [],
|
|
58
|
+
};
|
|
59
|
+
saveConfig({ [key]: defaults[key] });
|
|
60
|
+
console.log(`Unset ${key} (reverted to default)`);
|
|
61
|
+
}
|
|
62
|
+
function isValidKey(key) {
|
|
63
|
+
return VALID_KEYS.includes(key);
|
|
64
|
+
}
|
|
65
|
+
function maskKey(key) {
|
|
66
|
+
if (key.length <= 8)
|
|
67
|
+
return '****';
|
|
68
|
+
return `${key.slice(0, 4)}…${key.slice(-4)}`;
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function doctor(argv?: string[]): Promise<void>;
|