@kodycodes/cli 0.0.0 → 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kent C. Dodds
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,65 @@
1
1
  # @kodycodes/cli
2
2
 
3
- Under construction
3
+ Turn one-off agent work into something you can rerun: a local MCP client for
4
+ [Kody](https://kody.codes) with login, OS keychain token storage, `search`, and
5
+ `execute`. Talks MCP `2026-07-28` (Kody's stateless `/mcp` lane) and logs in
6
+ with Client ID Metadata Documents (SEP-991).
7
+
8
+ ```bash
9
+ npx @kodycodes/cli login
10
+ npx @kodycodes/cli search "what can you do"
11
+ npx @kodycodes/cli skill install
12
+ ```
13
+
14
+ Copyright © 2026 [Kent C. Dodds](https://kentcdodds.com). MIT licensed.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install -g @kodycodes/cli
20
+ kody login
21
+ ```
22
+
23
+ Or run via `npx @kodycodes/cli` without a global install.
24
+
25
+ ## Commands
26
+
27
+ | Command | Purpose |
28
+ | --- | --- |
29
+ | `kody login` | Browser OAuth (CIMD + PKCE). Stores access and refresh tokens. |
30
+ | `kody logout` | Deletes stored credentials. |
31
+ | `kody status` | Shows login state without printing secrets. |
32
+ | `kody whoami` | Confirms the MCP connection and lists tools. |
33
+ | `kody search [query]` | Calls Kody `search`. |
34
+ | `kody execute` | Calls Kody `execute` (`--code`, `--file`, or stdin via `--file -`). |
35
+ | `kody skill install` | Copies the getting-started skill into Claude Code / Cursor / Agents. |
36
+
37
+ `--mcp-url` or `KODY_MCP_URL` overrides the default `https://kody.codes/mcp`.
38
+ `--json` prints structured MCP results.
39
+
40
+ ## Token storage
41
+
42
+ Credentials are stored in the OS secret store:
43
+
44
+ - macOS: Keychain
45
+ - Windows: Credential Manager
46
+ - Linux: Secret Service / libsecret
47
+
48
+ If the keychain is unavailable (common on headless Linux), the CLI writes a
49
+ `0600` file under `$XDG_CONFIG_HOME/kody` (or `%APPDATA%\kody` on Windows,
50
+ `~/Library/Application Support/kody` on macOS). Tokens are never printed.
51
+
52
+ Access tokens refresh automatically on expiry or HTTP 401.
53
+
54
+ ## Releases
55
+
56
+ This repo uses [semantic-release](https://github.com/semantic-release/semantic-release)
57
+ the same way [match-sorter](https://github.com/kentcdodds/match-sorter) does:
58
+ conventional commits on `main` publish `@kodycodes/cli` with npm provenance
59
+ (`id-token: write`). Version in `package.json` stays `0.0.0-semantically-released`.
60
+
61
+ Trusted publishing for `@kodycodes/cli` is attached to this GitHub repository.
62
+
63
+ ## License
64
+
65
+ MIT © Kent C. Dodds
package/dist/auth.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { type OAuthClientInformationMixed, type OAuthTokens } from '@modelcontextprotocol/client';
2
+ import { type SecretBackend, type StoredCredentials } from './store.js';
3
+ export type LoginOptions = {
4
+ mcpUrl?: string;
5
+ openBrowser?: boolean;
6
+ backend?: SecretBackend;
7
+ timeoutMs?: number;
8
+ now?: () => number;
9
+ fetchFn?: typeof fetch;
10
+ onAuthorizationUrl?: (url: URL) => void;
11
+ };
12
+ export declare function isAccessTokenExpired(credentials: StoredCredentials, now?: number): boolean;
13
+ export declare function credentialsFromTokens(input: {
14
+ mcpUrl: string;
15
+ resource: string;
16
+ authorizationServerUrl: string;
17
+ client: OAuthClientInformationMixed;
18
+ tokens: OAuthTokens;
19
+ previous?: StoredCredentials;
20
+ now?: number;
21
+ }): StoredCredentials;
22
+ export declare function refreshStoredCredentials(input: {
23
+ credentials: StoredCredentials;
24
+ backend?: SecretBackend;
25
+ now?: number;
26
+ fetchFn?: typeof fetch;
27
+ }): Promise<StoredCredentials>;
28
+ export declare function ensureFreshCredentials(input: {
29
+ mcpUrl?: string;
30
+ backend?: SecretBackend;
31
+ now?: number;
32
+ fetchFn?: typeof fetch;
33
+ }): Promise<StoredCredentials>;
34
+ export declare function login(options?: LoginOptions): Promise<{
35
+ credentials: StoredCredentials;
36
+ authorizationUrl: URL;
37
+ backendKind: 'keyring' | 'file';
38
+ backendPath?: string;
39
+ }>;
package/dist/auth.js ADDED
@@ -0,0 +1,225 @@
1
+ import { createServer, } from 'node:http';
2
+ import { auth, } from '@modelcontextprotocol/client';
3
+ import { accessTokenSkewMs, cliRedirectUrl, defaultMcpUrl, defaultScopes, loginTimeoutMs, } from './defaults.js';
4
+ import { createCliOAuthProvider } from './oauth-provider.js';
5
+ import { redactError } from './redact.js';
6
+ import { loadCredentials, saveCredentials, } from './store.js';
7
+ export function isAccessTokenExpired(credentials, now = Date.now()) {
8
+ if (!credentials.expiresAt)
9
+ return false;
10
+ return now + accessTokenSkewMs >= credentials.expiresAt;
11
+ }
12
+ export function credentialsFromTokens(input) {
13
+ const now = input.now ?? Date.now();
14
+ const expiresAt = typeof input.tokens.expires_in === 'number'
15
+ ? now + input.tokens.expires_in * 1000
16
+ : input.previous?.expiresAt;
17
+ return {
18
+ version: 1,
19
+ mcpUrl: input.mcpUrl,
20
+ resource: input.resource,
21
+ authorizationServerUrl: input.authorizationServerUrl,
22
+ clientId: input.client.client_id,
23
+ clientSecret: 'client_secret' in input.client
24
+ ? input.client.client_secret
25
+ : input.previous?.clientSecret,
26
+ accessToken: input.tokens.access_token,
27
+ refreshToken: input.tokens.refresh_token ?? input.previous?.refreshToken,
28
+ tokenType: input.tokens.token_type ?? 'bearer',
29
+ expiresAt,
30
+ scope: input.tokens.scope ?? input.previous?.scope,
31
+ };
32
+ }
33
+ async function persistAuthorizedSession(input) {
34
+ const tokens = await input.provider.tokens();
35
+ const client = await input.provider.clientInformation();
36
+ if (!tokens || !client) {
37
+ throw new Error('OAuth completed without tokens. Run `kody login`.');
38
+ }
39
+ const credentials = credentialsFromTokens({
40
+ mcpUrl: input.mcpUrl,
41
+ resource: input.mcpUrl,
42
+ authorizationServerUrl: tokens.issuer ??
43
+ input.previous?.authorizationServerUrl ??
44
+ new URL(input.mcpUrl).origin,
45
+ client,
46
+ tokens,
47
+ previous: input.previous,
48
+ now: input.now,
49
+ });
50
+ const saved = saveCredentials(credentials, input.backend);
51
+ return { credentials, saved };
52
+ }
53
+ export async function refreshStoredCredentials(input) {
54
+ const { credentials } = input;
55
+ if (!credentials.refreshToken) {
56
+ throw new Error('No refresh token is stored. Run `kody login`.');
57
+ }
58
+ const provider = createCliOAuthProvider({
59
+ mcpUrl: credentials.mcpUrl,
60
+ redirectUri: cliRedirectUrl(),
61
+ existing: credentials,
62
+ loadStoredTokens: true,
63
+ openBrowser: false,
64
+ expectedState: crypto.randomUUID(),
65
+ });
66
+ const result = await auth(provider, {
67
+ serverUrl: credentials.mcpUrl,
68
+ scope: defaultScopes.join(' '),
69
+ fetchFn: input.fetchFn,
70
+ });
71
+ if (result !== 'AUTHORIZED') {
72
+ throw new Error('Token refresh requires a new `kody login`.');
73
+ }
74
+ const { credentials: next } = await persistAuthorizedSession({
75
+ mcpUrl: credentials.mcpUrl,
76
+ provider,
77
+ backend: input.backend,
78
+ previous: credentials,
79
+ now: input.now,
80
+ });
81
+ return next;
82
+ }
83
+ export async function ensureFreshCredentials(input) {
84
+ const mcpUrl = input.mcpUrl ?? defaultMcpUrl;
85
+ const credentials = loadCredentials(mcpUrl, input.backend);
86
+ if (!credentials) {
87
+ throw new Error('Not logged in. Run `kody login`.');
88
+ }
89
+ if (!isAccessTokenExpired(credentials, input.now)) {
90
+ return credentials;
91
+ }
92
+ return await refreshStoredCredentials({
93
+ credentials,
94
+ backend: input.backend,
95
+ now: input.now,
96
+ fetchFn: input.fetchFn,
97
+ });
98
+ }
99
+ function startCallbackServer(redirectUri) {
100
+ return new Promise((resolve, reject) => {
101
+ const server = createServer();
102
+ const port = Number(redirectUri.port);
103
+ server.listen(port, redirectUri.hostname, () => resolve(server));
104
+ server.on('error', (error) => {
105
+ if ('code' in error && error.code === 'EADDRINUSE') {
106
+ reject(new Error(`Login callback port ${port} is in use. Stop the other listener and retry.`));
107
+ return;
108
+ }
109
+ reject(error);
110
+ });
111
+ });
112
+ }
113
+ function waitForCallback(input) {
114
+ return new Promise((resolve, reject) => {
115
+ const finish = (error, result) => {
116
+ clearTimeout(timer);
117
+ input.server.close();
118
+ if (error)
119
+ reject(error);
120
+ else
121
+ resolve(result ?? { code: '' });
122
+ };
123
+ const timer = setTimeout(() => {
124
+ finish(new Error('Timed out waiting for the browser login.'));
125
+ }, input.timeoutMs);
126
+ input.server.on('request', (request, response) => {
127
+ try {
128
+ const url = new URL(request.url ?? '/', input.redirectUri);
129
+ if (url.pathname !== input.redirectUri.pathname) {
130
+ response.writeHead(404).end('Not found');
131
+ return;
132
+ }
133
+ const error = url.searchParams.get('error');
134
+ if (error) {
135
+ const description = url.searchParams.get('error_description') ?? '';
136
+ response
137
+ .writeHead(400, { 'Content-Type': 'text/html' })
138
+ .end('<p>Authorization failed. You can close this window.</p>');
139
+ finish(new Error(description || error));
140
+ return;
141
+ }
142
+ const state = url.searchParams.get('state');
143
+ const code = url.searchParams.get('code');
144
+ const iss = url.searchParams.get('iss') ?? undefined;
145
+ if (state !== input.expectedState || !code) {
146
+ response
147
+ .writeHead(400, { 'Content-Type': 'text/html' })
148
+ .end('<p>Invalid OAuth callback. You can close this window.</p>');
149
+ finish(new Error('OAuth callback missing code or state.'));
150
+ return;
151
+ }
152
+ response
153
+ .writeHead(200, { 'Content-Type': 'text/html' })
154
+ .end('<p>Kody CLI is signed in. You can close this window.</p>');
155
+ finish(null, { code, ...(iss ? { iss } : {}) });
156
+ }
157
+ catch (error) {
158
+ finish(redactError(error));
159
+ }
160
+ });
161
+ });
162
+ }
163
+ export async function login(options = {}) {
164
+ const mcpUrl = options.mcpUrl ?? defaultMcpUrl;
165
+ const redirectUri = cliRedirectUrl();
166
+ const expectedState = crypto.randomUUID();
167
+ const server = await startCallbackServer(redirectUri);
168
+ let authorizationUrl = redirectUri;
169
+ const provider = createCliOAuthProvider({
170
+ mcpUrl,
171
+ redirectUri,
172
+ loadStoredTokens: false,
173
+ openBrowser: options.openBrowser !== false,
174
+ expectedState,
175
+ onAuthorizationUrl: (url) => {
176
+ authorizationUrl = url;
177
+ options.onAuthorizationUrl?.(url);
178
+ },
179
+ });
180
+ try {
181
+ const first = await auth(provider, {
182
+ serverUrl: mcpUrl,
183
+ scope: defaultScopes.join(' '),
184
+ fetchFn: options.fetchFn,
185
+ });
186
+ if (first !== 'AUTHORIZED') {
187
+ const callback = await waitForCallback({
188
+ server,
189
+ redirectUri,
190
+ expectedState,
191
+ timeoutMs: options.timeoutMs ?? loginTimeoutMs,
192
+ });
193
+ const exchanged = await auth(provider, {
194
+ serverUrl: mcpUrl,
195
+ authorizationCode: callback.code,
196
+ ...(callback.iss ? { iss: callback.iss } : {}),
197
+ scope: defaultScopes.join(' '),
198
+ fetchFn: options.fetchFn,
199
+ });
200
+ if (exchanged !== 'AUTHORIZED') {
201
+ throw new Error('OAuth redirect completed without tokens.');
202
+ }
203
+ }
204
+ else {
205
+ server.close();
206
+ }
207
+ const { credentials, saved } = await persistAuthorizedSession({
208
+ mcpUrl,
209
+ provider,
210
+ backend: options.backend,
211
+ now: options.now?.(),
212
+ });
213
+ return {
214
+ credentials,
215
+ authorizationUrl,
216
+ backendKind: saved.backend.kind,
217
+ backendPath: saved.backend.path,
218
+ };
219
+ }
220
+ catch (error) {
221
+ server.close();
222
+ throw redactError(error);
223
+ }
224
+ }
225
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './cli.js';
3
+ const code = await runCli();
4
+ process.exitCode = code;
5
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAA;AAC3B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAA"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ export type CommandName = 'login' | 'logout' | 'status' | 'whoami' | 'search' | 'execute' | 'skill' | 'help' | 'version';
2
+ declare function parseKnown(args: Array<string>): {
3
+ values: {
4
+ [longOption: string]: string | boolean | undefined;
5
+ } & {
6
+ help?: string | boolean | undefined;
7
+ version?: string | boolean | undefined;
8
+ json?: string | boolean | undefined;
9
+ 'mcp-url'?: string | boolean | undefined;
10
+ entity?: string | boolean | undefined;
11
+ domain?: string | boolean | undefined;
12
+ limit?: string | boolean | undefined;
13
+ code?: string | boolean | undefined;
14
+ file?: string | boolean | undefined;
15
+ params?: string | boolean | undefined;
16
+ 'conversation-id'?: string | boolean | undefined;
17
+ project?: string | boolean | undefined;
18
+ 'no-browser'?: string | boolean | undefined;
19
+ };
20
+ positionals: string[];
21
+ };
22
+ export declare function resolveCommand(argv: Array<string>): {
23
+ command: CommandName;
24
+ positionals: Array<string>;
25
+ values: ReturnType<typeof parseKnown>['values'];
26
+ };
27
+ export declare function runCli(argv?: Array<string>, io?: {
28
+ stdout?: (text: string) => void;
29
+ stderr?: (text: string) => void;
30
+ }): Promise<number>;
31
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,206 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { defaultMcpUrl, modernMcpProtocolVersion } from './defaults.js';
4
+ import { usage } from './help.js';
5
+ import { ensureFreshCredentials, login } from './auth.js';
6
+ import { deleteCredentials, loadCredentials } from './store.js';
7
+ import { callKodyTool, formatToolResult, listKodyTools } from './mcp.js';
8
+ import { installSkill } from './skill.js';
9
+ import { readPackageVersion } from './package-info.js';
10
+ import { redactError } from './redact.js';
11
+ function mcpUrlFrom(values) {
12
+ return values.mcpUrl || process.env.KODY_MCP_URL || defaultMcpUrl;
13
+ }
14
+ function parseKnown(args) {
15
+ return parseArgs({
16
+ args,
17
+ allowPositionals: true,
18
+ strict: false,
19
+ options: {
20
+ help: { type: 'boolean', short: 'h' },
21
+ version: { type: 'boolean', short: 'v' },
22
+ json: { type: 'boolean' },
23
+ 'mcp-url': { type: 'string' },
24
+ entity: { type: 'string' },
25
+ domain: { type: 'string' },
26
+ limit: { type: 'string' },
27
+ code: { type: 'string' },
28
+ file: { type: 'string' },
29
+ params: { type: 'string' },
30
+ 'conversation-id': { type: 'string' },
31
+ project: { type: 'boolean' },
32
+ 'no-browser': { type: 'boolean' },
33
+ },
34
+ });
35
+ }
36
+ export function resolveCommand(argv) {
37
+ const { positionals, values } = parseKnown(argv);
38
+ if (values.help && positionals.length === 0) {
39
+ return { command: 'help', positionals, values };
40
+ }
41
+ if (values.version && positionals.length === 0) {
42
+ return { command: 'version', positionals, values };
43
+ }
44
+ const raw = positionals[0];
45
+ if (!raw)
46
+ return { command: 'help', positionals, values };
47
+ switch (raw) {
48
+ case 'login':
49
+ case 'logout':
50
+ case 'status':
51
+ case 'whoami':
52
+ case 'search':
53
+ case 'execute':
54
+ case 'skill':
55
+ case 'help':
56
+ case 'version':
57
+ return { command: raw, positionals: positionals.slice(1), values };
58
+ default:
59
+ throw new Error(`Unknown command "${raw}".\n\n${usage}`);
60
+ }
61
+ }
62
+ export async function runCli(argv = process.argv.slice(2), io = {}) {
63
+ const write = io.stdout ?? ((text) => process.stdout.write(text));
64
+ const writeErr = io.stderr ?? ((text) => process.stderr.write(text));
65
+ try {
66
+ const parsed = resolveCommand(argv);
67
+ if (parsed.values.help && parsed.command !== 'help') {
68
+ write(usage);
69
+ return 0;
70
+ }
71
+ return await dispatch(parsed, write);
72
+ }
73
+ catch (error) {
74
+ writeErr(`${redactError(error).message}\n`);
75
+ return 1;
76
+ }
77
+ }
78
+ async function dispatch(parsed, write) {
79
+ const mcpUrl = mcpUrlFrom({
80
+ mcpUrl: typeof parsed.values['mcp-url'] === 'string' ? parsed.values['mcp-url'] : undefined,
81
+ });
82
+ const json = parsed.values.json === true;
83
+ switch (parsed.command) {
84
+ case 'help':
85
+ write(usage);
86
+ return 0;
87
+ case 'version':
88
+ write(`${readPackageVersion()}\n`);
89
+ return 0;
90
+ case 'login': {
91
+ write('Opening the Kody login page in your browser…\n');
92
+ const result = await login({
93
+ mcpUrl,
94
+ openBrowser: parsed.values['no-browser'] !== true,
95
+ onAuthorizationUrl: (url) => {
96
+ write(`If the browser does not open, visit:\n${url.href}\n`);
97
+ },
98
+ });
99
+ write(`Logged in to ${result.credentials.mcpUrl}.\n`);
100
+ if (result.backendKind === 'file' && result.backendPath) {
101
+ write(`OS keychain was unavailable; credentials saved at ${result.backendPath} (mode 0600).\n`);
102
+ }
103
+ else {
104
+ write('Credentials stored in the OS keychain.\n');
105
+ }
106
+ return 0;
107
+ }
108
+ case 'logout': {
109
+ const result = deleteCredentials(mcpUrl);
110
+ write(result.deleted ? 'Logged out.\n' : 'No stored credentials.\n');
111
+ return 0;
112
+ }
113
+ case 'status': {
114
+ const credentials = loadCredentials(mcpUrl);
115
+ if (!credentials) {
116
+ write('Not logged in.\n');
117
+ return 1;
118
+ }
119
+ const expires = credentials.expiresAt
120
+ ? new Date(credentials.expiresAt).toISOString()
121
+ : 'unknown';
122
+ write([
123
+ `mcp: ${credentials.mcpUrl}`,
124
+ `logged in: yes`,
125
+ `access token expires: ${expires}`,
126
+ `refresh token: ${credentials.refreshToken ? 'yes' : 'no'}`,
127
+ `scope: ${credentials.scope ?? 'unknown'}`,
128
+ '',
129
+ ].join('\n'));
130
+ return 0;
131
+ }
132
+ case 'whoami': {
133
+ const credentials = await ensureFreshCredentials({ mcpUrl });
134
+ const tools = await listKodyTools({ mcpUrl });
135
+ if (json) {
136
+ write(`${JSON.stringify({
137
+ mcpUrl: credentials.mcpUrl,
138
+ protocol: modernMcpProtocolVersion,
139
+ scope: credentials.scope ?? null,
140
+ tools: tools.map((tool) => tool.name),
141
+ }, null, 2)}\n`);
142
+ return 0;
143
+ }
144
+ write(`Connected to ${credentials.mcpUrl} (${modernMcpProtocolVersion})\nTools: ${tools.map((tool) => tool.name).join(', ') || '(none)'}\n`);
145
+ return 0;
146
+ }
147
+ case 'search': {
148
+ const query = parsed.positionals.join(' ').trim();
149
+ const args = {};
150
+ if (query)
151
+ args.query = query;
152
+ if (typeof parsed.values.entity === 'string')
153
+ args.entity = parsed.values.entity;
154
+ if (typeof parsed.values.domain === 'string')
155
+ args.domain = parsed.values.domain;
156
+ if (typeof parsed.values.limit === 'string')
157
+ args.limit = Number(parsed.values.limit);
158
+ const result = await callKodyTool({ name: 'search', args, mcpUrl });
159
+ write(formatToolResult(result, json));
160
+ return result.isError ? 1 : 0;
161
+ }
162
+ case 'execute': {
163
+ const code = typeof parsed.values.code === 'string'
164
+ ? parsed.values.code
165
+ : typeof parsed.values.file === 'string'
166
+ ? parsed.values.file === '-'
167
+ ? await readStdin()
168
+ : await readFile(parsed.values.file, 'utf8')
169
+ : parsed.positionals.join('\n').trim();
170
+ if (!code) {
171
+ throw new Error('Provide --code, --file, or a module string.');
172
+ }
173
+ const args = { code };
174
+ if (typeof parsed.values.params === 'string') {
175
+ args.params = JSON.parse(parsed.values.params);
176
+ }
177
+ if (typeof parsed.values['conversation-id'] === 'string') {
178
+ args.conversationId = parsed.values['conversation-id'];
179
+ }
180
+ const result = await callKodyTool({ name: 'execute', args, mcpUrl });
181
+ write(formatToolResult(result, json));
182
+ return result.isError ? 1 : 0;
183
+ }
184
+ case 'skill': {
185
+ const action = parsed.positionals[0] ?? 'install';
186
+ if (action !== 'install') {
187
+ throw new Error('Usage: kody skill install [--project]');
188
+ }
189
+ const targets = await installSkill({ project: parsed.values.project === true });
190
+ write(`Installed the Kody skill to:\n${targets.map((target) => `- ${target.host}: ${target.path}`).join('\n')}\n`);
191
+ return 0;
192
+ }
193
+ default: {
194
+ const exhaustive = parsed.command;
195
+ throw new Error(`Unhandled command: ${String(exhaustive)}`);
196
+ }
197
+ }
198
+ }
199
+ async function readStdin() {
200
+ const chunks = [];
201
+ for await (const chunk of process.stdin) {
202
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
203
+ }
204
+ return Buffer.concat(chunks).toString('utf8');
205
+ }
206
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare const defaultMcpUrl = "https://kody.codes/mcp";
2
+ /** Pin to Kody's stateless `/mcp` lane. */
3
+ export declare const modernMcpProtocolVersion = "2026-07-28";
4
+ export declare const defaultScopes: readonly ["profile", "email"];
5
+ export declare const keyringService = "kody.codes";
6
+ export declare const loginTimeoutMs: number;
7
+ export declare const accessTokenSkewMs = 60000;
8
+ export declare const cliName = "@kodycodes/cli";
9
+ export declare const cliClientUri = "https://github.com/kody-bot/cli";
10
+ /** Fixed loopback port so CIMD can list an exact redirect URI. */
11
+ export declare const oauthCallbackPort = 43742;
12
+ export declare const cliClientIdMetadataPath = "/oauth/cli-client-metadata.json";
13
+ export declare function cliClientMetadataUrl(mcpUrl: string): string;
14
+ export declare function cliRedirectUrl(port?: number): URL;