@tiny-fish/cli 0.45.2-next.354 → 0.45.2-next.357

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.
Files changed (48) hide show
  1. package/dist/commands/config-claude.js +1 -1
  2. package/dist/commands/connect.d.ts +0 -37
  3. package/dist/commands/connect.js +29 -846
  4. package/dist/commands/onboard.js +1 -1
  5. package/dist/lib/auth.d.ts +4 -0
  6. package/dist/lib/auth.js +26 -4
  7. package/dist/lib/config/cline-config.d.ts +4 -0
  8. package/dist/lib/config/cline-config.js +36 -0
  9. package/dist/lib/config/connect-config-file.d.ts +76 -0
  10. package/dist/lib/config/connect-config-file.js +241 -0
  11. package/dist/lib/{hermes-config.js → config/hermes-config.js} +2 -2
  12. package/dist/lib/{mcp-json-config.d.ts → config/mcp-json-config.d.ts} +2 -0
  13. package/dist/lib/{mcp-json-config.js → config/mcp-json-config.js} +11 -5
  14. package/dist/lib/{omp-config.js → config/omp-config.js} +2 -2
  15. package/dist/lib/{pi-config.js → config/pi-config.js} +1 -1
  16. package/dist/lib/connect-all-uninstall.js +3 -3
  17. package/dist/lib/connect-all.js +1 -1
  18. package/dist/lib/connect-clients.d.ts +1 -1
  19. package/dist/lib/connect-clients.js +8 -1
  20. package/dist/lib/connect-harness.d.ts +4 -0
  21. package/dist/lib/connect-harness.js +76 -0
  22. package/dist/lib/connect-native.d.ts +4 -0
  23. package/dist/lib/connect-native.js +389 -0
  24. package/dist/lib/connect-openclaw.d.ts +3 -0
  25. package/dist/lib/connect-openclaw.js +71 -0
  26. package/dist/lib/connect-steps.d.ts +38 -0
  27. package/dist/lib/connect-steps.js +104 -0
  28. package/dist/lib/doctor-checks.js +1 -1
  29. package/dist/lib/doctor-repairs.js +1 -1
  30. package/dist/lib/doctor-report.d.ts +6 -0
  31. package/dist/lib/harness-detect.js +7 -3
  32. package/dist/lib/harness-spec.d.ts +23 -2
  33. package/dist/lib/harness-spec.js +23 -0
  34. package/dist/lib/harness.js +5 -0
  35. package/dist/lib/hermes-plugin.js +1 -1
  36. package/dist/lib/registration-detect.js +22 -5
  37. package/dist/lib/setup-telemetry.d.ts +10 -0
  38. package/dist/lib/skill-paths.js +1 -0
  39. package/package.json +1 -1
  40. /package/dist/lib/{claude-config.d.ts → config/claude-config.d.ts} +0 -0
  41. /package/dist/lib/{claude-config.js → config/claude-config.js} +0 -0
  42. /package/dist/lib/{command-code-config.d.ts → config/command-code-config.d.ts} +0 -0
  43. /package/dist/lib/{command-code-config.js → config/command-code-config.js} +0 -0
  44. /package/dist/lib/{cursor-config.d.ts → config/cursor-config.d.ts} +0 -0
  45. /package/dist/lib/{cursor-config.js → config/cursor-config.js} +0 -0
  46. /package/dist/lib/{hermes-config.d.ts → config/hermes-config.d.ts} +0 -0
  47. /package/dist/lib/{omp-config.d.ts → config/omp-config.d.ts} +0 -0
  48. /package/dist/lib/{pi-config.d.ts → config/pi-config.d.ts} +0 -0
