@trekagent/claude 0.2.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 +7 -4
- package/bin/cli.mjs +23 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,8 +6,9 @@ API token — so an agent starts reporting presence and working the ready-task f
|
|
|
6
6
|
you restart Claude Code.
|
|
7
7
|
|
|
8
8
|
If no token is already available, `init` **opens your browser** so you can sign in or create an
|
|
9
|
-
account — the token
|
|
10
|
-
loopback listener
|
|
9
|
+
account and **pick a project** — the token (and the selected project) are then delivered straight
|
|
10
|
+
back to the installer over a localhost loopback listener and written as `TREK_TOKEN` /
|
|
11
|
+
`TREK_PROJECT_ID`. No copy-paste required.
|
|
11
12
|
|
|
12
13
|
## Usage
|
|
13
14
|
|
|
@@ -46,8 +47,10 @@ npx @trekagent/claude init --uninstall
|
|
|
46
47
|
3. A `trk_` token already wired into project `./.claude/settings.local.json` or user
|
|
47
48
|
`~/.claude/settings.local.json` (skipped when `--login` is passed).
|
|
48
49
|
4. **Browser login** (interactive terminals, unless `--no-browser`): opens the cockpit
|
|
49
|
-
`cli-auth` page, you sign in / sign up, and the token
|
|
50
|
-
loopback listener bound to `127.0.0.1`.
|
|
50
|
+
`cli-auth` page, you sign in / sign up and select a project, and the token plus the chosen
|
|
51
|
+
project are delivered back automatically over a loopback listener bound to `127.0.0.1`. The
|
|
52
|
+
selected project is written as `TREK_PROJECT_ID` (an explicit `--project-id` still applies to
|
|
53
|
+
the non-browser paths).
|
|
51
54
|
5. Manual paste prompt — the fallback for `--no-browser`, non-interactive shells, or if the
|
|
52
55
|
browser flow times out (3 min). Points you at **Settings → API tokens** in the cockpit.
|
|
53
56
|
|
package/bin/cli.mjs
CHANGED
|
@@ -146,8 +146,12 @@ display:flex;align-items:center;justify-content:center;height:100vh;margin:0}
|
|
|
146
146
|
.card{text-align:center;max-width:30rem;padding:2rem}h1{font-size:1.4rem}p{color:#f28b82}</style></head>
|
|
147
147
|
<body><div class="card"><h1>Trek CLI</h1><p>${String(msg).replace(/[<>&]/g, '')}</p></div></body></html>`;
|
|
148
148
|
|
|
149
|
-
// Loopback browser-login flow. Resolves with
|
|
150
|
-
// not complete (timeout / browser failure / user error) so the
|
|
149
|
+
// Loopback browser-login flow. Resolves with { token, projectId } on success, or
|
|
150
|
+
// null if it could not complete (timeout / browser failure / user error) so the
|
|
151
|
+
// caller can fall back. The cockpit success callback contract is:
|
|
152
|
+
// success: http://127.0.0.1:<port>/callback?token=<trk_...>&project=<projectId>&state=<nonce>
|
|
153
|
+
// error: http://127.0.0.1:<port>/callback?error=<msg>&state=<nonce>
|
|
154
|
+
// Project selection is mandatory in the cockpit, so `project` is normally present.
|
|
151
155
|
function browserLogin(flags) {
|
|
152
156
|
return new Promise((resolve) => {
|
|
153
157
|
const expectedState = randomUUID();
|
|
@@ -176,6 +180,7 @@ function browserLogin(flags) {
|
|
|
176
180
|
const token = url.searchParams.get('token');
|
|
177
181
|
const state = url.searchParams.get('state');
|
|
178
182
|
const error = url.searchParams.get('error');
|
|
183
|
+
const projectId = url.searchParams.get('project') || '';
|
|
179
184
|
|
|
180
185
|
// A mismatched state must NOT resolve — keep waiting.
|
|
181
186
|
if (state !== expectedState) {
|
|
@@ -195,7 +200,7 @@ function browserLogin(flags) {
|
|
|
195
200
|
if (looksLikeToken(token)) {
|
|
196
201
|
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
|
|
197
202
|
res.end(SUCCESS_HTML);
|
|
198
|
-
finish(token);
|
|
203
|
+
finish({ token, projectId });
|
|
199
204
|
return;
|
|
200
205
|
}
|
|
201
206
|
|
|
@@ -246,24 +251,28 @@ async function pasteToken() {
|
|
|
246
251
|
return tok;
|
|
247
252
|
}
|
|
248
253
|
|
|
254
|
+
// Resolve a token (and, where available, a project id) following this precedence.
|
|
255
|
+
// Always returns { token, projectId }; projectId is '' for every path except a
|
|
256
|
+
// successful browser login, where the cockpit's mandatory project selection is
|
|
257
|
+
// delivered back over the loopback callback.
|
|
249
258
|
async function resolveToken(flags) {
|
|
250
259
|
// 1. explicit flag
|
|
251
|
-
if (typeof flags.token === 'string' && flags.token) return flags.token;
|
|
260
|
+
if (typeof flags.token === 'string' && flags.token) return { token: flags.token, projectId: '' };
|
|
252
261
|
// 2. environment
|
|
253
|
-
if (process.env.TREK_TOKEN) { skip('using TREK_TOKEN from environment'); return process.env.TREK_TOKEN; }
|
|
262
|
+
if (process.env.TREK_TOKEN) { skip('using TREK_TOKEN from environment'); return { token: process.env.TREK_TOKEN, projectId: '' }; }
|
|
254
263
|
// 3. reuse an existing token from settings (unless --login forces re-auth)
|
|
255
264
|
if (!flags.login) {
|
|
256
265
|
const existing = detectExistingToken();
|
|
257
|
-
if (existing) { skip(`reusing TREK_TOKEN from ${rel(existing.path)}`); return existing.token; }
|
|
266
|
+
if (existing) { skip(`reusing TREK_TOKEN from ${rel(existing.path)}`); return { token: existing.token, projectId: '' }; }
|
|
258
267
|
}
|
|
259
268
|
// 4. browser login (interactive, unless --no-browser)
|
|
260
269
|
if (process.stdin.isTTY && !flags['no-browser']) {
|
|
261
|
-
const
|
|
262
|
-
if (looksLikeToken(
|
|
270
|
+
const result = await browserLogin(flags);
|
|
271
|
+
if (result && looksLikeToken(result.token)) { ok('signed in via browser'); return { token: result.token, projectId: result.projectId || '' }; }
|
|
263
272
|
warn('falling back to manual token entry.');
|
|
264
273
|
}
|
|
265
274
|
// 5. manual paste fallback (also the --no-browser / non-TTY path)
|
|
266
|
-
return pasteToken();
|
|
275
|
+
return { token: await pasteToken(), projectId: '' };
|
|
267
276
|
}
|
|
268
277
|
|
|
269
278
|
// --- settings.local.json: merge env block ----------------------------------
|
|
@@ -316,7 +325,7 @@ function installPlugin(bin, marketplaceRepo) {
|
|
|
316
325
|
async function init(flags) {
|
|
317
326
|
const userScope = !!flags.user;
|
|
318
327
|
const apiUrl = (typeof flags['api-url'] === 'string' && flags['api-url']) || DEFAULT_API_URL;
|
|
319
|
-
const
|
|
328
|
+
const flagProjectId = typeof flags['project-id'] === 'string' ? flags['project-id'] : process.env.TREK_PROJECT_ID || '';
|
|
320
329
|
const marketplaceRepo = (typeof flags.marketplace === 'string' && flags.marketplace) || DEFAULT_MARKETPLACE_REPO;
|
|
321
330
|
|
|
322
331
|
log(c.bold(`\nTrek installer — ${userScope ? 'user' : 'project'} scope`));
|
|
@@ -332,7 +341,10 @@ async function init(flags) {
|
|
|
332
341
|
installPlugin(bin, marketplaceRepo);
|
|
333
342
|
}
|
|
334
343
|
|
|
335
|
-
const token = await resolveToken(flags);
|
|
344
|
+
const { token, projectId: browserProjectId } = await resolveToken(flags);
|
|
345
|
+
// The browser flow's mandatory project selection wins; otherwise fall back to
|
|
346
|
+
// the explicit --project-id / $TREK_PROJECT_ID resolution.
|
|
347
|
+
const projectId = browserProjectId || flagProjectId;
|
|
336
348
|
const claudeDir = userScope ? join(homedir(), '.claude') : join(CWD, '.claude');
|
|
337
349
|
writeTokenEnv(claudeDir, apiUrl, token, projectId);
|
|
338
350
|
if (!userScope) ensureGitignore(CWD, ['.claude/settings.local.json']);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trekagent/claude",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "One-command installer for Trek: installs the Trek Claude Code plugin (skill + hooks + MCP) from the Trek marketplace and wires your API token.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|