opencode-cockpit 0.1.4 → 0.2.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/README.md CHANGED
@@ -1,15 +1,106 @@
1
1
  # opencode-cockpit
2
2
 
3
3
  [![CI](https://github.com/Codestz/opencode-cockpit/actions/workflows/ci.yml/badge.svg)](https://github.com/Codestz/opencode-cockpit/actions/workflows/ci.yml)
4
- [![npm](https://img.shields.io/npm/v/opencode-cockpit)](https://www.npmjs.com/package/opencode-cockpit)
4
+ [![npm](https://img.shields.io/npm/v/opencode-cockpit?color=%23cb3837&label=opencode-cockpit)](https://www.npmjs.com/package/opencode-cockpit)
5
+ [![npm](https://img.shields.io/npm/v/@opencode-cockpit/shell?color=%23cb3837&label=%40opencode-cockpit%2Fshell)](https://www.npmjs.com/package/@opencode-cockpit/shell)
5
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Codestz/opencode-cockpit/blob/main/LICENSE)
6
7
 
7
- Superpowers for [OpenCode](https://opencode.ai). Take all of them, or only the ones you want.
8
+ **Superpowers for [OpenCode](https://opencode.ai) take all of them, or just the one you need.**
8
9
 
9
- | Feature | What it gives you | Package |
10
+ Coding agents are stuck in a one-command-at-a-time world: they run something, wait for it to
11
+ finish, and paste the whole log back into their context. Cockpit gives your agent the things a
12
+ developer actually has — long-running terminals, a way to wait for "ready", and output it can read
13
+ without drowning in it — and gives *you* a live view of all of it, inside OpenCode.
14
+
15
+ ```
16
+ ────────────────────────────────────────────────────────────────────────────────────────
17
+ Shells ⠹ RUN dev server FAIL unit tests ▸ 3 more ctrl+x i console · ctrl+x o hide
18
+ VITE v7.3.1 ready in 431 ms
19
+ ➜ Local: http://localhost:5173/
20
+ ✓ 142 modules transformed
21
+ 2m14s sh_k4tq8b2p · $ npm run dev
22
+ ────────────────────────────────────────────────────────────────────────────────────────
23
+ ```
24
+
25
+ ## Features
26
+
27
+ | Feature | What your agent gains | Package |
10
28
  |---|---|---|
11
- | **Shell** | Background terminals the agent starts, waits on and drives, with a docked panel and console for you | [`@opencode-cockpit/shell`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/shell) |
12
- | **Agents** *(coming)* | A live, keyboard-first view of every subagent, without leaving your chat | `@opencode-cockpit/agents` |
29
+ | **Shell** | Background terminals it starts, waits on, reads and types into dev servers, watchers, test suites, REPLs | [`@opencode-cockpit/shell`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/shell) |
30
+ | **Agents** *(next)* | A live, keyboard-first view of every subagent, without leaving your chat | `@opencode-cockpit/agents` |
31
+
32
+ ## Shell, by example
33
+
34
+ **"Start the dev server and wait until it's actually ready."**
35
+ The agent starts it in a real terminal and blocks on the port opening — not a guess, not a sleep:
36
+ ```
37
+ shell_start command="npm run dev" waitFor={ port: 5173 }
38
+ → condition met: port is accepting connections
39
+ 1| VITE v7.3.1 ready in 431 ms
40
+ ```
41
+
42
+ **"Run the tests, keep working, tell me if they fail."**
43
+ The suite runs in the background. When it exits, the agent is messaged once, with the error line
44
+ already picked out:
45
+ ```
46
+ <shell_exited id="sh_9wq2f1ab" title="unit tests">
47
+ exited with code 1 after 48s
48
+ last output: 37| FAIL src/auth.test.ts > refresh token expiry
49
+ ```
50
+
51
+ **"How is DB Monitoring doing?"**
52
+ Shells are shared across sessions and can be addressed by name:
53
+ ```
54
+ shell_read name="DB Monitoring"
55
+ ```
56
+
57
+ **Logs that don't eat your context.** Colour codes stripped, progress-bar redraws collapsed to
58
+ their final frame, repeated lines folded to `(×12)`, and every read returns a cursor so the next
59
+ one only brings what's new. For full-screen programs (`vitest --ui`, `htop`, prompts) the agent can
60
+ ask for the *screen* instead of the log.
61
+
62
+ **It notices breakage on its own.** Watch a process that never exits and the agent hears only about
63
+ changes, never about a thousand identical recompiles:
64
+ ```
65
+ shell_start command="tsc --watch --noEmit" description="type checker" watch=true
66
+ → tsc: ok → fail · src/auth.ts(42,3): error TS2339: Property 'id' does not exist
67
+ ```
68
+ Presets cover about 35 tools (tsc, vitest, jest, eslint, cargo, go, gradle, pytest, vite, next,
69
+ docker compose…), and anything else takes three regexes of its own. A watched process that dies
70
+ counts as a failure, so a crashed dev server is reported too.
71
+
72
+ **You can find things in a huge log.** `/` in the console filters the scrollback to matching lines,
73
+ keeping line numbers and highlighting matches — and output keeps the colours the program printed.
74
+
75
+ **It can type.** Prompts, REPLs, migration wizards: `shell_send` sends text or named keys
76
+ (`ctrl+c`, `up`, `enter`) and returns whatever the program printed back.
77
+
78
+ ### Why not just `bash`?
79
+
80
+ | | Built-in `bash` tool | Cockpit Shell |
81
+ |---|---|---|
82
+ | Long-running processes | Blocks until exit | Runs in the background, survives the turn |
83
+ | Knowing something is ready | Guess, or sleep and poll | Blocks on a port, a pattern, silence or exit |
84
+ | Interactive programs | Not possible (no TTY) | Real PTY: prompts, REPLs, ctrl+c |
85
+ | Reading output | Whole log, every time | Clean lines from a cursor, with grep |
86
+ | Noticing a break later | Never | Watchers report health changes |
87
+ | Your visibility | None until it finishes | Live panel, console and sidebar |
88
+ | After OpenCode restarts | Gone | Still running |
89
+
90
+ ## For you, not just the agent
91
+
92
+ | Key / command | Does |
93
+ |---|---|
94
+ | `ctrl+x o` · `/shells` | Toggle the shells panel under the chat |
95
+ | `ctrl+x i` · `/shell` | Open the shell console |
96
+ | `/shell-new` | Start a shell yourself |
97
+ | `/shells-clear` | Remove finished shells |
98
+ | `/cockpit-update` | Update the plugin when a newer release exists |
99
+
100
+ Status reads the same everywhere — `RUN` (with a spinner), `FAIL`, `STOP`, `DONE` — running shells
101
+ and recent failures stay in view, the rest folds behind `▸ N more`. In the console: `i` types
102
+ straight into the program (`ctrl+]` to stop), `c` sends ctrl+c, `r` restarts, `x` stops, `tab`
103
+ switches between the live screen and the scrollback, `?` shows details.
13
104
 
14
105
  ## Install
15
106
 
@@ -25,34 +116,36 @@ opencode plugin opencode-cockpit --global
25
116
  opencode plugin @opencode-cockpit/shell --global
26
117
  ```
27
118
 
28
- **Everything except some features**: switch them off on the plugin entry, in both `opencode.json`
29
- and `tui.json`:
119
+ Restart OpenCode. Requires OpenCode 1.18+ on macOS or Linux. Install a feature either through
120
+ `opencode-cockpit` or on its own — if both are configured, the first one loaded is used and
121
+ OpenCode warns you which entry to remove.
122
+
123
+ **Turn features off** (in both `opencode.json` and `tui.json`):
30
124
 
31
125
  ```json
32
- { "plugin": [["opencode-cockpit", { "features": { "shell": false } }]] }
126
+ {
127
+ "plugin": [["opencode-cockpit", { "features": { "shell": true } }]]
128
+ }
33
129
  ```
34
130
 
35
- Restart OpenCode after installing. Requires OpenCode 1.18 or newer on macOS or Linux.
131
+ **Configure them** in one file, read by both halves of the plugin and by every project:
36
132
 
37
- > Install a feature **either** through `opencode-cockpit` **or** on its own, not both. If both are
38
- > configured, the first one loaded is used and OpenCode shows a warning telling you which entry to
39
- > remove.
40
-
41
- ## Configuring features
42
-
43
- Each feature's README lists its options. With `opencode-cockpit`, nest them under the feature's
44
- name:
133
+ ```
134
+ ~/.config/opencode-cockpit/config.json → <project>/.cockpit.json → plugin-entry options
135
+ ```
45
136
 
46
137
  ```json
47
138
  {
48
- "plugin": [
49
- ["opencode-cockpit", { "shell": { "dockHeight": 16, "historyMinutes": 60 } }]
50
- ]
139
+ "kinds": { "e2e": "playwright|cypress" },
140
+ "defaults": { "logFile": true, "timeoutSeconds": 900 },
141
+ "ui": { "dockHeight": 16, "historyMinutes": 60 }
51
142
  }
52
143
  ```
53
144
 
54
- With a standalone package, put them directly on its entry:
55
- `["@opencode-cockpit/shell", { "dockHeight": 16 }]`.
145
+ Later sources win key by key, and an invalid file is ignored rather than fatal. You can categorize
146
+ your own commands, define watch rules, cap how long shells live, choose what may interrupt the
147
+ agent, and trade context tokens for accuracy. Each feature's README documents its own settings:
148
+ [Shell](https://github.com/Codestz/opencode-cockpit/tree/main/packages/shell#configuration).
56
149
 
57
150
  ## How it works
58
151
 
@@ -62,25 +155,41 @@ OpenCode TUI thread ── feature plugins (tui) ──┐
62
155
  OpenCode server worker ─ feature plugins (server) ┘
63
156
  ```
64
157
 
65
- Each feature is a complete OpenCode plugin. Features that need long-lived processes share one
66
- small daemon, `cockpitd`, which starts on demand, is shared by every OpenCode window, upgrades
67
- itself when a newer plugin connects and exits when idle. See [CONTRIBUTING.md](https://github.com/Codestz/opencode-cockpit/blob/main/CONTRIBUTING.md).
158
+ OpenCode runs its interface and its server in separate threads, so a plugin's two halves can't
159
+ share memory. Both talk to **`cockpitd`**, a small daemon that owns every long-lived process: it
160
+ starts on demand, is shared by every OpenCode window, upgrades itself when a newer plugin connects,
161
+ cleans up processes left by a crash, and exits when idle. That's why shells outlive OpenCode
162
+ restarts, and why one session can look at a shell another session started.
163
+
164
+ Each shell's output feeds three views at once: a normalized **log** for the agent, an emulated
165
+ **screen** for you, and a raw ring buffer so a panel opened late can catch up.
68
166
 
69
167
  | Package | Role |
70
168
  |---|---|
71
- | [`opencode-cockpit`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/opencode) | All features in one plugin, each can be switched off |
169
+ | [`opencode-cockpit`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/opencode) | All features in one plugin |
72
170
  | [`@opencode-cockpit/shell`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/shell) | Shell feature |
73
171
  | [`@opencode-cockpit/daemon`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/daemon) | `cockpitd`, the shared process host |
74
- | [`@opencode-cockpit/client`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/client) | Typed, auto-spawning client and shared plugin helpers |
172
+ | [`@opencode-cockpit/client`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/client) | Typed, auto-spawning client and plugin helpers |
75
173
  | [`@opencode-cockpit/protocol`](https://github.com/Codestz/opencode-cockpit/tree/main/packages/protocol) | Wire contracts |
76
174
 
77
175
  ## Roadmap
78
176
 
79
- - **Watchers** (Shell): `tsc`, `eslint` and `vitest` shells that report only state changes.
80
- - **Agents**: live subagent tree with a peek overlay.
81
- - **Doctor**: one command that checks your setup (duplicate features, daemon health, config) and
82
- tells you how to fix it.
83
- - Coloured output in the Shell panel and console.
177
+ - **Agents** live subagent tree with a peek overlay.
178
+ - **Doctor** one command that checks your setup and tells you how to fix it.
179
+ - Shell groups in the sidebar, if the five-row cap ever stops being enough.
180
+
181
+ ## Contributing
182
+
183
+ Issues and pull requests are welcome. [CONTRIBUTING.md](https://github.com/Codestz/opencode-cockpit/blob/main/CONTRIBUTING.md) covers the architecture,
184
+ the invariants worth knowing before changing anything, and how to run your working copy inside
185
+ OpenCode.
186
+
187
+ ```sh
188
+ bun install
189
+ bun run check # lint, typecheck, tests (real PTYs, real daemon)
190
+ bun run pack:check # pack, install the tarballs, run a shell through them
191
+ bun run smoke:tui # drive a real OpenCode against the packed plugin
192
+ ```
84
193
 
85
194
  ## License
86
195
 
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Merges the server hooks of several features into one plugin. Tool maps are unioned (a name
3
+ * clash is a bug, so it throws); function hooks run in feature order, each awaited, which is how
4
+ * OpenCode itself runs hooks from separate plugins.
5
+ */
6
+ export function composeHooks(parts) {
7
+ const tools = {};
8
+ const functions = new Map();
9
+ const singles = {};
10
+ for (const part of parts) {
11
+ for (const [key, value] of Object.entries(part)) {
12
+ if (value === undefined) continue;
13
+ if (key === "tool") {
14
+ for (const [id, def] of Object.entries(value)) {
15
+ if (id in tools) throw new Error(`tool "${id}" is registered by more than one cockpit feature`);
16
+ tools[id] = def;
17
+ }
18
+ } else if (typeof value === "function") {
19
+ const list = functions.get(key) ?? [];
20
+ list.push(value);
21
+ functions.set(key, list);
22
+ } else {
23
+ if (key in singles) throw new Error(`hook "${key}" is provided by more than one cockpit feature`);
24
+ singles[key] = value;
25
+ }
26
+ }
27
+ }
28
+ const hooks = {
29
+ ...singles
30
+ };
31
+ for (const [key, list] of functions) {
32
+ hooks[key] = list.length === 1 ? list[0] : async (...args) => {
33
+ for (const fn of list) await fn(...args);
34
+ };
35
+ }
36
+ if (Object.keys(tools).length > 0) hooks.tool = tools;
37
+ return hooks;
38
+ }
@@ -0,0 +1,23 @@
1
+ /** Every feature the bundle can load. Adding one: list it here and wire it in server.ts / tui.ts. */
2
+ export const FEATURES = ["shell"];
3
+ export const BUNDLE = "opencode-cockpit";
4
+ export function isEnabled(options, feature) {
5
+ return options?.features?.[feature] !== false;
6
+ }
7
+
8
+ /**
9
+ * Options for one feature. Shell also accepts options at the top level, which is where 0.1.x
10
+ * (when `opencode-cockpit` was Shell) read them from.
11
+ */
12
+ export function featureOptions(options, feature) {
13
+ const own = options?.[feature] ?? {};
14
+ if (feature !== "shell" || !options) return own;
15
+ const legacy = {};
16
+ for (const [key, value] of Object.entries(options)) {
17
+ if (key !== "features" && !FEATURES.includes(key)) legacy[key] = value;
18
+ }
19
+ return {
20
+ ...legacy,
21
+ ...own
22
+ };
23
+ }
package/dist/server.js ADDED
@@ -0,0 +1,17 @@
1
+ import { createShellServer } from "@opencode-cockpit/shell/server";
2
+ import { composeHooks } from "./compose.js";
3
+ import { BUNDLE, featureOptions, isEnabled } from "./features.js";
4
+ const shell = createShellServer({
5
+ source: BUNDLE
6
+ });
7
+ const server = async (input, rawOptions) => {
8
+ const options = rawOptions;
9
+ const parts = [];
10
+ if (isEnabled(options, "shell")) parts.push(await shell(input, featureOptions(options, "shell")));
11
+ return composeHooks(parts);
12
+ };
13
+ const plugin = {
14
+ id: BUNDLE,
15
+ server
16
+ };
17
+ export default plugin;
package/dist/tui.js ADDED
@@ -0,0 +1,14 @@
1
+ import { createShellTui } from "@opencode-cockpit/shell/tui";
2
+ import { BUNDLE, featureOptions, isEnabled } from "./features.js";
3
+ const shell = createShellTui({
4
+ source: BUNDLE
5
+ });
6
+ const tui = async (api, rawOptions, meta) => {
7
+ const options = rawOptions;
8
+ if (isEnabled(options, "shell")) await shell(api, featureOptions(options, "shell"), meta);
9
+ };
10
+ const plugin = {
11
+ id: BUNDLE,
12
+ tui
13
+ };
14
+ export default plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-cockpit",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "OpenCode superpowers, all in one: installs every opencode-cockpit feature (Shell today), each can be switched off",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,15 +25,22 @@
25
25
  "agents"
26
26
  ],
27
27
  "exports": {
28
- "./server": "./src/server.ts",
29
- "./tui": "./src/tui.ts"
28
+ "./server": {
29
+ "types": "./types/server.d.ts",
30
+ "default": "./dist/server.js"
31
+ },
32
+ "./tui": {
33
+ "types": "./types/tui.d.ts",
34
+ "default": "./dist/tui.js"
35
+ }
30
36
  },
31
37
  "engines": {
32
38
  "opencode": ">=1.18.0",
33
39
  "bun": ">=1.3.5"
34
40
  },
35
41
  "files": [
36
- "src",
42
+ "dist",
43
+ "types",
37
44
  "README.md",
38
45
  "LICENSE"
39
46
  ],
@@ -41,10 +48,10 @@
41
48
  "access": "public"
42
49
  },
43
50
  "dependencies": {
44
- "@opencode-cockpit/shell": "0.1.4",
51
+ "@opencode-cockpit/shell": "0.2.0",
45
52
  "@opencode-ai/plugin": "1.18.31"
46
53
  },
47
54
  "devDependencies": {
48
- "@opencode-cockpit/client": "0.1.4"
55
+ "@opencode-cockpit/client": "0.2.0"
49
56
  }
50
57
  }
@@ -0,0 +1,7 @@
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
+ /**
3
+ * Merges the server hooks of several features into one plugin. Tool maps are unioned (a name
4
+ * clash is a bug, so it throws); function hooks run in feature order, each awaited, which is how
5
+ * OpenCode itself runs hooks from separate plugins.
6
+ */
7
+ export declare function composeHooks(parts: Hooks[]): Hooks;
@@ -0,0 +1,17 @@
1
+ /** Every feature the bundle can load. Adding one: list it here and wire it in server.ts / tui.ts. */
2
+ export declare const FEATURES: readonly ["shell"];
3
+ export type Feature = (typeof FEATURES)[number];
4
+ export interface CockpitOptions {
5
+ /** Switch features off, e.g. `{ "shell": false }`. Everything is on by default. */
6
+ features?: Partial<Record<Feature, boolean>>;
7
+ /** Options passed to a single feature, keyed by feature name. */
8
+ shell?: Record<string, unknown>;
9
+ [key: string]: unknown;
10
+ }
11
+ export declare const BUNDLE = "opencode-cockpit";
12
+ export declare function isEnabled(options: CockpitOptions | undefined, feature: Feature): boolean;
13
+ /**
14
+ * Options for one feature. Shell also accepts options at the top level, which is where 0.1.x
15
+ * (when `opencode-cockpit` was Shell) read them from.
16
+ */
17
+ export declare function featureOptions(options: CockpitOptions | undefined, feature: Feature): Record<string, unknown>;
@@ -0,0 +1,5 @@
1
+ import type { PluginModule } from "@opencode-ai/plugin";
2
+ declare const plugin: PluginModule & {
3
+ id: string;
4
+ };
5
+ export default plugin;
package/types/tui.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import type { TuiPluginModule } from "@opencode-ai/plugin/tui";
2
+ declare const plugin: TuiPluginModule & {
3
+ id: string;
4
+ };
5
+ export default plugin;
package/src/compose.ts DELETED
@@ -1,43 +0,0 @@
1
- import type { Hooks } from "@opencode-ai/plugin"
2
-
3
- /**
4
- * Merges the server hooks of several features into one plugin. Tool maps are unioned (a name
5
- * clash is a bug, so it throws); function hooks run in feature order, each awaited, which is how
6
- * OpenCode itself runs hooks from separate plugins.
7
- */
8
- export function composeHooks(parts: Hooks[]): Hooks {
9
- const tools: NonNullable<Hooks["tool"]> = {}
10
- const functions = new Map<string, ((...args: unknown[]) => unknown)[]>()
11
- const singles: Record<string, unknown> = {}
12
-
13
- for (const part of parts) {
14
- for (const [key, value] of Object.entries(part)) {
15
- if (value === undefined) continue
16
- if (key === "tool") {
17
- for (const [id, def] of Object.entries(value as NonNullable<Hooks["tool"]>)) {
18
- if (id in tools) throw new Error(`tool "${id}" is registered by more than one cockpit feature`)
19
- tools[id] = def
20
- }
21
- } else if (typeof value === "function") {
22
- const list = functions.get(key) ?? []
23
- list.push(value as (...args: unknown[]) => unknown)
24
- functions.set(key, list)
25
- } else {
26
- if (key in singles) throw new Error(`hook "${key}" is provided by more than one cockpit feature`)
27
- singles[key] = value
28
- }
29
- }
30
- }
31
-
32
- const hooks: Record<string, unknown> = { ...singles }
33
- for (const [key, list] of functions) {
34
- hooks[key] =
35
- list.length === 1
36
- ? list[0]
37
- : async (...args: unknown[]) => {
38
- for (const fn of list) await fn(...args)
39
- }
40
- }
41
- if (Object.keys(tools).length > 0) hooks.tool = tools
42
- return hooks as Hooks
43
- }
package/src/features.ts DELETED
@@ -1,34 +0,0 @@
1
- /** Every feature the bundle can load. Adding one: list it here and wire it in server.ts / tui.ts. */
2
- export const FEATURES = ["shell"] as const
3
- export type Feature = (typeof FEATURES)[number]
4
-
5
- export interface CockpitOptions {
6
- /** Switch features off, e.g. `{ "shell": false }`. Everything is on by default. */
7
- features?: Partial<Record<Feature, boolean>>
8
- /** Options passed to a single feature, keyed by feature name. */
9
- shell?: Record<string, unknown>
10
- [key: string]: unknown
11
- }
12
-
13
- export const BUNDLE = "opencode-cockpit"
14
-
15
- export function isEnabled(options: CockpitOptions | undefined, feature: Feature): boolean {
16
- return options?.features?.[feature] !== false
17
- }
18
-
19
- /**
20
- * Options for one feature. Shell also accepts options at the top level, which is where 0.1.x
21
- * (when `opencode-cockpit` was Shell) read them from.
22
- */
23
- export function featureOptions(
24
- options: CockpitOptions | undefined,
25
- feature: Feature,
26
- ): Record<string, unknown> {
27
- const own = (options?.[feature] as Record<string, unknown> | undefined) ?? {}
28
- if (feature !== "shell" || !options) return own
29
- const legacy: Record<string, unknown> = {}
30
- for (const [key, value] of Object.entries(options)) {
31
- if (key !== "features" && !(FEATURES as readonly string[]).includes(key)) legacy[key] = value
32
- }
33
- return { ...legacy, ...own }
34
- }
package/src/server.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { Hooks, Plugin, PluginModule } from "@opencode-ai/plugin"
2
- import { createShellServer } from "@opencode-cockpit/shell/server"
3
- import { composeHooks } from "./compose.ts"
4
- import { BUNDLE, type CockpitOptions, featureOptions, isEnabled } from "./features.ts"
5
-
6
- const shell = createShellServer({ source: BUNDLE })
7
-
8
- const server: Plugin = async (input, rawOptions) => {
9
- const options = rawOptions as CockpitOptions | undefined
10
- const parts: Hooks[] = []
11
- if (isEnabled(options, "shell")) parts.push(await shell(input, featureOptions(options, "shell")))
12
- return composeHooks(parts)
13
- }
14
-
15
- const plugin: PluginModule & { id: string } = { id: BUNDLE, server }
16
- export default plugin
package/src/tui.ts DELETED
@@ -1,13 +0,0 @@
1
- import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui"
2
- import { createShellTui } from "@opencode-cockpit/shell/tui"
3
- import { BUNDLE, type CockpitOptions, featureOptions, isEnabled } from "./features.ts"
4
-
5
- const shell = createShellTui({ source: BUNDLE })
6
-
7
- const tui: TuiPlugin = async (api, rawOptions, meta) => {
8
- const options = rawOptions as CockpitOptions | undefined
9
- if (isEnabled(options, "shell")) await shell(api, featureOptions(options, "shell"), meta)
10
- }
11
-
12
- const plugin: TuiPluginModule & { id: string } = { id: BUNDLE, tui }
13
- export default plugin