opencode-island 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +185 -2
- package/dist/gui-experimental.cjs +45 -0
- package/dist/island/index.html +24 -0
- package/package.json +68 -4
- package/src/env.d.ts +1 -0
- package/src/gui.tsx +84 -0
- package/src/index.ts +11 -0
- package/src/island/app/components/island.tsx +491 -0
- package/src/island/app/components/ui/button.tsx +63 -0
- package/src/island/app/components/ui/toggle.tsx +44 -0
- package/src/island/app/global.d.ts +22 -0
- package/src/island/app/index.html +15 -0
- package/src/island/app/island.css +101 -0
- package/src/island/app/lib/utils.ts +6 -0
- package/src/island/app/main.tsx +10 -0
- package/src/island/app/tsconfig.json +20 -0
- package/src/island/preload.cjs +20 -0
- package/src/model.ts +416 -0
- package/src/state.ts +59 -0
- package/src/window.ts +262 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 opencode-island contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,186 @@
|
|
|
1
|
-
#
|
|
1
|
+
# opencode-island
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A macOS **Dynamic Island** for [OpenCode](https://opencode.ai).
|
|
4
|
+
|
|
5
|
+
It floats on the right edge of your screen and tells you what every session and
|
|
6
|
+
agent on your machine is doing — and lets you answer a permission prompt
|
|
7
|
+
without ever leaving the window you are working in.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
- **Closed**, it is a thin vertical tab on the right edge with the status
|
|
12
|
+
reading down its spine.
|
|
13
|
+
- **Open** it (click it) and it becomes a drawer listing the sessions running
|
|
14
|
+
right now, with their subagents nested underneath.
|
|
15
|
+
- **Approvals** turn the whole island warning orange, open it by themselves,
|
|
16
|
+
and can be answered in place.
|
|
17
|
+
- **Live** — the last ten words the agent is saying scroll down the closed tab
|
|
18
|
+
as they arrive.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
| | |
|
|
25
|
+
|---|---|
|
|
26
|
+
| macOS | 13 or newer |
|
|
27
|
+
| OpenCode | 2.2.7 or newer (the GUI plugin API) |
|
|
28
|
+
| Node | 20.19 or newer (only if you build from source) |
|
|
29
|
+
|
|
30
|
+
The island is a macOS-only plugin: it uses an Electron window that floats
|
|
31
|
+
above full-screen apps and every Space.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
### With the OpenCode CLI (recommended)
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
opencode plugin add opencode-island
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
That installs the package and adds it to your global OpenCode config.
|
|
42
|
+
Restart the desktop app and the island appears on the right edge of your
|
|
43
|
+
primary display.
|
|
44
|
+
|
|
45
|
+
To remove it again:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
opencode plugin remove opencode-island
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The CLI also takes a Git specifier, which builds the plugin from source:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
opencode plugin add github:hamzasoussi53/opencode-island
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### From source
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
git clone https://github.com/hamzasoussi53/opencode-island
|
|
61
|
+
cd opencode-island
|
|
62
|
+
npm install --ignore-scripts
|
|
63
|
+
npm run build
|
|
64
|
+
ln -s "$PWD" ~/.config/opencode/plugins/opencode-island
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`--ignore-scripts` skips Electron's ~100 MB binary download. The plugin only
|
|
68
|
+
needs Electron's type declarations to build; the desktop app supplies the
|
|
69
|
+
runtime. A plain `npm install` works too, it just downloads the binary as
|
|
70
|
+
well.
|
|
71
|
+
|
|
72
|
+
## Use
|
|
73
|
+
|
|
74
|
+
### The closed tab
|
|
75
|
+
|
|
76
|
+
The tab sits on the right edge, vertically centred. It shows one line:
|
|
77
|
+
|
|
78
|
+
- `2 agents working` — how many agents are busy right now
|
|
79
|
+
- `1 approval needed` — somebody is waiting for you
|
|
80
|
+
- `Idle` — nothing is running
|
|
81
|
+
|
|
82
|
+
The dotted grip at the **top** moves the tab: press and drag it up or down and
|
|
83
|
+
it slides along the edge, staying where you leave it.
|
|
84
|
+
|
|
85
|
+
The grip at the **bottom** changes how long the bar is: drag it and the bar
|
|
86
|
+
grows or shrinks downwards, its top staying put.
|
|
87
|
+
|
|
88
|
+
Click anywhere else on the tab to open the island.
|
|
89
|
+
|
|
90
|
+
### The expanded island
|
|
91
|
+
|
|
92
|
+
The drawer lists only the sessions that are running **now** — idle sessions
|
|
93
|
+
stay out of the way. Each row shows:
|
|
94
|
+
|
|
95
|
+
| | |
|
|
96
|
+
|---|---|
|
|
97
|
+
| The agent | which agent is running it |
|
|
98
|
+
| The phase | `THINKING`, `WRITING`, `WORKING`, `WAITING` or `RETRYING` |
|
|
99
|
+
| The title | what the session is about |
|
|
100
|
+
| The tool | the tool running right now, if any |
|
|
101
|
+
| The answer | the last words the agent said, as they stream in |
|
|
102
|
+
| The clock | how long the session has been going |
|
|
103
|
+
|
|
104
|
+
Subagents appear indented under the session that spawned them.
|
|
105
|
+
|
|
106
|
+
### The bottom bar
|
|
107
|
+
|
|
108
|
+
| Control | What it does |
|
|
109
|
+
|---|---|
|
|
110
|
+
| ☀️ 🌙 🖥 | Appearance, in one button: click it and it cycles light, dark, system |
|
|
111
|
+
| 👆 | Click-through: the island stops taking clicks, except its grip, so you can still open it |
|
|
112
|
+
| ☰ | Show the latest session's work in the closed tab instead of the summary |
|
|
113
|
+
|
|
114
|
+
### Approvals
|
|
115
|
+
|
|
116
|
+
When an agent asks for permission, the island turns warning orange and opens
|
|
117
|
+
itself. Three buttons answer it in place:
|
|
118
|
+
|
|
119
|
+
- **Allow once** — this one call
|
|
120
|
+
- **Always allow** — this tool for the rest of the session
|
|
121
|
+
- **Deny**
|
|
122
|
+
|
|
123
|
+
Answering closes the island again.
|
|
124
|
+
|
|
125
|
+
## How it works
|
|
126
|
+
|
|
127
|
+
The plugin has two halves, and the split is what makes it survive.
|
|
128
|
+
|
|
129
|
+
**The server half** (`src/index.ts`) is an ordinary OpenCode plugin. It does
|
|
130
|
+
nothing on its own; it exists so the desktop app discovers the package and
|
|
131
|
+
reads its GUI bundle.
|
|
132
|
+
|
|
133
|
+
**The GUI half** (`src/gui.tsx`) runs in the desktop app's **main process**.
|
|
134
|
+
That is the important part: a window-hosted plugin would stop when the last
|
|
135
|
+
app window closes, which is exactly when you want to know that an agent is
|
|
136
|
+
stuck on a permission prompt. From main, the plugin also reaches the app's own
|
|
137
|
+
server, so it sees the sessions of **every project** on your machine, not just
|
|
138
|
+
the one you have open.
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
src/gui.tsx the plugin: follows the app's server, owns the state
|
|
142
|
+
src/model.ts turns the server's event stream into sessions and phases
|
|
143
|
+
src/state.ts the JSON the island renders
|
|
144
|
+
src/window.ts the Electron window: placement, dragging, resizing
|
|
145
|
+
src/island/app/ the island UI: React 19, Tailwind v4 and shadcn/ui
|
|
146
|
+
src/island/preload.cjs the bridge between the page and the window
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The island page is built by its own Vite pass into a single self-contained
|
|
150
|
+
HTML file, which is then inlined into the plugin bundle. At runtime the
|
|
151
|
+
island makes no network requests of its own and loads nothing from disk.
|
|
152
|
+
|
|
153
|
+
The window is frameless, transparent and always on top. It is sized by the
|
|
154
|
+
page: the page measures itself and asks the window for that size, and the
|
|
155
|
+
window animates to it as a drawer sliding out of the screen edge. The island
|
|
156
|
+
never takes focus when it appears.
|
|
157
|
+
|
|
158
|
+
## Develop
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
npm install # --ignore-scripts also works, and skips Electron's binary
|
|
162
|
+
npm run dev # build the island, then watch the plugin bundle
|
|
163
|
+
npm run typecheck # the plugin and the island, separately
|
|
164
|
+
npm run check # the streaming tail helpers
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The desktop app hot-reloads the plugin when `dist/gui-experimental.cjs`
|
|
168
|
+
changes, so `npm run dev` is enough to see most edits. You must restart the
|
|
169
|
+
app after changing anything that runs in the main process (`src/gui.tsx`,
|
|
170
|
+
`src/window.ts`, `src/model.ts`).
|
|
171
|
+
|
|
172
|
+
The island UI lives in `src/island/app`. It is a separate Vite build with its
|
|
173
|
+
own TypeScript config, because the plugin's own JSX is Solid and the island's
|
|
174
|
+
is React.
|
|
175
|
+
|
|
176
|
+
## Limits
|
|
177
|
+
|
|
178
|
+
- macOS only, and the primary display only.
|
|
179
|
+
- The island's spot along the edge, its appearance and its switches are
|
|
180
|
+
remembered for the session only; they reset when the app restarts.
|
|
181
|
+
- The island shows what the app's server knows. A session that never
|
|
182
|
+
announces itself stays invisible.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT. See [LICENSE](LICENSE).
|