shmakk 1.2.4 → 1.2.5
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/.env.example +11 -0
- package/README.md +75 -1
- package/docs/index.html +154 -16
- package/docs/mcp.md +78 -0
- package/docs/ssh.md +82 -0
- package/docs/vibedit-analysis.md +375 -0
- package/docs/vim.md +110 -0
- package/docs/voice.md +4 -0
- package/package.json +9 -5
- package/scripts/test-vibedit.js +45 -0
- package/scripts/vibedit-demo.sh +52 -0
- package/skills/shmakk-skill-creator.md +269 -0
- package/src/_check.js +7 -0
- package/src/_check_schema.js +5 -0
- package/src/_cleanup.js +18 -0
- package/src/_fix.js +9 -0
- package/src/_test_import.js +15 -0
- package/src/agent.js +11 -4
- package/src/browser-daemon.js +209 -0
- package/src/browser.js +10 -0
- package/src/cli/browserDaemon.js +60 -0
- package/src/cli/connectBrowser.js +137 -0
- package/src/cli.js +235 -8
- package/src/completions.js +8 -0
- package/src/control.js +273 -1
- package/src/core/browserConnector.js +523 -0
- package/src/electron.js +305 -0
- package/src/endpoints.js +74 -9
- package/src/index.js +24 -1
- package/src/llm.js +501 -61
- package/src/mobile.js +307 -0
- package/src/notify.js +51 -3
- package/src/orchestrator.js +35 -1
- package/src/pty.js +11 -6
- package/src/review.js +45 -11
- package/src/self-commands.js +153 -0
- package/src/session-convert.js +508 -0
- package/src/session-search.js +31 -0
- package/src/session.js +384 -46
- package/src/skills/browserActions.ts +984 -0
- package/src/skills.js +451 -24
- package/src/system-prompt.js +31 -25
- package/src/tools.js +81 -0
- package/src/vibedit/control.js +534 -0
- package/src/vibedit/electron.js +108 -0
- package/src/vibedit/files.js +171 -0
- package/src/vibedit/index.js +298 -0
- package/src/vibedit/overlay.js +1482 -0
- package/src/vibedit/prompts.js +245 -0
- package/src/vibedit/state.js +32 -0
- package/src/vim.js +410 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// CLI entry point for `shmakk connect-browser`.
|
|
2
|
+
// Connects to a running Chrome instance via CDP, enabling the agent
|
|
3
|
+
// to interact with the user's own authenticated browser sessions.
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// shmakk connect-browser # auto-detect CDP port
|
|
7
|
+
// shmakk connect-browser --port 9222 # connect to specific port
|
|
8
|
+
// shmakk connect-browser --disconnect # disconnect
|
|
9
|
+
// shmakk connect-browser --status # show connection status
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
function resolveConnector() {
|
|
15
|
+
try {
|
|
16
|
+
return require('../core/browserConnector');
|
|
17
|
+
} catch (e) {
|
|
18
|
+
process.stderr.write(
|
|
19
|
+
'[shmakk] Browser connector unavailable.\n' +
|
|
20
|
+
'[shmakk] Install playwright: npm install playwright\n' +
|
|
21
|
+
`[shmakk] Details: ${e.message}\n`,
|
|
22
|
+
);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function parseArgs(argv) {
|
|
28
|
+
const args = {
|
|
29
|
+
port: null,
|
|
30
|
+
disconnect: false,
|
|
31
|
+
status: false,
|
|
32
|
+
help: false,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let i = 0;
|
|
36
|
+
while (i < argv.length) {
|
|
37
|
+
const a = argv[i];
|
|
38
|
+
if (a === '--port' || a === '-p') {
|
|
39
|
+
args.port = parseInt(argv[++i], 10);
|
|
40
|
+
if (isNaN(args.port) || args.port < 1 || args.port > 65535) {
|
|
41
|
+
process.stderr.write(`[shmakk] invalid port: ${argv[i]}\n`);
|
|
42
|
+
process.exit(2);
|
|
43
|
+
}
|
|
44
|
+
} else if (a === '--disconnect' || a === '-d') {
|
|
45
|
+
args.disconnect = true;
|
|
46
|
+
} else if (a === '--status' || a === '-s') {
|
|
47
|
+
args.status = true;
|
|
48
|
+
} else if (a === '--help' || a === '-h') {
|
|
49
|
+
args.help = true;
|
|
50
|
+
} else if (a === 'connect-browser') {
|
|
51
|
+
// skip the subcommand name itself
|
|
52
|
+
} else {
|
|
53
|
+
process.stderr.write(`[shmakk] connect-browser: unknown option: ${a}\n`);
|
|
54
|
+
args.help = true;
|
|
55
|
+
}
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return args;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const HELP = `shmakk connect-browser — connect to a running Chrome instance via CDP
|
|
63
|
+
|
|
64
|
+
Usage:
|
|
65
|
+
shmakk connect-browser [options]
|
|
66
|
+
|
|
67
|
+
Options:
|
|
68
|
+
--port, -p <port> Connect to Chrome on a specific CDP port (default: auto-detect)
|
|
69
|
+
--disconnect, -d Disconnect from Chrome
|
|
70
|
+
--status, -s Show connection status
|
|
71
|
+
--help, -h Show this help
|
|
72
|
+
|
|
73
|
+
Before running this command, start Chrome with remote debugging enabled:
|
|
74
|
+
google-chrome-stable --remote-debugging-port=9222
|
|
75
|
+
|
|
76
|
+
When connected, the agent's browser tool will interact with your
|
|
77
|
+
Chrome instance, preserving logins, cookies, and extensions.
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
async function main() {
|
|
81
|
+
const rawArgs = process.argv.slice(2);
|
|
82
|
+
|
|
83
|
+
// If no subcommand-like arg, default to connect.
|
|
84
|
+
const args = parseArgs(rawArgs);
|
|
85
|
+
|
|
86
|
+
if (args.help) {
|
|
87
|
+
process.stdout.write(HELP);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const bc = resolveConnector();
|
|
92
|
+
|
|
93
|
+
if (!bc.isAvailable()) {
|
|
94
|
+
process.stderr.write(
|
|
95
|
+
'[shmakk] playwright is required for browser CDP connection.\n' +
|
|
96
|
+
'[shmakk] Run: npm install playwright && npx playwright install chromium\n',
|
|
97
|
+
);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (args.disconnect) {
|
|
102
|
+
const result = await bc.disconnect();
|
|
103
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (args.status) {
|
|
108
|
+
const result = await bc.getStatus();
|
|
109
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Default: connect
|
|
114
|
+
const connectArgs = {};
|
|
115
|
+
if (args.port) connectArgs.port = args.port;
|
|
116
|
+
|
|
117
|
+
process.stdout.write('[shmakk] connecting to Chrome via CDP...\n');
|
|
118
|
+
|
|
119
|
+
const result = await bc.connect(connectArgs);
|
|
120
|
+
|
|
121
|
+
if (result.ok) {
|
|
122
|
+
process.stdout.write(
|
|
123
|
+
`[shmakk] connected to Chrome (port ${result.port})\n` +
|
|
124
|
+
`[shmakk] current page: ${result.url || '(about:blank)'}\n` +
|
|
125
|
+
`[shmakk] title: ${result.title || '(none)'}\n`,
|
|
126
|
+
);
|
|
127
|
+
process.exit(0);
|
|
128
|
+
} else {
|
|
129
|
+
process.stderr.write(`[shmakk] connection failed: ${result.error}\n`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
main().catch((err) => {
|
|
135
|
+
process.stderr.write(`[shmakk] connect-browser fatal: ${err && err.stack || err}\n`);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
package/src/cli.js
CHANGED
|
@@ -21,7 +21,9 @@ function parseArgs(argv) {
|
|
|
21
21
|
globalSkills: false,
|
|
22
22
|
resumeStatus: false,
|
|
23
23
|
showPlan: false,
|
|
24
|
+
newSession: false,
|
|
24
25
|
mcpStatus: false,
|
|
26
|
+
consolidateWorkspace: false,
|
|
25
27
|
exitNow: false,
|
|
26
28
|
restart: false,
|
|
27
29
|
profile: null,
|
|
@@ -30,6 +32,10 @@ function parseArgs(argv) {
|
|
|
30
32
|
markdown: null,
|
|
31
33
|
endpoint: null,
|
|
32
34
|
modelRecommendation: false,
|
|
35
|
+
vim: 'vi',
|
|
36
|
+
vimEditor: null,
|
|
37
|
+
vimReal: null,
|
|
38
|
+
vimAi: null,
|
|
33
39
|
voice: false,
|
|
34
40
|
stt: false,
|
|
35
41
|
tts: false,
|
|
@@ -45,12 +51,35 @@ function parseArgs(argv) {
|
|
|
45
51
|
completion: null,
|
|
46
52
|
helpCategory: null,
|
|
47
53
|
shell: null,
|
|
54
|
+
browserDaemon: false,
|
|
55
|
+
browserDaemonPort: null,
|
|
56
|
+
// connect-browser subcommand
|
|
57
|
+
connectBrowser: false,
|
|
58
|
+
connectBrowserPort: null,
|
|
59
|
+
connectBrowserDisconnect: false,
|
|
60
|
+
connectBrowserStatus: false,
|
|
48
61
|
unknown: [],
|
|
49
62
|
};
|
|
63
|
+
const setVoiceCliMode = (mode) => {
|
|
64
|
+
if (mode === 'stt') {
|
|
65
|
+
opts.stt = true;
|
|
66
|
+
opts.voice = true;
|
|
67
|
+
} else if (mode === 'tts') {
|
|
68
|
+
opts.tts = true;
|
|
69
|
+
} else if (mode === 'sts') {
|
|
70
|
+
opts.sts = true;
|
|
71
|
+
opts.voice = true;
|
|
72
|
+
opts.tts = true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
50
75
|
|
|
51
76
|
for (let i = 0; i < argv.length; i++) {
|
|
52
77
|
const a = argv[i];
|
|
53
78
|
switch (a) {
|
|
79
|
+
case '--':
|
|
80
|
+
opts.unknown.push(...argv.slice(i + 1));
|
|
81
|
+
i = argv.length;
|
|
82
|
+
break;
|
|
54
83
|
case '--review': opts.review = true; break;
|
|
55
84
|
case '--yes-files': opts.yesFiles = true; break;
|
|
56
85
|
case '--update-command-glossary': opts.updateGlossary = true; break;
|
|
@@ -79,7 +108,9 @@ function parseArgs(argv) {
|
|
|
79
108
|
case '--install-skill': opts.installSkill = argv[++i] || null; break;
|
|
80
109
|
case '--resume-status': opts.resumeStatus = true; break;
|
|
81
110
|
case '--show-plan': opts.showPlan = true; break;
|
|
111
|
+
case '--new-session': opts.newSession = true; break;
|
|
82
112
|
case '--mcp-status': opts.mcpStatus = true; break;
|
|
113
|
+
case '--consolidate-workspace': opts.consolidateWorkspace = true; break;
|
|
83
114
|
case '--exit': opts.exitNow = true; break;
|
|
84
115
|
case '--restart': opts.restart = true; break;
|
|
85
116
|
case '--reset': opts.reset = true; break;
|
|
@@ -93,10 +124,10 @@ function parseArgs(argv) {
|
|
|
93
124
|
}
|
|
94
125
|
if (!opts.buildHistory.length) opts.buildHistory = null; // flag with no files = auto-detect
|
|
95
126
|
break;
|
|
96
|
-
case '--stt':
|
|
97
|
-
case '--tts':
|
|
98
|
-
case '--sts':
|
|
99
|
-
case '--voice':
|
|
127
|
+
case '--stt': setVoiceCliMode('stt'); break;
|
|
128
|
+
case '--tts': setVoiceCliMode('tts'); break;
|
|
129
|
+
case '--sts': setVoiceCliMode('sts'); break;
|
|
130
|
+
case '--voice': setVoiceCliMode('stt'); break;
|
|
100
131
|
case '--voice-language': opts.voiceLanguage = argv[++i] || null; break;
|
|
101
132
|
case '--voice-max-sec': opts.voiceMaxDuration = parseInt(argv[++i], 10) || null; break;
|
|
102
133
|
case '--voice-silence-sec': opts.voiceSilenceSec = argv[++i] || null; break;
|
|
@@ -110,6 +141,19 @@ function parseArgs(argv) {
|
|
|
110
141
|
case '--markdown': opts.markdown = argv[++i] || null; break;
|
|
111
142
|
case '--endpoint': opts.endpoint = argv[++i] || null; break;
|
|
112
143
|
case '--model-recommendation': opts.modelRecommendation = true; break;
|
|
144
|
+
case '--vim':
|
|
145
|
+
{
|
|
146
|
+
const v = (argv[++i] || 'vi').toLowerCase();
|
|
147
|
+
if (!['vi', 'vim', 'disable', 'enable'].includes(v)) {
|
|
148
|
+
process.stderr.write('[shmakk] invalid --vim. Use: vi|vim|disable\n');
|
|
149
|
+
process.exit(2);
|
|
150
|
+
}
|
|
151
|
+
opts.vim = v === 'enable' ? 'vim' : v;
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
case '--vim-editor': opts.vimEditor = argv[++i] || null; break;
|
|
155
|
+
case '--vim-real': opts.vimReal = argv[++i] || null; break;
|
|
156
|
+
case '--vim-ai': opts.vimAi = argv[++i] || null; break;
|
|
113
157
|
case '--shell':
|
|
114
158
|
{
|
|
115
159
|
const v = argv[++i];
|
|
@@ -120,6 +164,53 @@ function parseArgs(argv) {
|
|
|
120
164
|
opts.shell = v;
|
|
121
165
|
}
|
|
122
166
|
break;
|
|
167
|
+
case 'connect-browser':
|
|
168
|
+
opts.connectBrowser = true;
|
|
169
|
+
// Consume subsequent flags that belong to connect-browser
|
|
170
|
+
while (i + 1 < argv.length) {
|
|
171
|
+
const n = argv[i + 1];
|
|
172
|
+
if (n === '--port' || n === '-p') {
|
|
173
|
+
i++;
|
|
174
|
+
opts.connectBrowserPort = parseInt(argv[++i], 10);
|
|
175
|
+
if (isNaN(opts.connectBrowserPort)) {
|
|
176
|
+
process.stderr.write(`[shmakk] connect-browser: invalid port: ${argv[i]}\n`);
|
|
177
|
+
process.exit(2);
|
|
178
|
+
}
|
|
179
|
+
} else if (n === '--disconnect' || n === '-d') {
|
|
180
|
+
i++;
|
|
181
|
+
opts.connectBrowserDisconnect = true;
|
|
182
|
+
} else if (n === '--status' || n === '-s') {
|
|
183
|
+
i++;
|
|
184
|
+
opts.connectBrowserStatus = true;
|
|
185
|
+
} else if (n === '--help' || n === '-h') {
|
|
186
|
+
i++;
|
|
187
|
+
opts.help = true;
|
|
188
|
+
opts.helpCategory = 'mcp';
|
|
189
|
+
} else {
|
|
190
|
+
break; // unknown or next subcommand
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
case 'browser-daemon':
|
|
195
|
+
opts.browserDaemon = true;
|
|
196
|
+
while (i + 1 < argv.length) {
|
|
197
|
+
const n = argv[i + 1];
|
|
198
|
+
if (n === '--port' || n === '-p') {
|
|
199
|
+
i++;
|
|
200
|
+
opts.browserDaemonPort = parseInt(argv[++i], 10);
|
|
201
|
+
if (isNaN(opts.browserDaemonPort)) {
|
|
202
|
+
process.stderr.write(`[shmakk] browser-daemon: invalid port: ${argv[i]}\n`);
|
|
203
|
+
process.exit(2);
|
|
204
|
+
}
|
|
205
|
+
} else if (n === '--help' || n === '-h') {
|
|
206
|
+
i++;
|
|
207
|
+
opts.help = true;
|
|
208
|
+
opts.helpCategory = 'mcp';
|
|
209
|
+
} else {
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
123
214
|
default: opts.unknown.push(a);
|
|
124
215
|
}
|
|
125
216
|
}
|
|
@@ -144,10 +235,12 @@ Categories (shmakk --help <name> for details):
|
|
|
144
235
|
session Status, stats, restart, exit, control signals
|
|
145
236
|
skills Skill discovery, loading, listing, management
|
|
146
237
|
models Provider configuration, endpoint presets
|
|
238
|
+
vim Vim/vi integration and AI suggestions
|
|
147
239
|
voice Speech-to-Text / Text-to-Speech options
|
|
148
240
|
env Environment variable reference
|
|
149
241
|
mcp MCP servers and browser automation
|
|
150
242
|
ssh Remote host execution
|
|
243
|
+
vibedit Visual editing overlay (web + Electron)
|
|
151
244
|
self Natural-language self-commands (inside a session)
|
|
152
245
|
|
|
153
246
|
`;
|
|
@@ -177,9 +270,11 @@ HELP_SECTIONS.launch = `══════════════════
|
|
|
177
270
|
--print-config Print resolved configuration and exit
|
|
178
271
|
|
|
179
272
|
--workspace <path> Override workspace root
|
|
273
|
+
--new-session Force a new session instead of resuming
|
|
180
274
|
--profile <name> Startup profile: tiny|balanced|deep|builder|large-app
|
|
181
275
|
--colors <true|false> Enable or disable ANSI colors
|
|
182
276
|
--markdown <true|false> Enable or disable markdown rendering
|
|
277
|
+
--vim <vi|vim|disable> Intercept vi/vim inside shmakk (default: vi)
|
|
183
278
|
--notify Desktop notifications for Y/n prompts
|
|
184
279
|
`;
|
|
185
280
|
|
|
@@ -190,17 +285,62 @@ HELP_SECTIONS.models = `══════════════════
|
|
|
190
285
|
--endpoint <name> Use model preset from ~/.config/shmakk/endpoints.json
|
|
191
286
|
--model-recommendation Main model chooses best model per call
|
|
192
287
|
|
|
193
|
-
Providers: openai-compatible | codex | anthropic | google
|
|
288
|
+
Providers: openai-compatible | codex | anthropic | google | nvidia
|
|
194
289
|
Configure in ~/.config/shmakk/endpoints.json:
|
|
195
290
|
{
|
|
196
291
|
"main": "claude",
|
|
292
|
+
"fast": "flash",
|
|
197
293
|
"models": {
|
|
198
294
|
"claude": { "provider":"anthropic", "model":"claude-sonnet-4-5-...", "api_key":"..." },
|
|
295
|
+
"flash": { "provider":"google", "model":"gemini-flash", "api_key":"..." },
|
|
199
296
|
"gpt5": { "provider":"codex", "model":"gpt-5-codex", "api_key":"..." },
|
|
297
|
+
"kimi": { "provider":"nvidia", "model":"moonshotai/kimi-k2.6", "api_key":"nvapi-..." },
|
|
200
298
|
"local-qwen": { "provider":"openai-compatible", "base_url":"http://127.0.0.1:1234/v1",
|
|
201
299
|
"model":"qwen/qwen3.5-9b" }
|
|
202
300
|
}
|
|
203
301
|
}
|
|
302
|
+
|
|
303
|
+
main is used for normal agent work. fast is used for low-latency paths such
|
|
304
|
+
as Vim suggestions. Override with SHMAKK_FAST_ENDPOINT or
|
|
305
|
+
SHMAKK_VIM_SUGGEST_ENDPOINT.
|
|
306
|
+
`;
|
|
307
|
+
|
|
308
|
+
HELP_SECTIONS.vim = `═══════════════════════════════════════════════════════════════════════════
|
|
309
|
+
VIM / VI
|
|
310
|
+
═══════════════════════════════════════════════════════════════════════════
|
|
311
|
+
|
|
312
|
+
--vim <vi|vim|disable> Intercept vi/vim inside shmakk (default: vi)
|
|
313
|
+
|
|
314
|
+
When enabled, shmakk puts a temporary vi or vim shim at the front of PATH
|
|
315
|
+
inside the shmakk shell. The shim launches your real editor, loads your
|
|
316
|
+
normal vimrc/plugins/colors first, then sources a small shmakk plugin.
|
|
317
|
+
|
|
318
|
+
Commands inside Vim:
|
|
319
|
+
:G <prompt> Generate code at the cursor
|
|
320
|
+
:Tw <prompt> Write prose or documentation at the cursor
|
|
321
|
+
:Cmd <command> Run a shell command in a scratch buffer
|
|
322
|
+
:ShmakkSuggest Ask for a full-block suggestion
|
|
323
|
+
:ShmakkAccept Preview and accept pending auto-suggestion
|
|
324
|
+
:ShmakkPreview Preview pending auto-suggestion
|
|
325
|
+
:ShmakkDeny Clear pending auto-suggestion
|
|
326
|
+
|
|
327
|
+
Mappings:
|
|
328
|
+
<C-Space> Manual full-block suggestion with preview
|
|
329
|
+
<leader>sa Accept pending auto-suggestion
|
|
330
|
+
<leader>sp Preview pending auto-suggestion
|
|
331
|
+
<leader>sd Deny pending auto-suggestion
|
|
332
|
+
|
|
333
|
+
Lowercase :g is not overridden; it remains Vim's native :global command.
|
|
334
|
+
Use :G for shmakk generation. Native commands such as :%s/foo/bar/g still
|
|
335
|
+
work normally.
|
|
336
|
+
|
|
337
|
+
Optional auto-suggest in vimrc:
|
|
338
|
+
let g:shmakk_auto_suggest = 1
|
|
339
|
+
let g:shmakk_auto_suggest_delay_ms = 2000
|
|
340
|
+
let g:shmakk_auto_suggest_min_chars = 20
|
|
341
|
+
|
|
342
|
+
Suggestions prefer SHMAKK_VIM_SUGGEST_ENDPOINT, then SHMAKK_FAST_ENDPOINT,
|
|
343
|
+
then the endpoint registry's fast model, then the current model.
|
|
204
344
|
`;
|
|
205
345
|
|
|
206
346
|
HELP_SECTIONS.session = `═══════════════════════════════════════════════════════════════════════════
|
|
@@ -214,6 +354,7 @@ HELP_SECTIONS.session = `══════════════════
|
|
|
214
354
|
shmakk --mcp-status MCP servers and their tools
|
|
215
355
|
|
|
216
356
|
shmakk --compact Clear conversation + task journal
|
|
357
|
+
shmakk --consolidate-workspace Merge nested .shmakk dirs into root
|
|
217
358
|
shmakk --reset Clear AI conversation history (keep session)
|
|
218
359
|
shmakk --restart Restart the inner shell (keeps window)
|
|
219
360
|
shmakk --exit Cleanly exit the parent shmakk
|
|
@@ -240,6 +381,7 @@ HELP_SECTIONS.voice = `═══════════════════
|
|
|
240
381
|
--sts Speech-to-Speech: always-on mic + TTS
|
|
241
382
|
--stt Speech-to-Text: mic input, text output
|
|
242
383
|
--tts Text-to-Speech: text input, spoken output
|
|
384
|
+
These modes are exclusive; the last one wins.
|
|
243
385
|
|
|
244
386
|
--voice-language <code> Language hint (e.g. en, es, fr)
|
|
245
387
|
--voice-max-sec <sec> Max recording seconds (default: 30)
|
|
@@ -261,10 +403,17 @@ HELP_SECTIONS.env = `═══════════════════
|
|
|
261
403
|
SHMAKK_BASE_URL OpenAI-compatible base URL
|
|
262
404
|
SHMAKK_API_KEY API key
|
|
263
405
|
SHMAKK_MODEL Default model
|
|
264
|
-
|
|
406
|
+
SHMAKK_FAST_ENDPOINT Named endpoint for low-latency tasks
|
|
407
|
+
SHMAKK_VIM_SUGGEST_ENDPOINT Named endpoint for Vim suggestions
|
|
408
|
+
SHMAKK_PROVIDER Provider: openai-compatible|codex|anthropic|google|nvidia
|
|
265
409
|
SHMAKK_HEADERS Extra headers: k=v,k=v
|
|
266
410
|
SHMAKK_REGISTRY Model registry filter (comma-separated)
|
|
267
411
|
SHMAKK_MODEL_RECOMMENDATION Set to 1 to let main model choose per call
|
|
412
|
+
SHMAKK_VIM_SHIM_DIR Internal PATH shim for enhanced vi/vim
|
|
413
|
+
SHMAKK_REAL_PATH Original PATH before shmakk vim shims
|
|
414
|
+
SHMAKK_VIM_SUGGEST_MAX_CHARS Max context chars sent for Vim suggestions
|
|
415
|
+
SHMAKK_VIM_SUGGEST_BEFORE_LINES Lines before cursor for Vim suggestions
|
|
416
|
+
SHMAKK_VIM_SUGGEST_AFTER_LINES Lines after cursor for Vim suggestions
|
|
268
417
|
|
|
269
418
|
SHMAKK_HF_CACHE HuggingFace cache directory (voice models)
|
|
270
419
|
SHMAKK_TTS_VOICE Pin a specific TTS voice
|
|
@@ -281,12 +430,37 @@ HELP_SECTIONS.mcp = `═══════════════════
|
|
|
281
430
|
═══════════════════════════════════════════════════════════════════════════
|
|
282
431
|
|
|
283
432
|
MCP servers: configure in ~/.config/shmakk/mcp.json or .shmakk/mcp.json
|
|
284
|
-
{
|
|
433
|
+
{
|
|
434
|
+
"mcpServers": {
|
|
435
|
+
"name": {
|
|
436
|
+
"command": "...",
|
|
437
|
+
"args": ["..."],
|
|
438
|
+
"env": { "TOKEN": "\${TOKEN}" },
|
|
439
|
+
"safety": "uncertain",
|
|
440
|
+
"safeTools": ["read"],
|
|
441
|
+
"unsafeTools": ["delete"],
|
|
442
|
+
"timeout": 30000,
|
|
443
|
+
"disabled": false
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
285
447
|
|
|
286
|
-
|
|
448
|
+
Agent browser tool: headless Playwright for non-interactive browsing.
|
|
287
449
|
npm install playwright && npx playwright install chromium
|
|
288
450
|
Tools: navigate, click, type, read_page, screenshot, evaluate, select,
|
|
289
451
|
wait, scroll, close.
|
|
452
|
+
|
|
453
|
+
Extension automation for the current Chrome tab:
|
|
454
|
+
shmakk browser-daemon run global extension backend
|
|
455
|
+
shmakk browser-daemon --port 3947 use a custom extension port
|
|
456
|
+
|
|
457
|
+
CDP connection is for live debugging / Electron-style targets:
|
|
458
|
+
shmakk connect-browser auto-detect and connect
|
|
459
|
+
shmakk connect-browser --port 9222 connect to specific port
|
|
460
|
+
shmakk connect-browser --status show connection status
|
|
461
|
+
shmakk connect-browser --disconnect disconnect
|
|
462
|
+
|
|
463
|
+
shmakk --mcp-status Show configured servers and discovered tools
|
|
290
464
|
`;
|
|
291
465
|
|
|
292
466
|
HELP_SECTIONS.ssh = `═══════════════════════════════════════════════════════════════════════════
|
|
@@ -317,6 +491,50 @@ HELP_SECTIONS.ssh = `═══════════════════
|
|
|
317
491
|
ControlPersist 600
|
|
318
492
|
`;
|
|
319
493
|
|
|
494
|
+
HELP_SECTIONS['vibedit'] = `═══════════════════════════════════════════════════════════════════════════
|
|
495
|
+
VIBEDIT (web + Electron)
|
|
496
|
+
═══════════════════════════════════════════════════════════════════════════
|
|
497
|
+
|
|
498
|
+
Vibedit is the visual editing overlay. It opens a Chromium browser tab,
|
|
499
|
+
injects a chat panel with a shadow-DOM overlay, captures screenshots for
|
|
500
|
+
vision-model analysis, and applies code changes directly to your project.
|
|
501
|
+
|
|
502
|
+
── Web mode ──
|
|
503
|
+
|
|
504
|
+
Inside a session:
|
|
505
|
+
/vibedit <url | file | package.json | dir>
|
|
506
|
+
|
|
507
|
+
Opens a Playwright Chromium browser, injects the overlay, and auto-starts
|
|
508
|
+
a dev server if given a package.json or project directory. The overlay
|
|
509
|
+
appears as a puck in the bottom-right corner.
|
|
510
|
+
|
|
511
|
+
── Electron mode ──
|
|
512
|
+
|
|
513
|
+
Inside a session:
|
|
514
|
+
/vibedit-electron <debug-port>
|
|
515
|
+
/ve <debug-port> (short alias)
|
|
516
|
+
|
|
517
|
+
Connects to an already-running Electron app via Chrome DevTools Protocol.
|
|
518
|
+
The app must be launched with --remote-debugging-port=<port>.
|
|
519
|
+
No new browser window is opened — the overlay is injected into the
|
|
520
|
+
existing Electron window.
|
|
521
|
+
|
|
522
|
+
── Specs ──
|
|
523
|
+
|
|
524
|
+
Use the overlay's Save button to capture a spec (screenshot + description).
|
|
525
|
+
The spec is immediately sent to the agent for implementation. If the
|
|
526
|
+
agent is already busy, the spec is queued and applied on the next run.
|
|
527
|
+
|
|
528
|
+
── Dependencies ──
|
|
529
|
+
|
|
530
|
+
Both modes require: npm install playwright && npx playwright install chromium
|
|
531
|
+
Electron mode also needs the target app's debug port accessible.
|
|
532
|
+
|
|
533
|
+
Project-local state: .shmakk/state/vibedit-*
|
|
534
|
+
Extension daemon state: ~/.config/shmakk/browser-daemon.json
|
|
535
|
+
Vibedit control port: auto-assigned per overlay session
|
|
536
|
+
`;
|
|
537
|
+
|
|
320
538
|
HELP_SECTIONS.self = `═══════════════════════════════════════════════════════════════════════════
|
|
321
539
|
SELF-COMMANDS (type inside an shmakk session)
|
|
322
540
|
═══════════════════════════════════════════════════════════════════════════
|
|
@@ -372,6 +590,15 @@ HELP_SECTIONS.self = `═══════════════════
|
|
|
372
590
|
enable yes-files | disable yes-files
|
|
373
591
|
enable colors | disable colors
|
|
374
592
|
enable debug | disable debug
|
|
593
|
+
enable stt | disable stt Ctrl+O voice input; disables TTS/STS
|
|
594
|
+
enable tts | disable tts Spoken agent replies; disables STT/STS
|
|
595
|
+
enable sts | disable sts Always-on speech-to-speech; disables STT/TTS
|
|
596
|
+
|
|
597
|
+
-- Vibedit --
|
|
598
|
+
/vibedit <url | path> Launch visual editing overlay on a web app
|
|
599
|
+
/vibedit-electron <port> Connect overlay to an Electron app via CDP
|
|
600
|
+
/ve <port> Short alias for /vibedit-electron
|
|
601
|
+
shmakk browser-daemon Run Chrome extension automation backend
|
|
375
602
|
|
|
376
603
|
-- Workflows --
|
|
377
604
|
list workflows Show available automation workflows
|
package/src/completions.js
CHANGED
|
@@ -41,6 +41,7 @@ const FLAGS = [
|
|
|
41
41
|
{ flag: '--profile-set', arg: '<name>', desc: 'Switch profile and restart' },
|
|
42
42
|
{ flag: '--endpoint', arg: '<name>', desc: 'Use model preset from ~/.config/shmakk/endpoints.json' },
|
|
43
43
|
{ flag: '--colors', arg: '<true|false>', desc: 'Toggle ANSI colors' },
|
|
44
|
+
{ flag: '--vim', arg: '<vi|vim|disable>', desc: 'Intercept vi/vim with shmakk Vim mode' },
|
|
44
45
|
{ flag: '--load-skill', arg: '<name>', desc: 'Load a skill into workspace state' },
|
|
45
46
|
{ flag: '--unload-skill', arg: '<name>', desc: 'Remove skill from registry' },
|
|
46
47
|
{ flag: '--install-skill', arg: '<url>', desc: 'Download and install skill from URL' },
|
|
@@ -79,6 +80,9 @@ function bash() {
|
|
|
79
80
|
} else if (f.flag === '--colors') {
|
|
80
81
|
lines.push(' COMPREPLY=($(compgen -W "true false" -- "$cur"))');
|
|
81
82
|
lines.push(' return');
|
|
83
|
+
} else if (f.flag === '--vim') {
|
|
84
|
+
lines.push(' COMPREPLY=($(compgen -W "vi vim disable" -- "$cur"))');
|
|
85
|
+
lines.push(' return');
|
|
82
86
|
} else {
|
|
83
87
|
lines.push(' COMPREPLY=()');
|
|
84
88
|
lines.push(' return');
|
|
@@ -122,6 +126,8 @@ function zsh() {
|
|
|
122
126
|
lines.push(` "${f.flag}[${f.desc}]:shell:(bash zsh fish)" \\`);
|
|
123
127
|
} else if (f.flag === '--colors') {
|
|
124
128
|
lines.push(` "${f.flag}[${f.desc}]:value:(true false)" \\`);
|
|
129
|
+
} else if (f.flag === '--vim') {
|
|
130
|
+
lines.push(` "${f.flag}[${f.desc}]:mode:(vi vim disable)" \\`);
|
|
125
131
|
} else {
|
|
126
132
|
lines.push(` "${f.flag}[${f.desc}]: :" \\`);
|
|
127
133
|
}
|
|
@@ -148,6 +154,8 @@ function fish() {
|
|
|
148
154
|
lines.push(`complete -c shmakk -l ${f.flag.slice(2)} -d '${f.desc}' -xa 'bash zsh fish'`);
|
|
149
155
|
} else if (f.flag === '--colors') {
|
|
150
156
|
lines.push(`complete -c shmakk -l ${f.flag.slice(2)} -d '${f.desc}' -xa 'true false'`);
|
|
157
|
+
} else if (f.flag === '--vim') {
|
|
158
|
+
lines.push(`complete -c shmakk -l ${f.flag.slice(2)} -d '${f.desc}' -xa 'vi vim disable'`);
|
|
151
159
|
} else {
|
|
152
160
|
// arg but no specific completions
|
|
153
161
|
lines.push(`complete -c shmakk -l ${f.flag.slice(2)} -d '${f.desc}' -r`);
|