toggle-oh-my 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/README.md +40 -0
- package/index.js +166 -0
- package/package.json +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# toggle-oh-my
|
|
2
|
+
|
|
3
|
+
Opencode plugin that provides `/toggle-oh-my` — a command to enable/disable **oh-my-opencode** in opencode's configuration.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
The plugin reads your opencode config (`~/.config/opencode/opencode.jsonc` or project-local `.opencode/opencode.json`), finds **oh-my-opencode** in the `plugin` array, and toggles it by adding/removing a `disabled_` prefix:
|
|
8
|
+
|
|
9
|
+
| State | plugin entry |
|
|
10
|
+
|-------|-------------|
|
|
11
|
+
| **ON** | `"oh-my-opencode@latest"` |
|
|
12
|
+
| **OFF** | `"disabled_oh-my-opencode@latest"` |
|
|
13
|
+
|
|
14
|
+
The version string (`@latest`, `@1.2.3`, etc.) is preserved during the toggle, so you never lose the version pin.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
/toggle-oh-my
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The change takes effect on the **next opencode restart**.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g toggle-oh-my
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then add to your `opencode.json` / `opencode.jsonc`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"plugin": ["toggle-oh-my", "oh-my-opencode@latest"]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Compatibility
|
|
39
|
+
|
|
40
|
+
Works with any version of oh-my-opencode. The version specifier (`@latest`, `@1.x`, etc.) is preserved through toggles.
|
package/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
2
|
+
import { homedir, platform } from 'os';
|
|
3
|
+
import { join, sep } from 'path';
|
|
4
|
+
|
|
5
|
+
const PLUGIN_NAME = 'oh-my-opencode';
|
|
6
|
+
const DISABLED_PREFIX = 'disabled_';
|
|
7
|
+
const PLUGIN_DISPLAY = 'oh-my-opencode';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Find and read the opencode config file that contains the plugin entry.
|
|
11
|
+
* Checks project-level config first, then user-level config.
|
|
12
|
+
*/
|
|
13
|
+
function findConfig() {
|
|
14
|
+
// project-level: <cwd>/.opencode/opencode.json
|
|
15
|
+
const projectCandidates = [
|
|
16
|
+
join(process.cwd(), '.opencode', 'opencode.json'),
|
|
17
|
+
join(process.cwd(), '.opencode', 'opencode.jsonc'),
|
|
18
|
+
];
|
|
19
|
+
for (const fp of projectCandidates) {
|
|
20
|
+
if (!existsSync(fp)) continue;
|
|
21
|
+
const raw = readFileSync(fp, 'utf-8');
|
|
22
|
+
if (raw.includes(PLUGIN_NAME) || raw.includes(DISABLED_PREFIX + PLUGIN_NAME)) {
|
|
23
|
+
return { path: fp, raw, format: fp.endsWith('.jsonc') ? 'jsonc' : 'json' };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// user-level: ~/.config/opencode/opencode.jsonc (or opencode.json)
|
|
28
|
+
const home = homedir();
|
|
29
|
+
const userCandidates = [
|
|
30
|
+
join(home, '.config', 'opencode', 'opencode.jsonc'),
|
|
31
|
+
join(home, '.config', 'opencode', 'opencode.json'),
|
|
32
|
+
join(home, '.opencode.json'),
|
|
33
|
+
];
|
|
34
|
+
for (const fp of userCandidates) {
|
|
35
|
+
if (!existsSync(fp)) continue;
|
|
36
|
+
const raw = readFileSync(fp, 'utf-8');
|
|
37
|
+
return { path: fp, raw, format: fp.endsWith('.jsonc') ? 'jsonc' : 'json' };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Linux/macOS fallback: $XDG_CONFIG_HOME/opencode/opencode.jsonc
|
|
41
|
+
if (platform() !== 'win32') {
|
|
42
|
+
const xdg = process.env.XDG_CONFIG_HOME || join(home, '.config');
|
|
43
|
+
const fp = join(xdg, 'opencode', 'opencode.jsonc');
|
|
44
|
+
if (existsSync(fp)) {
|
|
45
|
+
const raw = readFileSync(fp, 'utf-8');
|
|
46
|
+
return { path: fp, raw, format: 'jsonc' };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Toggle oh-my-opencode in the raw config text.
|
|
55
|
+
* Uses regex to find the plugin string and toggle its name.
|
|
56
|
+
* Preserves original formatting, comments, and whitespace.
|
|
57
|
+
*/
|
|
58
|
+
function toggleInText(raw) {
|
|
59
|
+
// Match: "oh-my-opencode@version" or "disabled_oh-my-opencode@version"
|
|
60
|
+
// Captures: the full string including quotes, and the version part
|
|
61
|
+
const enabledPattern = new RegExp(
|
|
62
|
+
`"(${escapeRegex(PLUGIN_NAME)}(?:@[^"]*)?)"`,
|
|
63
|
+
'g'
|
|
64
|
+
);
|
|
65
|
+
const disabledPattern = new RegExp(
|
|
66
|
+
`"(${escapeRegex(DISABLED_PREFIX)}${escapeRegex(PLUGIN_NAME)}(?:@[^"]*)?)"`,
|
|
67
|
+
'g'
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
let isCurrentlyEnabled = false;
|
|
71
|
+
let version = '';
|
|
72
|
+
|
|
73
|
+
// Check if currently enabled
|
|
74
|
+
let match;
|
|
75
|
+
enabledPattern.lastIndex = 0;
|
|
76
|
+
while ((match = enabledPattern.exec(raw)) !== null) {
|
|
77
|
+
isCurrentlyEnabled = true;
|
|
78
|
+
// Extract version from the match
|
|
79
|
+
const atIdx = match[1].indexOf('@');
|
|
80
|
+
version = atIdx >= 0 ? match[1].slice(atIdx) : '';
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check if currently disabled
|
|
85
|
+
disabledPattern.lastIndex = 0;
|
|
86
|
+
let disabledVersion = '';
|
|
87
|
+
while ((match = disabledPattern.exec(raw)) !== null) {
|
|
88
|
+
isCurrentlyEnabled = false;
|
|
89
|
+
const atIdx = match[1].indexOf('@');
|
|
90
|
+
disabledVersion = atIdx >= 0 ? match[1].slice(atIdx) : '';
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let toggledText;
|
|
95
|
+
if (isCurrentlyEnabled) {
|
|
96
|
+
// Toggle OFF: add disabled_ prefix
|
|
97
|
+
toggledText = raw.replace(
|
|
98
|
+
enabledPattern,
|
|
99
|
+
`"${DISABLED_PREFIX}${PLUGIN_NAME}${version}"`
|
|
100
|
+
);
|
|
101
|
+
return { raw: toggledText, newState: 'disabled', version };
|
|
102
|
+
} else if (disabledVersion !== '') {
|
|
103
|
+
// Toggle ON: remove disabled_ prefix
|
|
104
|
+
toggledText = raw.replace(
|
|
105
|
+
disabledPattern,
|
|
106
|
+
`"${PLUGIN_NAME}${disabledVersion}"`
|
|
107
|
+
);
|
|
108
|
+
return { raw: toggledText, newState: 'enabled', version: disabledVersion };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Not found in any form
|
|
112
|
+
return { raw: null, newState: 'not-found', version: '' };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function escapeRegex(str) {
|
|
116
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const ToggleOhMyPlugin = async () => {
|
|
120
|
+
return {
|
|
121
|
+
config: async (opencodeConfig) => {
|
|
122
|
+
// Register the /toggle-oh-my command
|
|
123
|
+
opencodeConfig.command ??= {};
|
|
124
|
+
opencodeConfig.command['toggle-oh-my'] = {
|
|
125
|
+
template: '',
|
|
126
|
+
description: 'Toggle oh-my-opencode on/off (modified on next opencode restart)',
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
'command.execute.before': async (input, output) => {
|
|
131
|
+
if (input.command !== 'toggle-oh-my') return;
|
|
132
|
+
|
|
133
|
+
const configFile = findConfig();
|
|
134
|
+
if (!configFile) {
|
|
135
|
+
output.parts = [{
|
|
136
|
+
type: 'text',
|
|
137
|
+
text: '❌ Could not find opencode config file. Checked:\n' +
|
|
138
|
+
' - .opencode/opencode.json\n' +
|
|
139
|
+
' - ~/.config/opencode/opencode.jsonc\n' +
|
|
140
|
+
' - ~/.opencode.json',
|
|
141
|
+
}];
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const result = toggleInText(configFile.raw);
|
|
146
|
+
if (result.newState === 'not-found') {
|
|
147
|
+
output.parts = [{
|
|
148
|
+
type: 'text',
|
|
149
|
+
text: `⚠️ "${PLUGIN_DISPLAY}" not found in ${configFile.path}. Nothing to toggle.`,
|
|
150
|
+
}];
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Write the modified config back
|
|
155
|
+
writeFileSync(configFile.path, result.raw, 'utf-8');
|
|
156
|
+
|
|
157
|
+
const message = result.newState === 'enabled'
|
|
158
|
+
? `✅ **${PLUGIN_DISPLAY}${result.version}** is now **ENABLED**\n Restart opencode to apply.`
|
|
159
|
+
: `❌ **${PLUGIN_DISPLAY}${result.version}** is now **DISABLED**\n Restart opencode to apply.`;
|
|
160
|
+
|
|
161
|
+
output.parts = [{ type: 'text', text: message }];
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default ToggleOhMyPlugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "toggle-oh-my",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Opencode plugin to toggle oh-my-opencode on/off with a /toggle-oh-my command",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"index.js",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"opencode",
|
|
13
|
+
"plugin",
|
|
14
|
+
"oh-my-opencode",
|
|
15
|
+
"toggle"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
}
|
|
24
|
+
}
|