@@ -0,0 +1,104 @@
1
+ import { verifyMcpHealth } from './verify.js';
2
+ import { installTinyFishCli } from './cli-install.js';
3
+ import { createStdinPrompt, runCliFallback } from './connect-fallback.js';
4
+ import { detectHumanInitiated } from './harness.js';
5
+ import { errLine } from './output.js';
6
+ import { ConnectInterruptedError, ConnectStepError, HoistedFailureReportedError, finishSetupCommand, requireCommandSupport, settle, stageDurationOf, withStageDuration, } from './connect-runtime.js';
7
+ export async function requireKeylessMcp(mcpUrl) {
8
+ if ((await verifyMcpHealth(mcpUrl, true)).ok)
9
+ return;
10
+ throw new ConnectStepError('TinyFish keyless Search is unavailable', 'invalid_config');
11
+ }
12
+ function isMissingHarness(error) {
13
+ return error instanceof ConnectStepError && error.failureReason === 'harness_not_installed';
14
+ }
15
+ /** Undefined means the rescue ran; the caller returns immediately. */
16
+ export async function requireSupportOrRescue(client, connectClient, state, telemetry, options) {
17
+ try {
18
+ return requireCommandSupport(client);
19
+ }
20
+ catch (error) {
21
+ if (!options.fallbackWhenMissing || !isMissingHarness(error))
22
+ throw error;
23
+ await runMissingHarnessFallback(client.displayName, connectClient, state, telemetry, options);
24
+ return undefined;
25
+ }
26
+ }
27
+ // The harness attempt stays failed; the rescue rides fallback_outcome (PF-3707).
28
+ async function runMissingHarnessFallback(displayName, connectClient, state, telemetry, options) {
29
+ // Stamped before any step: Ctrl+C settles before an outcome exists.
30
+ telemetry.setFallbackOutcome('abandoned');
31
+ errLine(`${displayName} was not found on PATH. Setting up the TinyFish CLI instead.`);
32
+ const outcome = await runCliFallback({
33
+ apiKey: options.apiKey,
34
+ verbose: options.verbose ?? false,
35
+ prompt: detectHumanInitiated() ? createStdinPrompt() : undefined,
36
+ retryCommand: `npx @tiny-fish/cli connect ${connectClient}`,
37
+ hooks: {
38
+ // Terminal detail is explicit below; abort rows still name the step.
39
+ onStepStart: (stage) => {
40
+ state.stage = stage;
41
+ },
42
+ onStepDone: (phase) => telemetry.track('checkpoint', { phase }),
43
+ },
44
+ });
45
+ telemetry.setFallbackOutcome(outcome);
46
+ // Never `completed`: dashboards read that as "the harness install worked".
47
+ settle(state, telemetry, 'failed', {
48
+ failedStage: 'prerequisite_check',
49
+ failureReason: 'harness_not_installed',
50
+ });
51
+ if (outcome !== 'cli_verified') {
52
+ process.exitCode = 1;
53
+ return;
54
+ }
55
+ errLine('The TinyFish CLI is installed and working.');
56
+ errLine('Using a different agent? Run: tinyfish connect --all');
57
+ }
58
+ /** Fails on a carried failure; only the first take reports anything. */
59
+ function takeHoistedCliInstall(take, telemetry) {
60
+ const { outcome, firstTake } = take();
61
+ if (!outcome.ok) {
62
+ // Late takers fail too; only the first reports the install.
63
+ if (!firstTake)
64
+ throw new HoistedFailureReportedError(outcome.error.message);
65
+ throw withStageDuration(outcome.error, outcome.durationMs);
66
+ }
67
+ if (firstTake) {
68
+ telemetry.track('checkpoint', {
69
+ phase: 'cli_installed',
70
+ stageDurationMs: outcome.durationMs,
71
+ });
72
+ }
73
+ }
74
+ /** Consumes the `--all` hoist when present; installs inline otherwise. */
75
+ export function runCliInstallStep(options, telemetry) {
76
+ if (options.hoistedCliInstall) {
77
+ takeHoistedCliInstall(options.hoistedCliInstall, telemetry);
78
+ return;
79
+ }
80
+ installTinyFishCli({ verbose: options.verbose ?? false, announce: true });
81
+ telemetry.track('checkpoint', { phase: 'cli_installed' });
82
+ }
83
+ export function walkthroughPhase(outcome) {
84
+ return outcome === 'printed' ? 'walkthrough_prompt_printed' : 'walkthrough_launched';
85
+ }
86
+ export function finishSetupHint(connectClient) {
87
+ return `Finish setup with: ${finishSetupCommand(connectClient)}`;
88
+ }
89
+ /** Warn + report post_install_failed; interrupts are abandonment, not failure. */
90
+ export function trackPostInstallFailure(displayName, state, telemetry, error) {
91
+ if (error instanceof ConnectInterruptedError)
92
+ return;
93
+ // An earlier harness already owns the shared install's failure record.
94
+ if (!(error instanceof HoistedFailureReportedError)) {
95
+ telemetry.track('post_install_failed', {
96
+ failedStage: state.stage,
97
+ failureReason: error instanceof ConnectStepError ? error.failureReason : 'unexpected_error',
98
+ failureDetail: error instanceof ConnectStepError ? (error.failureDetail ?? error.message) : undefined,
99
+ stageDurationMs: stageDurationOf(error),
100
+ });
101
+ }
102
+ errLine(`The ${displayName} MCP connection succeeded, but a finishing step ` +
103
+ `(${state.stage}) failed: ${error instanceof Error ? error.message : String(error)}`);
104
+ }
@@ -4,7 +4,7 @@ import { AuthMode, Registered } from './harness-detect.js';
4
4
  import { resolveHermesHome } from './hermes-env.js';
