opencode-manager 0.3.0 → 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.
- package/PROJECT-SUMMARY.md +104 -24
- package/README.md +335 -7
- package/bun.lock +17 -1
- package/manage_opencode_projects.py +71 -66
- package/package.json +6 -3
- package/src/bin/opencode-manager.ts +133 -3
- package/src/cli/backup.ts +324 -0
- package/src/cli/commands/chat.ts +322 -0
- package/src/cli/commands/projects.ts +222 -0
- package/src/cli/commands/sessions.ts +495 -0
- package/src/cli/commands/tokens.ts +168 -0
- package/src/cli/commands/tui.ts +36 -0
- package/src/cli/errors.ts +259 -0
- package/src/cli/formatters/json.ts +184 -0
- package/src/cli/formatters/ndjson.ts +71 -0
- package/src/cli/formatters/table.ts +837 -0
- package/src/cli/index.ts +169 -0
- package/src/cli/output.ts +661 -0
- package/src/cli/resolvers.ts +249 -0
- package/src/lib/clipboard.ts +37 -0
- package/src/lib/opencode-data.ts +380 -1
- package/src/lib/search.ts +170 -0
- package/src/{opencode-tui.tsx → tui/app.tsx} +739 -105
- package/src/tui/args.ts +92 -0
- package/src/tui/index.tsx +46 -0
package/src/cli/index.ts
ADDED
|
@@ -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
|
+
}
|