@grympler/opencode-tmux-handover 1.0.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/DISTRIBUTION_AND_CONFIG.md +514 -0
- package/IMPLEMENTATION_GUIDE.md +529 -0
- package/QUICK_REFERENCE.md +320 -0
- package/README.md +117 -0
- package/install.sh +157 -0
- package/package.json +50 -0
- package/scripts/register-plugin.js +45 -0
- package/scripts/unregister-plugin.js +48 -0
- package/src/commands/tmux-claude.md +5 -0
- package/src/commands/tmux-copilot.md +5 -0
- package/src/commands/tmux-oc.md +5 -0
- package/src/commands/tmux.md +5 -0
- package/src/commands/tt-configure.md +5 -0
- package/src/config.ts +46 -0
- package/src/index.ts +66 -0
- package/src/scripts/opencode-tmux-claude.sh +39 -0
- package/src/scripts/opencode-tmux-copilot.sh +39 -0
- package/src/scripts/opencode-tmux-oc.sh +45 -0
- package/src/scripts/opencode-tmux.sh +36 -0
- package/src/scripts/opencode-tt-config.sh +64 -0
- package/uninstall.sh +106 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# From Local Plugin to Web-Available: Distribution & Configuration Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to evolve the `tt-plugin` from a local development plugin to a web-available npm package, and how to add customizable settings for command availability.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Current Architecture](#current-architecture)
|
|
10
|
+
2. [Distribution Methods](#distribution-methods)
|
|
11
|
+
3. [Publishing to npm](#publishing-to-npm)
|
|
12
|
+
4. [Adding Plugin Configuration](#adding-plugin-configuration)
|
|
13
|
+
5. [Plugin Settings Management](#plugin-settings-management)
|
|
14
|
+
6. [Examples](#examples)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Current Architecture
|
|
19
|
+
|
|
20
|
+
The `tt-plugin` currently uses a **local installation model**:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
tt-plugin (local directory)
|
|
24
|
+
├── src/
|
|
25
|
+
│ ├── index.ts # Plugin entry point
|
|
26
|
+
│ ├── commands/ # Command definitions (.md files)
|
|
27
|
+
│ └── scripts/ # Bash implementations
|
|
28
|
+
├── scripts/ # Registration utilities
|
|
29
|
+
├── install.sh # Local installation script
|
|
30
|
+
└── package.json # Plugin manifest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Current Flow:**
|
|
34
|
+
1. User clones repository locally
|
|
35
|
+
2. Runs `npm run install`
|
|
36
|
+
3. Plugin path is added to `~/.config/opencode/opencode.json`
|
|
37
|
+
4. Commands are symlinked to `~/.config/opencode/commands/`
|
|
38
|
+
|
|
39
|
+
**Limitations:**
|
|
40
|
+
- Requires manual git cloning
|
|
41
|
+
- Must be maintained locally
|
|
42
|
+
- No version management
|
|
43
|
+
- Updates require manual pulling
|
|
44
|
+
- No built-in configuration UI
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Distribution Methods
|
|
49
|
+
|
|
50
|
+
### Option 1: Local Files (Current)
|
|
51
|
+
**Best for:** Personal use, development, testing
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Users manually clone and install
|
|
55
|
+
git clone https://github.com/yourname/tt-plugin.git
|
|
56
|
+
cd tt-plugin
|
|
57
|
+
npm run install
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Pros:**
|
|
61
|
+
- Full control over code
|
|
62
|
+
- Easy to debug
|
|
63
|
+
- No build process needed
|
|
64
|
+
|
|
65
|
+
**Cons:**
|
|
66
|
+
- Manual updates
|
|
67
|
+
- Version conflicts
|
|
68
|
+
- Not discoverable
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### Option 2: npm Registry (Recommended)
|
|
73
|
+
**Best for:** Wide distribution, discoverability, version management
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Users simply add to config
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"plugin": ["tt-plugin"]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Pros:**
|
|
86
|
+
- Automatic installation via Bun
|
|
87
|
+
- Version management (semantic versioning)
|
|
88
|
+
- Discoverable in OpenCode ecosystem
|
|
89
|
+
- Easy updates
|
|
90
|
+
- No symlink management
|
|
91
|
+
|
|
92
|
+
**Cons:**
|
|
93
|
+
- Requires build step
|
|
94
|
+
- Must publish to npm
|
|
95
|
+
- Less flexible for local development
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### Option 3: GitHub Package Registry
|
|
100
|
+
**Best for:** Organizations, private packages
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"plugin": ["@yourorg/tt-plugin"]
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Similar to npm but hosted on GitHub.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Publishing to npm
|
|
113
|
+
|
|
114
|
+
### Step 1: Prepare Package
|
|
115
|
+
|
|
116
|
+
Update your `package.json`:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"name": "tt-plugin",
|
|
121
|
+
"version": "1.0.0",
|
|
122
|
+
"description": "OpenCode plugin for launching tmux with AI assistants",
|
|
123
|
+
"main": "src/index.ts",
|
|
124
|
+
"type": "module",
|
|
125
|
+
"repository": {
|
|
126
|
+
"type": "git",
|
|
127
|
+
"url": "https://github.com/yourusername/tt-plugin"
|
|
128
|
+
},
|
|
129
|
+
"keywords": ["opencode", "plugin", "tmux", "terminal"],
|
|
130
|
+
"author": "Your Name",
|
|
131
|
+
"license": "MIT",
|
|
132
|
+
"engines": {
|
|
133
|
+
"opencode": ">=dev",
|
|
134
|
+
"tmux": ">=3.0",
|
|
135
|
+
"bash": ">=4.0"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Important fields:**
|
|
141
|
+
- `name`: Must be lowercase, can include scopes (`@org/name`)
|
|
142
|
+
- `version`: Follows semantic versioning (1.0.0)
|
|
143
|
+
- `main`: Entry point (TypeScript supported by Bun)
|
|
144
|
+
- `type`: "module" for ES modules
|
|
145
|
+
- `files`: Include only necessary files
|
|
146
|
+
|
|
147
|
+
### Step 2: Build (Optional)
|
|
148
|
+
|
|
149
|
+
If you need to transpile TypeScript:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# In your build process
|
|
153
|
+
npx tsc src/index.ts --outDir dist/
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Update `package.json` main field:
|
|
157
|
+
```json
|
|
158
|
+
"main": "dist/index.js"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**For this plugin:** No build needed! Bun natively supports TypeScript.
|
|
162
|
+
|
|
163
|
+
### Step 3: Create npm Account
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npm login
|
|
167
|
+
# Enter credentials
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Or sign up at https://www.npmjs.com/signup
|
|
171
|
+
|
|
172
|
+
### Step 4: Publish
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# First time publish
|
|
176
|
+
npm publish
|
|
177
|
+
|
|
178
|
+
# Subsequent updates (bump version first)
|
|
179
|
+
npm version minor # or major, patch
|
|
180
|
+
npm publish
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Step 5: Verify Installation
|
|
184
|
+
|
|
185
|
+
Users can then use it:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"plugin": ["tt-plugin"]
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
OpenCode will automatically install it to `~/.cache/opencode/node_modules/tt-plugin`. This includes all bundled files (specifically `src/scripts/*.sh`), ensuring the bash scripts are available locally for the plugin to execute.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Adding Plugin Configuration
|
|
198
|
+
|
|
199
|
+
OpenCode plugins can accept configuration through two mechanisms:
|
|
200
|
+
|
|
201
|
+
### Method 1: Config File Settings
|
|
202
|
+
|
|
203
|
+
Store configuration in `opencode.json`:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"plugin": [
|
|
208
|
+
{
|
|
209
|
+
"path": "tt-plugin",
|
|
210
|
+
"config": {
|
|
211
|
+
"enabledCommands": ["tmux", "tmux-oc"],
|
|
212
|
+
"defaultTerminal": "alacritty",
|
|
213
|
+
"sessionPrefix": "oc"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Note:** Current OpenCode plugin system doesn't natively support this structure. This would require either:
|
|
221
|
+
1. Custom environment variables
|
|
222
|
+
2. Reading a separate config file
|
|
223
|
+
3. Extending the plugin API (future feature)
|
|
224
|
+
|
|
225
|
+
### Method 2: Environment Variables
|
|
226
|
+
|
|
227
|
+
Users can set environment variables to control behavior:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
export TT_PLUGIN_COMMANDS="tmux,tmux-oc,tmux-claude"
|
|
231
|
+
export TT_PLUGIN_DEFAULT_TERMINAL="alacritty"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Modify your plugin to read these:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// src/index.ts
|
|
238
|
+
const enabledCommands = (process.env.TT_PLUGIN_COMMANDS || "tmux,tmux-oc,tmux-claude,tmux-copilot").split(",")
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Plugin Settings Management
|
|
244
|
+
|
|
245
|
+
### Approach: JSON Configuration File
|
|
246
|
+
|
|
247
|
+
Create a configuration system that reads from `~/.config/opencode/tt-plugin-config.json`:
|
|
248
|
+
|
|
249
|
+
#### 1. Update Plugin to Read Config
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// src/index.ts
|
|
253
|
+
import type { Plugin } from "@opencode-ai/plugin"
|
|
254
|
+
import { readFileSync } from "fs"
|
|
255
|
+
import { homedir } from "os"
|
|
256
|
+
import { join } from "path"
|
|
257
|
+
|
|
258
|
+
interface PluginConfig {
|
|
259
|
+
enabledCommands: string[]
|
|
260
|
+
defaultTerminal?: string
|
|
261
|
+
sessionPrefix?: string
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function loadConfig(): PluginConfig {
|
|
265
|
+
const configPath = join(homedir(), ".config", "opencode", "tt-plugin-config.json")
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"))
|
|
269
|
+
return {
|
|
270
|
+
enabledCommands: ["tmux", "tmux-oc", "tmux-claude", "tmux-copilot"],
|
|
271
|
+
...config
|
|
272
|
+
}
|
|
273
|
+
} catch {
|
|
274
|
+
// Return defaults if no config file
|
|
275
|
+
return {
|
|
276
|
+
enabledCommands: ["tmux", "tmux-oc", "tmux-claude", "tmux-copilot"]
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export const TmuxLauncher: Plugin = async ({ $, directory }) => {
|
|
282
|
+
const config = loadConfig()
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
"command.execute.before": async (input, output) => {
|
|
286
|
+
const commandName = input.command || ""
|
|
287
|
+
|
|
288
|
+
// Check if command is enabled
|
|
289
|
+
if (!config.enabledCommands.includes(commandName)) {
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!commandName.startsWith("tmux")) return
|
|
294
|
+
|
|
295
|
+
const scriptMap: Record<string, string> = {
|
|
296
|
+
tmux: "opencode-tmux.sh",
|
|
297
|
+
"tmux-oc": "opencode-tmux-oc.sh",
|
|
298
|
+
"tmux-claude": "opencode-tmux-claude.sh",
|
|
299
|
+
"tmux-copilot": "opencode-tmux-copilot.sh"
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const scriptName = scriptMap[commandName]
|
|
303
|
+
if (!scriptName) return
|
|
304
|
+
|
|
305
|
+
const scriptPath = join(import.meta.dirname, "..", "scripts", scriptName)
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
await $`bash ${scriptPath}`.cwd(directory)
|
|
309
|
+
output.parts = []
|
|
310
|
+
} catch (err) {
|
|
311
|
+
console.error("tt-plugin:", err)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### 2. Create Setup/Configuration Command
|
|
319
|
+
|
|
320
|
+
Add a command to help users configure the plugin:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
#!/usr/bin/env bash
|
|
324
|
+
# scripts/opencode-tt-configure.sh
|
|
325
|
+
|
|
326
|
+
set -euo pipefail
|
|
327
|
+
|
|
328
|
+
CONFIG_DIR="$HOME/.config/opencode"
|
|
329
|
+
CONFIG_FILE="$CONFIG_DIR/tt-plugin-config.json"
|
|
330
|
+
|
|
331
|
+
mkdir -p "$CONFIG_DIR"
|
|
332
|
+
|
|
333
|
+
# Show current configuration
|
|
334
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
335
|
+
echo "Current configuration:"
|
|
336
|
+
cat "$CONFIG_FILE"
|
|
337
|
+
echo ""
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
# Create default config if it doesn't exist
|
|
341
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
342
|
+
cat > "$CONFIG_FILE" << 'EOF'
|
|
343
|
+
{
|
|
344
|
+
"enabledCommands": ["tmux", "tmux-oc", "tmux-claude", "tmux-copilot"],
|
|
345
|
+
"defaultTerminal": "auto",
|
|
346
|
+
"sessionPrefix": "oc"
|
|
347
|
+
}
|
|
348
|
+
EOF
|
|
349
|
+
echo "Created default configuration at: $CONFIG_FILE"
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
echo ""
|
|
353
|
+
echo "Edit the configuration file to customize:"
|
|
354
|
+
echo " - enabledCommands: Which tmux commands to enable"
|
|
355
|
+
echo " - defaultTerminal: Preferred terminal emulator (auto, gnome-terminal, alacritty, kitty, etc.)"
|
|
356
|
+
echo " - sessionPrefix: Prefix for tmux session names"
|
|
357
|
+
echo ""
|
|
358
|
+
echo "To edit: $EDITOR $CONFIG_FILE"
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### 3. Add Configuration Command to Plugin
|
|
362
|
+
|
|
363
|
+
Add to `src/commands/tt-configure.md`:
|
|
364
|
+
|
|
365
|
+
```markdown
|
|
366
|
+
---
|
|
367
|
+
description: Configure tt-plugin settings
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
Open the tt-plugin configuration file to customize enabled commands, terminal preference, and session naming.
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### 4. Example Configuration File
|
|
374
|
+
|
|
375
|
+
`~/.config/opencode/tt-plugin-config.json`:
|
|
376
|
+
|
|
377
|
+
```json
|
|
378
|
+
{
|
|
379
|
+
"enabledCommands": [
|
|
380
|
+
"tmux",
|
|
381
|
+
"tmux-oc"
|
|
382
|
+
],
|
|
383
|
+
"defaultTerminal": "alacritty",
|
|
384
|
+
"sessionPrefix": "dev"
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Examples
|
|
391
|
+
|
|
392
|
+
### Example 1: User Only Wants Two Commands
|
|
393
|
+
|
|
394
|
+
**Scenario:** User only uses `/tmux` and `/tmux-oc`, doesn't want `/tmux-claude` or `/tmux-copilot`
|
|
395
|
+
|
|
396
|
+
**Configuration:**
|
|
397
|
+
|
|
398
|
+
```json
|
|
399
|
+
{
|
|
400
|
+
"enabledCommands": ["tmux", "tmux-oc"],
|
|
401
|
+
"defaultTerminal": "auto",
|
|
402
|
+
"sessionPrefix": "oc"
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**Result:** Running `/tmux-claude` would be ignored (no error, just silently skipped)
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### Example 2: NPM Package Installation
|
|
411
|
+
|
|
412
|
+
**Step 1:** Publish package
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
npm login
|
|
416
|
+
npm version minor
|
|
417
|
+
npm publish
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Step 2:** User adds to config
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
# User updates ~/.config/opencode/opencode.json
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
```json
|
|
427
|
+
{
|
|
428
|
+
"plugin": ["tt-plugin"],
|
|
429
|
+
"command": {
|
|
430
|
+
"tt-configure": {
|
|
431
|
+
"template": "Help me configure the tt-plugin settings"
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**Step 3:** OpenCode installs automatically
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
At startup, OpenCode runs:
|
|
441
|
+
bun install --cwd ~/.cache/opencode
|
|
442
|
+
|
|
443
|
+
Plugin loads from:
|
|
444
|
+
~/.cache/opencode/node_modules/tt-plugin/src/index.ts
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
### Example 3: Scoped Organization Package
|
|
450
|
+
|
|
451
|
+
If publishing as organization package:
|
|
452
|
+
|
|
453
|
+
**Update package.json:**
|
|
454
|
+
|
|
455
|
+
```json
|
|
456
|
+
{
|
|
457
|
+
"name": "@myorg/tt-plugin",
|
|
458
|
+
"version": "1.0.0"
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**Publish:**
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
npm publish --access public # Scoped packages require explicit public access
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**User config:**
|
|
469
|
+
|
|
470
|
+
```json
|
|
471
|
+
{
|
|
472
|
+
"plugin": ["@myorg/tt-plugin"]
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## Summary: Local → Web Distribution Path
|
|
479
|
+
|
|
480
|
+
| Phase | Method | Installation | Version Mgmt | Discoverability |
|
|
481
|
+
|-------|--------|--------------|--------------|-----------------|
|
|
482
|
+
| **Development** | Local directory | `git clone` + `npm run install` | Manual | Private |
|
|
483
|
+
| **Testing** | npm (pre-release) | `npm install --save-dev` | Semantic | npm only |
|
|
484
|
+
| **Production** | npm Registry | Config file entry | Automatic | npm registry + ecosystem |
|
|
485
|
+
| **Enterprise** | GitHub Packages | Config file entry | Automatic | Private registry |
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Configuration Best Practices
|
|
490
|
+
|
|
491
|
+
### For Plugin Developers
|
|
492
|
+
|
|
493
|
+
1. **Provide sensible defaults** - Don't break if config file is missing
|
|
494
|
+
2. **Document configuration** - Include examples in README
|
|
495
|
+
3. **Version config schema** - If changing config format, handle migrations
|
|
496
|
+
4. **Validate configuration** - Check for invalid values at startup
|
|
497
|
+
5. **Log configuration** - Help users debug with clear logs
|
|
498
|
+
|
|
499
|
+
### For Users
|
|
500
|
+
|
|
501
|
+
1. **Keep it simple** - Only configure what's necessary
|
|
502
|
+
2. **Follow JSON syntax** - Use JSON validators
|
|
503
|
+
3. **Backup config** - Version control your config file
|
|
504
|
+
4. **Update regularly** - Check for new configuration options
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## Related Resources
|
|
509
|
+
|
|
510
|
+
- [OpenCode Plugins Documentation](https://opencode.ai/docs/plugins)
|
|
511
|
+
- [OpenCode Commands Documentation](https://opencode.ai/docs/commands)
|
|
512
|
+
- [npm Publishing Guide](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry)
|
|
513
|
+
- [OpenCode Ecosystem](https://opencode.ai/docs/ecosystem)
|
|
514
|
+
- [semantic-release](https://github.com/semantic-release/semantic-release) - Automated versioning
|