1import { SERVER_VERSION } from "./version.ts";
2import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3import * as NodeServices from "@effect/platform-node/NodeServices";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6import { Argument, Command } from "effect/cli";
7import * as CliError from "effect/cli/CliError";
8
9import * as NetService from "@t3tools/shared/Net";
10import { acpMcpBridgeCommand, acpMcpCallCommand } from "./cli/acpMcpBridge.ts";
11import { authCommand } from "./cli/auth.ts";
12import { appCommand } from "./cli/app.ts";
13import { browserCommand } from "./cli/browser.ts";
14import { connectCommand } from "./cli/connect.ts";
15import { pairCommand } from "./cli/pair.ts";
16import { hasCloudPublicConfig } from "./cloud/publicConfig.ts";
17import { sharedServerCommandFlags } from "./cli/config.ts";
18import { projectCommand } from "./cli/project.ts";
19import { runDefaultServerCommand, serveCommand, startCommand } from "./cli/server.ts";
20import { updateCommand } from "./cli/update.ts";
21import { uninstallCommand } from "./cli/uninstall.ts";
22import { serviceLauncherCommand } from "./cli/serviceLauncher.ts";
23import { claudeHistoryCommand } from "./cli/claudeHistory.ts";
24import { sshHelperCommand } from "./cli/sshHelper.ts";
25import { serviceCommand } from "./cli/service.ts";
26import { servicePreflightCommand } from "./cli/servicePreflight.ts";
27import { themeCommand } from "./cli/theme.ts";
28import { traceCommand } from "./cli/trace.ts";
29import { sharedCommand } from "./cli/shared.ts";
30import { triageCommand } from "./cli/triage.ts";
31
32const layerCliRuntime = Layer.mergeAll(NodeServices.layer, NetService.layer);
33
34const connectPublicConfigMissingMessage =
35 "T3 Connect commands are unavailable: this build is missing T3 Connect public configuration.";
36
37class ConnectPublicConfigMissingError extends CliError.UserError {
38 override get message() {
39 return connectPublicConfigMissingMessage;
40 }
41}
42
43const connectUnavailableCommand = Command.make("connect", {
44 command: Argument.String("command").pipe(Argument.variadic),
45}).pipe(
46 Command.withDescription("T3 Connect is unavailable in builds without public configuration."),
47 Command.unlisted,
48 Command.withHandler(() =>
49 Effect.fail(
50 new CliError.ShowHelp({
51 commandPath: ["t3", "connect"],
52 errors: [new ConnectPublicConfigMissingError({ cause: connectPublicConfigMissingMessage })],
53 }),
54 ),
55 ),
56);
57
58export const makeCli = ({ cloudEnabled = hasCloudPublicConfig } = {}) =>
59 Command.make("t3", { ...sharedServerCommandFlags }).pipe(
60 Command.withDescription("Run the T3 Code server."),
61 Command.withHandler(runDefaultServerCommand),
62 Command.withSubcommands([
63 Command.make("help").pipe(
64 Command.withDescription("Show command help."),
65 Command.withHandler(() =>
66 Effect.fail(new CliError.ShowHelp({ commandPath: ["t3"], errors: [] })),
67 ),
68 ),
69 acpMcpBridgeCommand,
70 acpMcpCallCommand,
71 startCommand,
72 serveCommand,
73 appCommand,
74 pairCommand,
75 authCommand,
76 browserCommand,
77 projectCommand,
78 serviceCommand,
79 updateCommand,
80 uninstallCommand,
81 serviceLauncherCommand,
82 claudeHistoryCommand,
83 sshHelperCommand,
84
85 servicePreflightCommand,
86 themeCommand,
87 traceCommand,
88 sharedCommand,
89 triageCommand,
90 cloudEnabled ? connectCommand : connectUnavailableCommand,
91 ]),
92 );
93
94export const cli = makeCli();
95
96export function runCli() {
97 Command.run(cli, { version: SERVER_VERSION }).pipe(
98 Effect.scoped,
99 Effect.provide(layerCliRuntime),
100 NodeRuntime.runMain,
101 );
102}