5
5
  import { hermesWebBackendsOurs, readHermesPluginStatus, } from './hermes-plugin.js';
6
6
  import { endpointOf, isDefaultEndpoint } from './mcp-endpoint.js';
7
- import { PI_ADAPTER_INSTALL_COMMAND, piMcpAdapterState } from './pi-config.js';
7
+ import { PI_ADAPTER_INSTALL_COMMAND, piMcpAdapterState } from './config/pi-config.js';
8
8
  import { boundedVersion } from './output.js';
9
9
  import { verifyMcpHealth } from './verify.js';
10
10
  // A green auth mode with a red auth call proves nothing, so the call's verdict gates the claim.
@@ -1,5 +1,5 @@
1
1
  import spawn from 'cross-spawn';
2
- import { connectHarness } from '../commands/connect.js';
2
+ import { connectHarness } from './connect-harness.js';
3
3
  import { OAUTH_SIGN_IN_TIMEOUT_MS } from './connect-all-auth.js';
4
4
  import { Registered } from './harness-detect.js';
5
5
  import { detectHumanInitiated } from './harness.js';
@@ -43,6 +43,7 @@ declare const doctorCheckSchema: z.ZodObject<{
43
43
  "command-code": "command-code";
44
44
  opencode: "opencode";
45
45
  pi: "pi";
46
+ cline: "cline";
46
47
  "claude-code": "claude-code";
47
48
  }>>;
