@peektag-ai/cli 0.1.0 → 0.1.2

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 CHANGED
@@ -8,9 +8,37 @@ Node.js 20 or newer is required.
8
8
 
9
9
  ```bash
10
10
  npm install -g @peektag-ai/cli
11
+ ```
12
+
13
+ The public npm package is [@peektag-ai/cli](https://www.npmjs.com/package/@peektag-ai/cli). Its source lives in this repository at `tools/peektag-cli`; the server repository is not a public source download.
14
+
15
+ ### Connect an existing coding client
16
+
17
+ Install Cursor, Claude Code or Codex first, then run the matching command:
18
+
19
+ ```bash
20
+ peektag mcp install cursor
21
+ peektag mcp install claude-code
22
+ peektag mcp install codex
23
+ ```
24
+
25
+ Use CLI 0.1.2 or newer. These installers add the public remote MCP URL to the client's user configuration. Cursor and Codex use dedicated public OAuth client IDs for the production endpoint, with no client secret. Custom/local endpoints retain their own authentication configuration. The installers do not install the coding client or share the CLI's credentials with it. Complete authorization in the client:
26
+
27
+ - Cursor: restart the app, open Customize → MCP, enable `peektag` and sign in.
28
+ - Claude Code: open `/mcp`, select `peektag` and sign in.
29
+ - Codex: adding the server may open sign-in automatically. For explicit sign-in or reconnection, run `codex mcp login peektag --scopes peektag.mcp,offline_access`, then restart the session. Use an up-to-date Codex version supporting `--oauth-client-id`.
30
+
31
+ Verify the client can list PeekTag experience templates before creating or editing an experience. Each host uses the existing PeekTag MCP tools and native agents; this CLI does not implement a separate agent.
32
+
33
+ ### Use standalone CLI commands
34
+
35
+ ```bash
11
36
  peektag auth login
37
+ peektag mcp tools
12
38
  ```
13
39
 
40
+ This sign-in is separate from the coding client's authorization. It requires the configured public Keycloak client described below. The default endpoint is production; use the non-secret environment overrides below for local development.
41
+
14
42
  For local development:
15
43
 
16
44
  ```bash
@@ -54,7 +82,9 @@ Defaults:
54
82
 
55
83
  Use `peektag config show` and `peektag config set`. Environment overrides are `PEEKTAG_MCP_URL`, `PEEKTAG_AUTHORITY`, `PEEKTAG_OAUTH_CLIENT_ID`, and `PEEKTAG_OAUTH_SCOPE`. Only non-secret configuration is written to the config file.
56
84
 
57
- The Keycloak realm must contain a public `peektag-cli` client with Standard Flow and PKCE S256 enabled. Allow loopback redirects matching `http://127.0.0.1:*/callback`, map the `peektag.mcp` scope into access tokens, and include the API's accepted audience. Keep Direct Access Grants and client authentication disabled.
85
+ The Keycloak realm must contain a public `peektag-cli` client with Standard Flow and PKCE S256 enabled. Register `http://127.0.0.1/callback`; Keycloak accepts the ephemeral loopback port under RFC 8252. Do not register an unsupported port wildcard. Map the `peektag.mcp` scope into access tokens and include the API's accepted audience. Keep Direct Access Grants, implicit flow, service accounts and client authentication disabled. The maintained client manifest and fail-closed provisioning command are in `infra/aws/keycloak` and `infra/aws/scripts/provision-native-mcp-oauth.ps1` in the server repository.
86
+
87
+ Tokens are held only in the OS credential store. Version 0.1.2 splits the token bundle into bounded entries and publishes a manifest only after all entries are stored, avoiding the Windows single-entry size limit. Legacy single-entry credentials remain readable and migrate on refresh. After signing in with 0.1.2, keep using 0.1.2 or newer; 0.1.1 cannot read the chunked format.
58
88
 
59
89
  ## Safety
60
90
 
@@ -67,3 +97,15 @@ npm run check
67
97
  npm test
68
98
  npm pack --dry-run
69
99
  ```
100
+
101
+ ## 0.1.2 — Native OAuth and Windows credentials (2026-10-19)
102
+
103
+ Real testing of 0.1.1 found a missing production CLI client, rejected Codex dynamic registration and a Windows keychain size failure with real Keycloak tokens. This patch adds bounded keychain storage, public pre-registered Cursor/Codex client configuration, safe Cursor configuration migration and explicit revocation failures. The browser callback now asks users to confirm completion in the terminal rather than reporting success before credentials are saved.
104
+
105
+ The production CLI and Codex clients were provisioned with PKCE S256, consent and restricted callbacks without relaxing dynamic registration policies. Live checks verified standalone sign-in, a protected profile call, template listing, refresh, revocation rejection and reconnection. Native Codex app-server testing used an ephemeral session with only PeekTag configured and directly called `peektag_profile`; no model invocation was required. Cursor tool discovery alone is not proof of authenticated tool execution; complete and verify that host's login separately.
106
+
107
+ ## 0.1.1 — Onboarding corrections (2026-10-19)
108
+
109
+ This patch launches Windows sign-in without passing the authorization query through `cmd /c start`, handles browser spawn failures, validates callback method/path and state bytes, ignores unrelated callbacks, and clears the callback timer when login ends.
110
+
111
+ Verification includes the TypeScript check and 10 tests covering argument handling, configuration, browser launch arguments, PKCE callback rejection and cleanup. The published `0.1.0` package was separately installed into an isolated directory and exercised against a local MCP fixture: initialization, tool listing, calling `peektag_answer`, large string IDs, all three installers, existing Cursor configuration preservation, and invalid input. Codex and Claude Code installers used recording stubs rather than changing real client settings. Actual end-user OAuth sign-in, refresh and revocation against production remain separate release checks; the local callback tests do not prove those completed.
package/dist/auth.d.ts CHANGED
@@ -7,8 +7,6 @@ export interface StoredTokens {
7
7
  }
8
8
  export declare function readStoredTokens(config: CliConfig): Promise<StoredTokens | undefined>;
9
9
  export declare function getAccessToken(config: CliConfig): Promise<string>;
10
- declare function openBrowser(url: string): void;
11
- export declare function login(config: CliConfig, open?: typeof openBrowser): Promise<StoredTokens>;
10
+ export declare function login(config: CliConfig, open?: (url: string) => void | Promise<void>): Promise<StoredTokens>;
12
11
  export declare function logout(config: CliConfig): Promise<boolean>;
13
12
  export declare function tokenIdentity(accessToken: string): Record<string, unknown>;
14
- export {};
package/dist/auth.js CHANGED
@@ -1,17 +1,19 @@
1
1
  import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
2
2
  import { createServer } from "node:http";
3
- import { spawn } from "node:child_process";
3
+ import { openSignInBrowser } from "./browser.js";
4
4
  import { AsyncEntry } from "@napi-rs/keyring";
5
5
  import { assertHttpsOrLoopback } from "./config.js";
6
+ import { deleteCredential, readCredential, writeCredential } from "./credential-store.js";
6
7
  const KEYRING_SERVICE = "com.peektag.cli";
7
8
  const CALLBACK_TIMEOUT_MS = 180_000;
9
+ const OAUTH_REQUEST_TIMEOUT_MS = 30_000;
8
10
  function keyring(config) {
9
- return new AsyncEntry(KEYRING_SERVICE, `${config.authority}|${config.clientId}`);
11
+ return suffix => new AsyncEntry(KEYRING_SERVICE, `${config.authority}|${config.clientId}${suffix}`);
10
12
  }
11
13
  async function discover(config) {
12
14
  const authority = assertHttpsOrLoopback(config.authority, "OAuth authority");
13
15
  const discoveryUrl = new URL(`${authority.pathname.replace(/\/$/, "")}/.well-known/openid-configuration`, authority);
14
- const response = await fetch(discoveryUrl, { headers: { Accept: "application/json" } });
16
+ const response = await fetch(discoveryUrl, { headers: { Accept: "application/json" }, signal: AbortSignal.timeout(OAUTH_REQUEST_TIMEOUT_MS) });
15
17
  if (!response.ok)
16
18
  throw new Error(`OAuth discovery failed (${response.status}).`);
17
19
  const metadata = await response.json();
@@ -30,7 +32,7 @@ function toStoredTokens(response, previousRefreshToken) {
30
32
  }
31
33
  async function persist(config, tokens) {
32
34
  try {
33
- await keyring(config).setPassword(JSON.stringify(tokens));
35
+ await writeCredential(keyring(config), JSON.stringify(tokens));
34
36
  }
35
37
  catch (error) {
36
38
  throw new Error(`Could not store credentials in the operating-system keychain: ${error.message}`);
@@ -38,7 +40,7 @@ async function persist(config, tokens) {
38
40
  }
39
41
  export async function readStoredTokens(config) {
40
42
  try {
41
- const value = await keyring(config).getPassword();
43
+ const value = await readCredential(keyring(config));
42
44
  return value ? JSON.parse(value) : undefined;
43
45
  }
44
46
  catch (error) {
@@ -52,6 +54,7 @@ async function tokenRequest(endpoint, fields) {
52
54
  method: "POST",
53
55
  headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded" },
54
56
  body: new URLSearchParams(fields),
57
+ signal: AbortSignal.timeout(OAUTH_REQUEST_TIMEOUT_MS),
55
58
  });
56
59
  const body = await response.json().catch(() => ({}));
57
60
  if (!response.ok) {
@@ -88,13 +91,7 @@ export async function getAccessToken(config) {
88
91
  function base64Url(bytes) {
89
92
  return bytes.toString("base64url");
90
93
  }
91
- function openBrowser(url) {
92
- const command = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
93
- const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
94
- const child = spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true });
95
- child.unref();
96
- }
97
- export async function login(config, open = openBrowser) {
94
+ export async function login(config, open = openSignInBrowser) {
98
95
  const metadata = await discover(config);
99
96
  const verifier = base64Url(randomBytes(48));
100
97
  const challenge = base64Url(createHash("sha256").update(verifier).digest());
@@ -111,25 +108,30 @@ export async function login(config, open = openBrowser) {
111
108
  const code = new Promise((res, rej) => { settle = res; fail = rej; });
112
109
  const timer = setTimeout(() => fail(new Error("OAuth login timed out.")), CALLBACK_TIMEOUT_MS);
113
110
  server.on("request", (request, response) => {
114
- const url = new URL(request.url ?? "/", `http://${request.headers.host}`);
111
+ const url = new URL(request.url ?? "/", "http://127.0.0.1");
115
112
  const state = url.searchParams.get("state") ?? "";
116
- const stateMatches = state.length === expectedState.length && timingSafeEqual(Buffer.from(state), Buffer.from(expectedState));
113
+ const receivedState = Buffer.from(state);
114
+ const expectedStateBytes = Buffer.from(expectedState);
115
+ const stateMatches = receivedState.length === expectedStateBytes.length && timingSafeEqual(receivedState, expectedStateBytes);
116
+ if (request.method !== "GET" || url.pathname !== "/callback" || !stateMatches) {
117
+ response.writeHead(400, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
118
+ response.end("Invalid sign-in callback.");
119
+ return;
120
+ }
117
121
  const error = url.searchParams.get("error_description") ?? url.searchParams.get("error");
118
122
  const authorizationCode = url.searchParams.get("code");
119
123
  const success = stateMatches && !error && authorizationCode;
120
124
  response.writeHead(success ? 200 : 400, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
121
- response.end(success ? "<h1>PeekTag connected</h1><p>You can close this window.</p>" : "<h1>PeekTag sign-in failed</h1><p>Return to the terminal.</p>");
125
+ response.end(success ? "<h1>Completing PeekTag sign-in</h1><p>Return to the terminal to confirm the connection.</p>" : "<h1>PeekTag sign-in failed</h1><p>Return to the terminal.</p>");
122
126
  clearTimeout(timer);
123
- if (!stateMatches)
124
- fail(new Error("OAuth state validation failed."));
125
- else if (error)
127
+ if (error)
126
128
  fail(new Error(`OAuth login failed: ${error}`));
127
129
  else if (!authorizationCode)
128
130
  fail(new Error("OAuth callback did not include an authorization code."));
129
131
  else
130
132
  settle(authorizationCode);
131
133
  });
132
- resolve({ redirectUri: `http://127.0.0.1:${address.port}/callback`, code, close: () => server.close() });
134
+ resolve({ redirectUri: `http://127.0.0.1:${address.port}/callback`, code, close: () => { clearTimeout(timer); server.close(); } });
133
135
  });
