opencode-manager 0.3.1 → 0.4.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.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * CLI entrypoint module.
3
+ *
4
+ * Provides Commander-based CLI with subcommands for projects, sessions,
5
+ * chat, and tokens. Global options are defined here and passed to
6
+ * subcommand handlers.
7
+ */
8
+
9
+ import { Command, type OptionValues } from "commander"
10
+ import { resolve } from "node:path"
11
+ import { DEFAULT_ROOT } from "../lib/opencode-data"
12
+ import { registerProjectsCommands } from "./commands/projects"
13
+ import { registerSessionsCommands } from "./commands/sessions"
14
+ import { registerChatCommands } from "./commands/chat"
15
+ import { registerTokensCommands } from "./commands/tokens"
16
+ import { registerTUICommand } from "./commands/tui"
17
+
18
+ /**
19
+ * Collect all options from a command and its ancestors.
20
+ * Commander stores global options on the root program, not on subcommands.
21
+ */
22
+ function collectOptions(cmd: Command): OptionValues {
23
+ const opts: OptionValues = {}
24
+ let current: Command | null = cmd
25
+ while (current) {
26
+ Object.assign(opts, current.opts())
27
+ current = current.parent
28
+ }
29
+ return opts
30
+ }
31
+
32
+ /**
33
+ * Global CLI options available to all subcommands.
34
+ */
35
+ export interface GlobalOptions {
36
+ /** Root path to OpenCode metadata store */
37
+ root: string
38
+ /** Output format: json, ndjson, or table */
39
+ format: "json" | "ndjson" | "table"
40
+ /** Maximum number of records to return */
41
+ limit: number
42
+ /** Sort order for list commands */
43
+ sort: "updated" | "created"
44
+ /** Skip confirmation prompts for destructive operations */
45
+ yes: boolean
46
+ /** Show planned changes without executing */
47
+ dryRun: boolean
48
+ /** Suppress non-essential output */
49
+ quiet: boolean
50
+ /** Copy output to clipboard */
51
+ clipboard: boolean
52
+ /** Directory for backup copies before deletion */
53
+ backupDir?: string
54
+ }
55
+
56
+ /**
57
+ * Default global options.
58
+ */
59
+ export const DEFAULT_OPTIONS: GlobalOptions = {
60
+ root: DEFAULT_ROOT,
61
+ format: "table",
62
+ limit: 200,
63
+ sort: "updated",
64
+ yes: false,
65
+ dryRun: false,
66
+ quiet: false,
67
+ clipboard: false,
68
+ backupDir: undefined,
69
+ }
70
+
71
+ /**
72
+ * Create the Commander program with global options and subcommands.
73
+ */
74
+ function createProgram(): Command {
75
+ const program = new Command()
76
+
77
+ program
78
+ .name("opencode-manager")
79
+ .description("CLI for managing OpenCode metadata stores")
80
+ .version("0.4.0")
81
+ // Global options
82
+ .option(
83
+ "-r, --root <path>",
84
+ "Root path to OpenCode metadata store",
85
+ DEFAULT_OPTIONS.root
86
+ )
87
+ .option(
88
+ "-f, --format <format>",
89
+ "Output format: json, ndjson, or table",
90
+ DEFAULT_OPTIONS.format
91
+ )
92
+ .option(
93
+ "-l, --limit <number>",
94
+ "Maximum number of records to return",
95
+ String(DEFAULT_OPTIONS.limit)
96
+ )
97
+ .option(
98
+ "--sort <order>",
99
+ "Sort order: updated or created",
100
+ DEFAULT_OPTIONS.sort
101
+ )
102
+ .option("-y, --yes", "Skip confirmation prompts", DEFAULT_OPTIONS.yes)
103
+ .option(
104
+ "-n, --dry-run",
105
+ "Show planned changes without executing",
106
+ DEFAULT_OPTIONS.dryRun
107
+ )
108
+ .option("-q, --quiet", "Suppress non-essential output", DEFAULT_OPTIONS.quiet)
109
+ .option("-c, --clipboard", "Copy output to clipboard", DEFAULT_OPTIONS.clipboard)
110
+ .option("--backup-dir <path>", "Directory for backup copies before deletion")
111
+
112
+ // Projects subcommand group
113
+ registerProjectsCommands(program)
114
+
115
+ // Sessions subcommand group
116
+ registerSessionsCommands(program)
117
+
118
+ // Chat subcommand group
119
+ registerChatCommands(program)
120
+
121
+ // Tokens subcommand group
122
+ registerTokensCommands(program)
123
+
124
+ // TUI subcommand to explicitly launch TUI from CLI
125
+ registerTUICommand(program)
126
+
127
+ return program
128
+ }
129
+
130
+ /**
131
+ * Parse global options from Commander's parsed options object.
132
+ * Resolves paths and converts types as needed.
133
+ */
134
+ export function parseGlobalOptions(opts: Record<string, unknown>): GlobalOptions {
135
+ return {
136
+ root: resolve(String(opts.root ?? DEFAULT_OPTIONS.root)),
137
+ format: validateFormat(String(opts.format ?? DEFAULT_OPTIONS.format)),
138
+ limit: parseInt(String(opts.limit ?? DEFAULT_OPTIONS.limit), 10),
139
+ sort: validateSort(String(opts.sort ?? DEFAULT_OPTIONS.sort)),
140
+ yes: Boolean(opts.yes ?? DEFAULT_OPTIONS.yes),
141
+ dryRun: Boolean(opts.dryRun ?? DEFAULT_OPTIONS.dryRun),
142
+ quiet: Boolean(opts.quiet ?? DEFAULT_OPTIONS.quiet),
143
+ clipboard: Boolean(opts.clipboard ?? DEFAULT_OPTIONS.clipboard),
144
+ backupDir: opts.backupDir ? resolve(String(opts.backupDir)) : undefined,
145
+ }
146
+ }
147
+
148
+ function validateFormat(format: string): GlobalOptions["format"] {
149
+ if (format === "json" || format === "ndjson" || format === "table") {
150
+ return format
151
+ }
152
+ return DEFAULT_OPTIONS.format
153
+ }
154
+
155
+ function validateSort(sort: string): GlobalOptions["sort"] {
156
+ if (sort === "updated" || sort === "created") {
157
+ return sort
158
+ }
159
+ return DEFAULT_OPTIONS.sort
160
+ }
161
+
162
+ /**
163
+ * Run the CLI with the given arguments.
164
+ * This is the main entry point called from opencode-manager.ts.
165
+ */
166
+ export async function runCLI(args: string[]): Promise<void> {
167
+ const program = createProgram()
168
+ await program.parseAsync(args, { from: "user" })
169
+ }