48
49
  scope: z.ZodEnum<{
@@ -62,6 +63,7 @@ declare const doctorHarnessSchema: z.ZodObject<{
62
63
  "command-code": "command-code";
63
64
  opencode: "opencode";
64
65
  pi: "pi";
66
+ cline: "cline";
65
67
  "claude-code": "claude-code";
66
68
  }>;
67
69
  detected: z.ZodBoolean;
@@ -91,6 +93,7 @@ declare const doctorRepairSchema: z.ZodObject<{
91
93
  "command-code": "command-code";
92
94
  opencode: "opencode";
93
95
  pi: "pi";
96
+ cline: "cline";
94
97
  "claude-code": "claude-code";
95
98
  }>>;
96
99
  command: z.ZodString;
@@ -129,6 +132,7 @@ export declare const doctorReportSchema: z.ZodObject<{
129
132
  "command-code": "command-code";
130
133
  opencode: "opencode";
131
134
  pi: "pi";
135
+ cline: "cline";
132
136
  "claude-code": "claude-code";
133
137
  }>>;
134
138
  scope: z.ZodEnum<{
@@ -148,6 +152,7 @@ export declare const doctorReportSchema: z.ZodObject<{
148
152
  "command-code": "command-code";
149
153
  opencode: "opencode";
150
154
  pi: "pi";
155
+ cline: "cline";
151
156
  "claude-code": "claude-code";
152
157
  }>;
153
158
  detected: z.ZodBoolean;
@@ -177,6 +182,7 @@ export declare const doctorReportSchema: z.ZodObject<{
177
182
  "command-code": "command-code";
178
183
  opencode: "opencode";
179
184
  pi: "pi";
185
+ cline: "cline";
180
186
  "claude-code": "claude-code";
181
187
  }>>;
182
188
  command: z.ZodString;
@@ -3,7 +3,8 @@ import * as os from 'os';
3
3
  import * as path from 'path';
4
4
  import which from 'which';
5
5
  import { ALL_HARNESSES, harnessSpec } from './harness-spec.js';
6
- import { piAgentDir, piBinaryIsPi } from './pi-config.js';
6
+ import { clineConfigDir } from './config/cline-config.js';
7
+ import { piAgentDir, piBinaryIsPi } from './config/pi-config.js';
7
8
  export { ALL_HARNESSES };
8
9
  export const HARNESS_DISPLAY_NAMES = Object.fromEntries(ALL_HARNESSES.map((harness) => [harness, harnessSpec(harness).displayName]));
9
10
  export const RELOAD_ACTION = Object.fromEntries(ALL_HARNESSES.map((harness) => [harness, harnessSpec(harness).reloadAction]));
@@ -33,8 +34,11 @@ export function commandOnPath(command) {
33
34
  return false;
34
35
  }
35
36
  }
36
- // PI_CODING_AGENT_DIR moves pi's dir; a guessed path would be written unread.
37
- const CONFIG_PATH_RESOLVERS = { pi: piAgentDir };
37
+ // PI_CODING_AGENT_DIR and CLINE_DIR move these dirs; a guessed path would be written unread.
38
+ const CONFIG_PATH_RESOLVERS = {
39
+ cline: clineConfigDir,
40
+ pi: piAgentDir,
41
+ };
38
42
  export function harnessConfigPath(harness) {
39
43
  const resolved = CONFIG_PATH_RESOLVERS[harness]?.();
40
44
  return resolved ?? path.join(os.homedir(), harnessSpec(harness).configDir); // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
@@ -1,5 +1,5 @@
1
1
  /** Our skill-path slugs, inherited from the `skills` CLI era. */
2
- export type SkillAgent = 'claude-code' | 'codex' | 'command-code' | 'cursor' | 'hermes-agent' | 'opencode' | 'pi';
2
+ export type SkillAgent = 'claude-code' | 'cline' | 'codex' | 'command-code' | 'cursor' | 'hermes-agent' | 'opencode' | 'pi';
3
3
  export interface HarnessSupportCheck {
4
4
  args: string[];
5
5
  /** Missing → nothing can work; setup fails. */
@@ -114,6 +114,27 @@ export declare const HARNESS_SPECS: {
114
114
  label: string;
115
115
  }[];
116
116
  };
117
+ cline: {
118
+ command: string;
119
+ displayName: string;
120
+ configDir: string;
121
+ reloadAction: string;
122
+ skillAgent: "cline";
123
+ nonInteractiveAdd: true;
124
+ keyRequired: true;
125
+ supportCheck: {
126
+ args: string[];
127
+ patterns: RegExp[];
128
+ keyAuthPattern: RegExp;
129
+ unavailableMessage: string;
130
+ };
131
+ urlStyle: "positional";
132
+ addFlags: string[];
133
+ header: {
134
+ name: string;
135
+ sep: ": ";
136
+ };
137
+ };
117
138
  codex: {
118
139
  command: string;
119
140
  displayName: string;
@@ -286,4 +307,4 @@ export type NonNativeHarness = {
286
307
  [K in Harness]: 'urlStyle' extends keyof (typeof HARNESS_SPECS)[K] ? never : 'keyRequired' extends keyof (typeof HARNESS_SPECS)[K] ? never : K;
287
308
  }[Harness];
288
309
  /** Native MCP harnesses generate an add; key-only ones generate only the keyed form. */
289
- export declare const NATIVE_HARNESSES: ("openclaw" | "omp" | "grok" | "cursor" | "codex" | "hermes" | "command-code" | "opencode" | "pi" | "claude-code")[];
310
+ export declare const NATIVE_HARNESSES: ("openclaw" | "omp" | "grok" | "cursor" | "codex" | "hermes" | "command-code" | "opencode" | "pi" | "cline" | "claude-code")[];
@@ -46,6 +46,9 @@ const OPENCODE_MODEL_NOTE = 'Note: TinyFish runs on tool calls, so OpenCode need
46
46
  'models (e.g. Nano Banana Pro) will show "No endpoints found that support tool use" — switch ' +
47
47
  "OpenCode's model if the walkthrough can't start.";
48
48
  const HERMES_RESTART_NOTE = 'Restart your Hermes session to pick up TinyFish — Hermes discovers MCP servers at startup.';
49
+ const CLINE_MCP_ADD_UNAVAILABLE_MESSAGE = 'Could not confirm this Cline installation supports non-interactive MCP setup: `cline mcp add ' +
50
+ '--help` did not list `--transport` and `--yes`. Update Cline with `cline --update` and retry.' +
51
+ SUPPORT_CHECK_DEBUG_HINT;
49
52
  const COMMAND_CODE_ADD_JSON_UNAVAILABLE_MESSAGE = 'Could not confirm this Command Code installation supports keyed MCP setup: `commandcode mcp ' +
50
53
  '--help` did not list `add-json`. Run `commandcode update` and retry.' +
51
54
  SUPPORT_CHECK_DEBUG_HINT;
@@ -87,6 +90,26 @@ export const HARNESS_SPECS = {
87
90
  },
88
91
  ],
89
92
  },
93
+ cline: {
94
+ command: 'cline',
95
+ displayName: 'Cline',
96
+ configDir: '.cline',
97
+ reloadAction: 'restart it',
98
+ skillAgent: 'cline',
99
+ nonInteractiveAdd: true,
100
+ // Key-only by decision: TinyFish never sends CLI-harness users through OAuth.
101
+ keyRequired: true,
102
+ supportCheck: {
103
+ args: ['mcp', 'add', '--help'],
104
+ // Without `--yes` the add opens a wizard and exits non-zero off a TTY.
105
+ patterns: [/--transport(?:[\s<=]|$)/m, /--yes(?:[\s<=]|$)/m],
106
+ keyAuthPattern: HEADER_FLAG,
107
+ unavailableMessage: CLINE_MCP_ADD_UNAVAILABLE_MESSAGE,
108
+ },
109
+ urlStyle: 'positional',
110
+ addFlags: ['--transport', 'http', '--yes'],
111
+ header: { name: 'X-API-Key', sep: ': ' },
112
+ },
90
113
  codex: {
91
114
  command: 'codex',
92
115
  displayName: 'Codex',
@@ -32,6 +32,11 @@ const HARNESS_FINGERPRINTS = [
32
32
  { name: 'opencode', matches: (env) => Boolean(env['OPENCODE']) },
33
33
  // Observed: pi launched from Claude Code inherits CLAUDECODE=1.
34
34
  { name: 'pi', matches: (env) => env['PI_CODING_AGENT'] === 'true' },
35
+ // Runtime-only markers; users export CLINE_API_KEY, so no prefix match.
36
+ {
37
+ name: 'cline',
38
+ matches: (env) => Boolean(env['CLINE_CONNECTOR_CLI_LAUNCH'] || env['CLINE_WRAPPER_PATH']),
39
+ },
35
40
  {
36
41
  name: 'claude-code',
37
42
  matches: (env) => env['CLAUDECODE'] === '1' || Boolean(env['CLAUDE_CODE_ENTRYPOINT']),
@@ -7,7 +7,7 @@ import { z } from 'zod';
7
7
  import { capturedOutput, replay, SKILL_INSTALL_TIMEOUT_MS, STEP_MAX_BUFFER, } from './cli-install.js';
8
8
  import { commandNotFound, ConnectStepError, spawnStepError, throwIfInterrupted, } from './connect-runtime.js';
9
9
  import { HARNESS_PROBE_TIMEOUT_MS, TINYFISH_ACCESS_MODE_HEADER, TINYFISH_KEYLESS_ACCESS_MODE, } from './constants.js';
10
- import { HERMES_HEADER_TEMPLATE, HERMES_MCP_SERVER_KEY } from './hermes-config.js';
10
+ import { HERMES_HEADER_TEMPLATE, HERMES_MCP_SERVER_KEY } from './config/hermes-config.js';
11
11
  import { errLine, parseJson } from './output.js';
12
12
  // Resolved at connect time, so plugin releases need no CLI release.
13
13
  export const HERMES_PLUGIN_PACKAGE = '@tiny-fish/hermes';
@@ -6,12 +6,13 @@ import { loadConfig, matchesCliKey } from './auth.js';
6
6
  import { NATIVE_BY_HARNESS } from './connect-clients.js';
7
7
  import { HARNESS_PROBE_TIMEOUT_MS } from './constants.js';
8
8
  import { errLine } from './output.js';
9
- import { readCommandCodeTinyfishEntry } from './command-code-config.js';
10
- import { readCursorTinyfishEntry } from './cursor-config.js';
11
- import { readOmpTinyfishEntry } from './omp-config.js';
12
- import { readPiTinyfishEntry } from './pi-config.js';
9
+ import { readClineTinyfishEntry } from './config/cline-config.js';
10
+ import { readCommandCodeTinyfishEntry } from './config/command-code-config.js';
11
+ import { readCursorTinyfishEntry } from './config/cursor-config.js';
12
+ import { readOmpTinyfishEntry } from './config/omp-config.js';
13
+ import { readPiTinyfishEntry } from './config/pi-config.js';
13
14
  import { readHermesKey, resolveHermesHome } from './hermes-env.js';
14
- import { readHermesEntry } from './hermes-config.js';
15
+ import { readHermesEntry } from './config/hermes-config.js';
15
16
  import { detectInstalledHarnesses, harnessConfigPath, harnessDisplayPath, AuthMode, Registered, } from './harness-detect.js';
16
17
  const NOT_REGISTERED = Object.freeze({
17
18
  registered: Registered.No,
@@ -279,6 +280,21 @@ function probeCodex() {
279
280
  ...(envVar ? envKeyVerdict(envVar) : {}),
280
281
  };
281
282
  }
283
+ // No `cline mcp list`, so the settings file is the only registration evidence.
284
+ function probeCline() {
285
+ const entry = readClineTinyfishEntry();
286
+ if (entry.error) {
287
+ return unverified('cline_mcp_settings.json exists but could not be read or parsed');
288
+ }
289
+ if (!entry.present)
290
+ return NOT_REGISTERED;
291
+ return {
292
+ registered: Registered.Yes,
293
+ authMode: entry.hasApiKeyHeader ? AuthMode.ApiKey : AuthMode.Unknown,
294
+ ...(entry.url ? { registeredUrl: entry.url } : {}),
295
+ ...(entry.keyMatchesCliKey ? { keyMatchesCliKey: true } : {}),
296
+ };
297
+ }
282
298
  function probeCommandCode() {
283
299
  const entry = readCommandCodeTinyfishEntry();
284
300
  if (entry.error)
@@ -523,6 +539,7 @@ function probeGrok() {
523
539
  }
524
540
  const PROBES = {
525
541
  'claude-code': () => fromMcpGet('claude'),
542
+ cline: probeCline,
526
543
  codex: probeCodex,
527
544
  'command-code': probeCommandCode,
528
545
  cursor: probeCursor,
@@ -31,6 +31,7 @@ declare const harnessResultSchema: z.ZodObject<{
31
31
  "command-code": "command-code";
32
32
  opencode: "opencode";
33
33
  pi: "pi";
34
+ cline: "cline";
34
35
  "claude-code": "claude-code";
35
36
  }>;
36
37
  detected: z.ZodBoolean;
@@ -67,6 +68,7 @@ export declare const setupCompletedPayloadSchema: z.ZodObject<{
67
68
  "command-code": "command-code";
68
69
  opencode: "opencode";
69
70
  pi: "pi";
71
+ cline: "cline";
70
72
  "claude-code": "claude-code";
71
73
  }>;
72
74
  detected: z.ZodBoolean;
@@ -130,6 +132,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
130
132
  "command-code": "command-code";
131
133
  opencode: "opencode";
132
134
  pi: "pi";
135
+ cline: "cline";
133
136
  "claude-code": "claude-code";
134
137
  all: "all";
135
138
  }>;
@@ -145,6 +148,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
145
148
  "command-code": "command-code";
146
149
  opencode: "opencode";
147
150
  pi: "pi";
151
+ cline: "cline";
148
152
  "claude-code": "claude-code";
149
153
  }>>;
150
154
  harnesses: z.ZodArray<z.ZodObject<{
@@ -158,6 +162,7 @@ declare const doctorCompletedPayloadSchema: z.ZodObject<{
158
162
  "command-code": "command-code";
159
163
  opencode: "opencode";
160
164
  pi: "pi";
165
+ cline: "cline";
161
166
  "claude-code": "claude-code";
162
167
  }>;
163
168
  detected: z.ZodBoolean;
@@ -200,6 +205,7 @@ declare const doctorCouldNotRunPayloadSchema: z.ZodObject<{
200
205
  "command-code": "command-code";
201
206
  opencode: "opencode";
202
207
  pi: "pi";
208
+ cline: "cline";
203
209
  "claude-code": "claude-code";
204
210
  all: "all";
205
211
  }>;
@@ -238,6 +244,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
238
244
  "command-code": "command-code";
239
245
  opencode: "opencode";
240
246
  pi: "pi";
247
+ cline: "cline";
241
248
  "claude-code": "claude-code";
242
249
  all: "all";
243
250
  }>;
@@ -253,6 +260,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
253
260
  "command-code": "command-code";
254
261
  opencode: "opencode";
255
262
  pi: "pi";
263
+ cline: "cline";
256
264
  "claude-code": "claude-code";
257
265
  }>>;
258
266
  harnesses: z.ZodArray<z.ZodObject<{
@@ -266,6 +274,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
266
274
  "command-code": "command-code";
267
275
  opencode: "opencode";
268
276
  pi: "pi";
277
+ cline: "cline";
269
278
  "claude-code": "claude-code";
270
279
  }>;
271
280
  detected: z.ZodBoolean;
@@ -307,6 +316,7 @@ declare const doctorPayloadSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
307
316
  "command-code": "command-code";
308
317
  opencode: "opencode";
309
318
  pi: "pi";
319
+ cline: "cline";
310
320
  "claude-code": "claude-code";
311
321
  all: "all";
312
322
  }>;
@@ -14,6 +14,7 @@ const SKILL_DIR_BY_AGENT = {
14
14
  'claude-code': () => path.join(agentHome('CLAUDE_CONFIG_DIR', '.claude'), 'skills'),
15
15
  // The env value, not resolveHermesHome(): skills@1.5.15 reads $HERMES_HOME directly.
16
16
  'hermes-agent': () => path.join(agentHome('HERMES_HOME', '.hermes'), 'skills'),
17
+ cline: canonicalSkillsDir,
17
18
  codex: canonicalSkillsDir,
18
19
  // Not the canonical dir: `skills` writes this one under the harness's own config dir.
19
20
  'command-code': () => path.join(os.homedir(), '.commandcode', 'skills'), // nosemgrep: path-join-resolve-traversal -- fixed dir names under os.homedir()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiny-fish/cli",
3
- "version": "0.45.2-next.354",
3
+ "version": "0.45.2-next.357",
4
4
  "description": "TinyFish CLI — run web automations from your terminal",
5
5
  "type": "module",
6
6
  "bin": {