134
136
  });
135
137
  try {
@@ -143,8 +145,8 @@ export async function login(config, open = openBrowser) {
143
145
  code_challenge: challenge,
144
146
  code_challenge_method: "S256",
145
147
  }).toString();
146
- open(authorizationUrl.toString());
147
- const code = await callback.code;
148
+ // Attach the rejection handler before opening the browser: callbacks may arrive immediately.
149
+ const [, code] = await Promise.all([Promise.resolve().then(() => open(authorizationUrl.toString())), callback.code]);
148
150
  const tokenResponse = await tokenRequest(metadata.token_endpoint, {
149
151
  grant_type: "authorization_code",
150
152
  client_id: config.clientId,
@@ -162,24 +164,26 @@ export async function login(config, open = openBrowser) {
162
164
  }
163
165
  export async function logout(config) {
164
166
  const tokens = await readStoredTokens(config);
165
- if (tokens?.refreshToken) {
166
- const metadata = await discover(config);
167
- if (metadata.revocation_endpoint) {
168
- await fetch(metadata.revocation_endpoint, {
167
+ let removed = false;
168
+ try {
169
+ if (tokens?.refreshToken) {
170
+ const metadata = await discover(config);
171
+ if (!metadata.revocation_endpoint)
172
+ throw new Error("The OAuth provider did not advertise token revocation.");
173
+ const response = await fetch(assertHttpsOrLoopback(metadata.revocation_endpoint, "OAuth revocation endpoint"), {
169
174
  method: "POST",
170
175
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
171
176
  body: new URLSearchParams({ token: tokens.refreshToken, token_type_hint: "refresh_token", client_id: config.clientId }),
172
- }).catch(() => undefined);
177
+ signal: AbortSignal.timeout(OAUTH_REQUEST_TIMEOUT_MS),
178
+ });
179
+ if (!response.ok)
180
+ throw new Error(`OAuth token revocation failed (${response.status}). Local credentials were removed; revoke the session in PeekTag account settings.`);
173
181
  }
174
182
  }
175
- try {
176
- return await keyring(config).deleteCredential();
177
- }
178
- catch (error) {
179
- if (/NoEntry/i.test(error.message))
180
- return false;
181
- throw error;
183
+ finally {
184
+ removed = await deleteCredential(keyring(config));
182
185
  }
186
+ return removed;
183
187
  }
184
188
  export function tokenIdentity(accessToken) {
185
189
  const payload = accessToken.split(".")[1];
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function browserCommand(url: string, platform: NodeJS.Platform): {
2
+ command: string;
3
+ args: string[];
4
+ };
5
+ export declare function openSignInBrowser(url: string): Promise<void>;
@@ -0,0 +1,16 @@
1
+ import { spawn } from "node:child_process";
2
+ export function browserCommand(url, platform) {
3
+ if (platform === "win32")
4
+ return { command: "rundll32.exe", args: ["url.dll,FileProtocolHandler", url] };
5
+ return { command: platform === "darwin" ? "open" : "xdg-open", args: [url] };
6
+ }
7
+ export async function openSignInBrowser(url) {
8
+ const { command, args } = browserCommand(url, process.platform);
9
+ await new Promise((resolve, reject) => {
10
+ // Pass the whole authorization URL as an argument, without a shell interpreting its query string.
11
+ const child = spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true, shell: false });
12
+ child.once("error", () => reject(new Error("Could not open the sign-in browser. Check your default browser and try again.")));
13
+ child.once("spawn", () => { child.unref(); resolve(); });
14
+ });
15
+ }
16
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,QAAyB;IACnE,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,6BAA6B,EAAE,GAAG,CAAC,EAAE,CAAC;IACzG,OAAO,EAAE,OAAO,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW;IACjD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,kGAAkG;QAClG,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACzG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC,CAAC,CAAC;QAC9H,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ function addSearchOptions(command) {
31
31
  const program = new Command()
32
32
  .name("peektag")
33
33
  .description("Use PeekTag from the command line and MCP-compatible agents.")
34
- .version("0.1.0")
34
+ .version("0.1.2")
35
35
  .option("--json", "Print machine-readable JSON")
36
36
  .option("--timeout <seconds>", "Request timeout in seconds", "60")
37
37
  .showSuggestionAfterError();
@@ -0,0 +1,10 @@
1
+ export interface CredentialEntry {
2
+ getPassword(): Promise<string | null | undefined>;
3
+ setPassword(value: string): Promise<void>;
4
+ deleteCredential(): Promise<boolean>;
5
+ }
6
+ type EntryFactory = (suffix: string) => CredentialEntry;
7
+ export declare function readCredential(entry: EntryFactory): Promise<string | undefined>;
8
+ export declare function writeCredential(entry: EntryFactory, value: string): Promise<void>;
9
+ export declare function deleteCredential(entry: EntryFactory): Promise<boolean>;
10
+ export {};
@@ -0,0 +1,98 @@
1
+ import { randomUUID } from "node:crypto";
2
+ const CHUNK_LENGTH = 1000;
3
+ const MAX_CHUNKS = 64;
4
+ function manifest(value) {
5
+ const parsed = JSON.parse(value);
6
+ if (parsed.format !== "peektag-keychain-v1")
7
+ return undefined;
8
+ if (!/^[a-f0-9-]{36}$/.test(parsed.generation ?? "") || !Number.isInteger(parsed.count) || parsed.count < 1 || parsed.count > MAX_CHUNKS) {
9
+ throw new Error("The keychain credential manifest is invalid. Sign in again.");
10
+ }
11
+ return parsed;
12
+ }
13
+ async function readEntry(entry) {
14
+ try {
15
+ return await entry.getPassword() ?? undefined;
16
+ }
17
+ catch (error) {
18
+ if (/NoEntry/i.test(error.message))
19
+ return undefined;
20
+ throw error;
21
+ }
22
+ }
23
+ async function removeEntry(entry) {
24
+ try {
25
+ return await entry.deleteCredential();
26
+ }
27
+ catch (error) {
28
+ if (/NoEntry/i.test(error.message))
29
+ return false;
30
+ throw error;
31
+ }
32
+ }
33
+ const partSuffix = (value, index) => `|${value.generation}|${index}`;
34
+ export async function readCredential(entry) {
35
+ // A refresh can replace the manifest while another CLI process is reading it.
36
+ for (let attempt = 0; attempt < 2; attempt++) {
37
+ const value = await readEntry(entry(""));
38
+ if (!value)
39
+ return undefined;
40
+ const stored = manifest(value);
41
+ if (!stored)
42
+ return value;
43
+ const parts = await Promise.all(Array.from({ length: stored.count }, (_, index) => readEntry(entry(partSuffix(stored, index)))));
44
+ if (parts.every(part => part !== undefined))
45
+ return parts.join("");
46
+ if (value === await readEntry(entry("")))
47
+ throw new Error("Stored credentials are incomplete. Sign in again.");
48
+ }
49
+ throw new Error("The keychain changed during the read. Retry the command.");
50
+ }
51
+ export async function writeCredential(entry, value) {
52
+ const previous = await readEntry(entry(""));
53
+ let oldManifest;
54
+ // New authorization must be able to replace a damaged legacy entry.
55
+ if (previous) {
56
+ try {
57
+ oldManifest = manifest(previous);
58
+ }
59
+ catch {
60
+ oldManifest = undefined;
61
+ }
62
+ }
63
+ // Each chunk stays below Windows' UTF-16 credential size limit, including surrogate pairs.
64
+ const chunks = [];
65
+ for (const character of value) {
66
+ if (!chunks.length || chunks[chunks.length - 1].length + character.length > CHUNK_LENGTH)
67
+ chunks.push("");
68
+ chunks[chunks.length - 1] += character;
69
+ }
70
+ if (!chunks.length || chunks.length > MAX_CHUNKS)
71
+ throw new Error("Credential size is outside the supported range.");
72
+ const next = { format: "peektag-keychain-v1", generation: randomUUID(), count: chunks.length };
73
+ const created = [];
74
+ try {
75
+ for (const [index, chunk] of chunks.entries()) {
76
+ await entry(partSuffix(next, index)).setPassword(chunk);
77
+ created.push(index);
78
+ }
79
+ // Publish only after every chunk exists; a failed write preserves the previous session.
80
+ await entry("").setPassword(JSON.stringify(next));
81
+ }
82
+ catch (error) {
83
+ await Promise.all(created.map(index => removeEntry(entry(partSuffix(next, index)))));
84
+ throw error;
85
+ }
86
+ if (oldManifest)
87
+ await Promise.all(Array.from({ length: oldManifest.count }, (_, index) => removeEntry(entry(partSuffix(oldManifest, index)))));
88
+ }
89
+ export async function deleteCredential(entry) {
90
+ const value = await readEntry(entry(""));
91
+ if (!value)
92
+ return false;
93
+ const stored = manifest(value);
94
+ if (stored)
95
+ await Promise.all(Array.from({ length: stored.count }, (_, index) => removeEntry(entry(partSuffix(stored, index)))));
96
+ return removeEntry(entry(""));
97
+ }
98
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,12 @@
1
1
  import type { CliConfig } from "./config.js";
2
2
  export type McpTarget = "claude-code" | "cursor" | "codex";
3
+ export declare function cursorServerConfig(url: string): {
4
+ url: string;
5
+ auth?: {
6
+ CLIENT_ID: string;
7
+ scopes: string[];
8
+ };
9
+ };
10
+ export declare function codexInstallArguments(url: string): string[];
11
+ export declare function mergeCursorDocument(document: unknown, url: string): Record<string, unknown>;
3
12
  export declare function installMcp(target: McpTarget, config: CliConfig): Promise<string>;
package/dist/installer.js CHANGED
@@ -2,7 +2,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
- import { assertHttpsOrLoopback } from "./config.js";
5
+ import { assertHttpsOrLoopback, DEFAULT_MCP_URL } from "./config.js";
6
6
  function run(command, args) {
7
7
  const result = spawnSync(command, args, { stdio: "inherit", shell: process.platform === "win32" });
8
8
  if (result.error)
@@ -10,6 +10,37 @@ function run(command, args) {
10
10
  if (result.status !== 0)
11
11
  throw new Error(`${command} exited with status ${result.status ?? "unknown"}.`);
12
12
  }
13
+ export function cursorServerConfig(url) {
14
+ return url === DEFAULT_MCP_URL
15
+ ? { url, auth: { CLIENT_ID: "peektag-cursor", scopes: ["peektag.mcp", "offline_access"] } }
16
+ : { url };
17
+ }
18
+ export function codexInstallArguments(url) {
19
+ return ["mcp", "add", "peektag", "--url", url,
20
+ ...(url === DEFAULT_MCP_URL ? ["--oauth-client-id", "peektag-codex"] : [])];
21
+ }
22
+ export function mergeCursorDocument(document, url) {
23
+ if (!document || typeof document !== "object" || Array.isArray(document)) {
24
+ throw new Error("Cursor MCP config must be a JSON object.");
25
+ }
26
+ const config = document;
27
+ const servers = config.mcpServers;
28
+ if (servers !== undefined && (!servers || typeof servers !== "object" || Array.isArray(servers))) {
29
+ throw new Error("Cursor mcpServers must be a JSON object.");
30
+ }
31
+ const entries = (servers ?? {});
32
+ const existing = entries.peektag;
33
+ if (existing && (typeof existing !== "object" || Array.isArray(existing) || existing.url !== url)) {
34
+ throw new Error("Cursor already has a different peektag server. Review it before replacing the connection.");
35
+ }
36
+ const existingAuth = existing?.auth;
37
+ if (url === DEFAULT_MCP_URL && existingAuth !== undefined &&
38
+ (!existingAuth || typeof existingAuth !== "object" || Array.isArray(existingAuth) ||
39
+ existingAuth.CLIENT_ID !== "peektag-cursor")) {
40
+ throw new Error("Cursor already has custom PeekTag OAuth settings. Review them before replacing the connection.");
41
+ }
42
+ return { ...config, mcpServers: { ...entries, peektag: { ...(existing ?? {}), ...cursorServerConfig(url) } } };
43
+ }
13
44
  async function mergeCursorConfig(url) {
14
45
  const path = join(homedir(), ".cursor", "mcp.json");
15
46
  let document = {};
@@ -20,14 +51,14 @@ async function mergeCursorConfig(url) {
20
51
  if (error.code !== "ENOENT")
21
52
  throw new Error(`Cursor MCP config is not valid JSON: ${path}`);
22
53
  }
23
- document.mcpServers = { ...document.mcpServers, peektag: { url } };
54
+ const updated = mergeCursorDocument(document, url);
24
55
  await mkdir(dirname(path), { recursive: true });
25
- await writeFile(path, `${JSON.stringify(document, null, 2)}\n`, "utf8");
56
+ await writeFile(path, `${JSON.stringify(updated, null, 2)}\n`, "utf8");
26
57
  return path;
27
58
  }
28
59
  export async function installMcp(target, config) {
29
60
  const mcpUrl = assertHttpsOrLoopback(config.mcpUrl, "MCP URL").toString();
30
- if (process.platform === "win32" && /[&|<>"^]/.test(mcpUrl)) {
61
+ if (process.platform === "win32" && /[&|<>"^%!]/.test(mcpUrl)) {
31
62
  throw new Error("The MCP URL contains characters that cannot be passed safely to a Windows agent installer.");
32
63
  }
33
64
  if (target === "cursor")
@@ -36,7 +67,7 @@ export async function installMcp(target, config) {
36
67
  run("claude", ["mcp", "add", "--transport", "http", "--scope", "user", "peektag", mcpUrl]);
37
68
  return "PeekTag added to Claude Code. Run /mcp in Claude Code to sign in.";
38
69
  }
39
- run("codex", ["mcp", "add", "peektag", "--url", mcpUrl]);
40
- return "PeekTag added to Codex. Run `codex mcp login peektag` to sign in.";
70
+ run("codex", codexInstallArguments(mcpUrl));
71
+ return "PeekTag added to Codex. If authentication is needed, run `codex mcp login peektag --scopes peektag.mcp,offline_access`.";
41
72
  }
42
73
  //# sourceMappingURL=installer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIpD,SAAS,GAAG,CAAC,OAAe,EAAE,IAAc;IAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;IACnG,IAAI,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,uBAAuB,MAAM,CAAC,MAAM,IAAI,SAAS,GAAG,CAAC,CAAC;AAC3G,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACpD,IAAI,QAAQ,GAAqE,EAAE,CAAC;IACpF,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,QAAQ,CAAC,UAAU,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;IACnE,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB,EAAE,MAAiB;IACnE,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,oBAAoB,MAAM,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC;IACvF,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3F,OAAO,mEAAmE,CAAC;IAC7E,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO,mEAAmE,CAAC;AAC7E,CAAC"}
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"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"}
package/dist/mcp.js CHANGED
@@ -2,7 +2,7 @@ import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/cli
2
2
  import { assertHttpsOrLoopback } from "./config.js";
3
3
  import { getAccessToken } from "./auth.js";
4
4
  export class PeekTagMcpClient {
5
- #client = new Client({ name: "peektag-cli", version: "0.1.0" });
5
+ #client = new Client({ name: "peektag-cli", version: "0.1.2" });
6
6
  #config;
7
7
  #timeoutMs;
8
8
  #transport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peektag-ai/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Official command-line client for PeekTag MCP tools.",
5
5
  "type": "module",
6
6
  "bin": {