@somacheck/vibecheck 0.6.11 → 0.6.12
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 +37 -16
- package/claude-marketplace/.claude-plugin/marketplace.json +1 -1
- package/claude-marketplace/plugins/vibecheck/.claude-plugin/plugin.json +1 -1
- package/claude-marketplace/plugins/vibecheck/hooks/hooks.json +1 -1
- package/dist/claude-hook.js +4 -0
- package/dist/cli.js +11 -10
- package/dist/client-setup.js +8 -2
- package/dist/constants.js +1 -1
- package/dist/runtime-mode.js +14 -0
- package/dist/server.js +11 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,13 +9,14 @@ Your agent has your context. It does not have your gut. This is the bridge.
|
|
|
9
9
|
|
|
10
10
|
Fair. Here is what you need, without executing anything.
|
|
11
11
|
|
|
12
|
-
**What the `link` command does.** `npx -y @somacheck/vibecheck@0.6.
|
|
12
|
+
**What the `link` command does.** `npx -y @somacheck/vibecheck@0.6.12 link <CODE> --client <CLIENT>`
|
|
13
13
|
exchanges a short-lived pairing code, generated inside the SomaCheck iOS app, for
|
|
14
14
|
a bearer token. It writes that token to `~/.sensie/config.json` with mode `0600`,
|
|
15
15
|
offers to configure supported agent clients found on the computer, and checks the
|
|
16
16
|
connection without printing the token. For Claude Code it also installs an
|
|
17
|
-
inspectable user-scoped SomaCheck plugin
|
|
18
|
-
|
|
17
|
+
inspectable user-scoped SomaCheck plugin and registers the local MCP server as
|
|
18
|
+
a Channel so a phone result can enter the same open conversation as a new
|
|
19
|
+
event. Setup is not reported ready until the
|
|
19
20
|
selected client has the exact pinned `vibecheck` MCP registration, the backend
|
|
20
21
|
accepts protocol `5` / toolset `vibecheck-0.6`, and both status and context
|
|
21
22
|
probes succeed. It contacts exactly one network host: the Supabase project below.
|
|
@@ -97,9 +98,9 @@ before the pairing code is redeemed.
|
|
|
97
98
|
To configure or repair a client later:
|
|
98
99
|
|
|
99
100
|
```text
|
|
100
|
-
npx -y @somacheck/vibecheck@0.6.
|
|
101
|
-
npx -y @somacheck/vibecheck@0.6.
|
|
102
|
-
npx -y @somacheck/vibecheck@0.6.
|
|
101
|
+
npx -y @somacheck/vibecheck@0.6.12 setup codex
|
|
102
|
+
npx -y @somacheck/vibecheck@0.6.12 setup claude
|
|
103
|
+
npx -y @somacheck/vibecheck@0.6.12 doctor
|
|
103
104
|
```
|
|
104
105
|
|
|
105
106
|
Manual registration remains available:
|
|
@@ -109,13 +110,25 @@ Manual registration remains available:
|
|
|
109
110
|
"mcpServers": {
|
|
110
111
|
"vibecheck": {
|
|
111
112
|
"command": "npx",
|
|
112
|
-
"args": ["-y", "@somacheck/vibecheck@0.6.
|
|
113
|
+
"args": ["-y", "@somacheck/vibecheck@0.6.12", "serve", "--client", "codex"]
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
For Claude Code: `claude mcp add --scope user vibecheck -- npx -y @somacheck/vibecheck@0.6.
|
|
119
|
+
For Claude Code: `claude mcp add --scope user vibecheck -- npx -y @somacheck/vibecheck@0.6.12 serve --client claude --channel`
|
|
120
|
+
|
|
121
|
+
Claude Channels are currently an Anthropic research preview. Until Anthropic
|
|
122
|
+
approves SomaCheck on its channel allowlist, start Claude Code with:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
claude --dangerously-load-development-channels server:vibecheck
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Keep that Claude Code session open. Channel events are queued while Claude is
|
|
129
|
+
busy, but a closed session cannot receive them. Claude does not acknowledge
|
|
130
|
+
channel notifications, so retain the stable `live:<uuid>` request handle as a
|
|
131
|
+
manual recovery path.
|
|
119
132
|
|
|
120
133
|
The link step writes only the bearer token in `~/.sensie/config.json`. The client
|
|
121
134
|
setup step asks Codex or Claude to add the pinned MCP command to that client's own
|
|
@@ -275,14 +288,22 @@ cancellation stops result reads and preserves the backend request and
|
|
|
275
288
|
idempotency key, but the cancelled MCP transport may suppress that pending
|
|
276
289
|
response.
|
|
277
290
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
`
|
|
281
|
-
|
|
282
|
-
answer, expiry, or cancellation arrives.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
291
|
+
Claude Code is the primary local experience. Its registered stdio server
|
|
292
|
+
advertises Anthropic's experimental Channel capability. When
|
|
293
|
+
`request_vibecheck` returns pending, the same local server follows only that
|
|
294
|
+
exact request and emits one `notifications/claude/channel` event when the
|
|
295
|
+
answer, expiry, or cancellation arrives. Claude receives the constrained
|
|
296
|
+
result as conversation input and can continue without another user message.
|
|
297
|
+
The event contains the binary reading, confidence, lifecycle, and opaque
|
|
298
|
+
handle—never the statement, link token, raw motion, or an instruction that
|
|
299
|
+
turns the result into authorization.
|
|
300
|
+
|
|
301
|
+
The installed `PostToolUse` hook remains a compatibility fallback for an
|
|
302
|
+
ordinary non-channel registration. A channel-armed response marks its
|
|
303
|
+
continuation transport explicitly, and the hook abstains, so two watchers
|
|
304
|
+
cannot wake the same turn. During Anthropic's research preview, the channel
|
|
305
|
+
session must be launched with the command above; a closed or non-enabled
|
|
306
|
+
session may silently drop the event.
|
|
286
307
|
|
|
287
308
|
Other standard MCP hosts retain the bounded tool response and stable-handle
|
|
288
309
|
fallback until they provide an equivalent supported wake mechanism. This
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "vibecheck",
|
|
11
11
|
"source": "./plugins/vibecheck",
|
|
12
12
|
"description": "Let Claude offer a vibecheck and continue when the phone result arrives.",
|
|
13
|
-
"version": "0.6.
|
|
13
|
+
"version": "0.6.12",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Sensie",
|
|
16
16
|
"email": "agents@joinsensie.com"
|
package/dist/claude-hook.js
CHANGED
|
@@ -21,6 +21,10 @@ export function parsePendingClaudeAsk(input) {
|
|
|
21
21
|
const structured = record(response.structuredContent ?? response.structured_content ?? response);
|
|
22
22
|
if (structured.state !== "pending" || typeof structured.request_id !== "string")
|
|
23
23
|
return null;
|
|
24
|
+
// The channel-enabled local server already owns this exact result watch.
|
|
25
|
+
// Abstaining prevents the PostToolUse fallback from waking Claude twice.
|
|
26
|
+
if (structured.continuation_transport === "claude_channel")
|
|
27
|
+
return null;
|
|
24
28
|
if (structured.delivery_state === "failed" || structured.delivery_state === "skipped")
|
|
25
29
|
return null;
|
|
26
30
|
const requestId = parseHandle(structured.request_id);
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { SupabaseAgentApi } from "./api.js";
|
|
6
|
-
import { clientDisplayName, detectInstalledClients, detectLegacyHostedRegistration, LocalCommandRunner, manualLegacyHostedRemoveCommand, manualRemoveCommand, manualSetupCommand, parseClientChoice, preflightClientPersistence, registerClient, singleNonInteractiveClientSelection, } from "./client-setup.js";
|
|
6
|
+
import { claudeChannelLaunchCommand, clientDisplayName, detectInstalledClients, detectLegacyHostedRegistration, LocalCommandRunner, manualLegacyHostedRemoveCommand, manualRemoveCommand, manualSetupCommand, parseClientChoice, preflightClientPersistence, registerClient, singleNonInteractiveClientSelection, } from "./client-setup.js";
|
|
7
7
|
import { configureClaudeContinuationPlugin } from "./claude-plugin-setup.js";
|
|
8
8
|
import { readConfig } from "./config.js";
|
|
9
9
|
import { awaitClaudeVibecheckResult } from "./claude-hook.js";
|
|
@@ -11,6 +11,7 @@ import { PACKAGE_SPEC, SUPABASE_PUBLISHABLE_KEY, SUPABASE_URL } from "./constant
|
|
|
11
11
|
import { LinkPersistenceError, NonInteractiveLinkError, linkAgent } from "./link.js";
|
|
12
12
|
import { checkReadiness } from "./readiness.js";
|
|
13
13
|
import { formatRecipeDetail, formatRecipeList, formatRecipePrompt, getRecipeExperience } from "./recipes.js";
|
|
14
|
+
import { parseRuntimeMode } from "./runtime-mode.js";
|
|
14
15
|
import { createVibecheckServer } from "./server.js";
|
|
15
16
|
const api = new SupabaseAgentApi(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY);
|
|
16
17
|
const runner = new LocalCommandRunner();
|
|
@@ -30,6 +31,7 @@ function usage() {
|
|
|
30
31
|
" npx -y @somacheck/vibecheck recipes",
|
|
31
32
|
" npx -y @somacheck/vibecheck recipes --id <id> --format prompt",
|
|
32
33
|
" npx -y @somacheck/vibecheck recipe <id>",
|
|
34
|
+
" npx -y @somacheck/vibecheck serve --client claude --channel",
|
|
33
35
|
].join("\n");
|
|
34
36
|
}
|
|
35
37
|
function parseLinkClient(args) {
|
|
@@ -46,11 +48,6 @@ function parseLinkClient(args) {
|
|
|
46
48
|
return [];
|
|
47
49
|
throw new Error(usage());
|
|
48
50
|
}
|
|
49
|
-
function parseServeClient(args) {
|
|
50
|
-
if (args.length !== 3 || args[0] !== "serve" || args[1] !== "--client")
|
|
51
|
-
return null;
|
|
52
|
-
return args[2] === "codex" || args[2] === "claude" ? args[2] : null;
|
|
53
|
-
}
|
|
54
51
|
async function promptForClients(installed) {
|
|
55
52
|
if (installed.length === 0)
|
|
56
53
|
return [];
|
|
@@ -105,6 +102,7 @@ async function configureClients(clients) {
|
|
|
105
102
|
throw new ClientPreflightError("Could not configure automatic SomaCheck results for Claude Code. No pairing code was used.");
|
|
106
103
|
}
|
|
107
104
|
output(`✓ Automatic Claude result continuation ${plugin.status === "installed" ? "was configured" : "is ready"}.`);
|
|
105
|
+
output(` Start Claude Code with SomaCheck Channels: ${claudeChannelLaunchCommand()}`);
|
|
108
106
|
}
|
|
109
107
|
}
|
|
110
108
|
}
|
|
@@ -180,6 +178,7 @@ async function preflightLinkClients(clients, interactive) {
|
|
|
180
178
|
].join("\n"));
|
|
181
179
|
}
|
|
182
180
|
output("✓ Automatic Claude result continuation is ready before redeeming the pairing code.");
|
|
181
|
+
output(` Start Claude Code with SomaCheck Channels: ${claudeChannelLaunchCommand()}`);
|
|
183
182
|
}
|
|
184
183
|
}
|
|
185
184
|
return selectedClients;
|
|
@@ -201,13 +200,15 @@ async function refreshRuntimeHealth(client) {
|
|
|
201
200
|
context_probe_ok: true,
|
|
202
201
|
});
|
|
203
202
|
}
|
|
204
|
-
async function startServer(
|
|
203
|
+
async function startServer(runtime) {
|
|
204
|
+
const runtimeClient = runtime?.client ?? null;
|
|
205
205
|
const server = createVibecheckServer({
|
|
206
206
|
api,
|
|
207
207
|
loadToken: async () => (await readConfig(homedir(), runtimeClient ?? undefined)).token,
|
|
208
208
|
identity: runtimeClient === null
|
|
209
209
|
? { kind: "legacy" }
|
|
210
210
|
: { kind: "local", client_key: runtimeClient },
|
|
211
|
+
...(runtime?.claudeChannel ? { claudeChannelWatch: {} } : {}),
|
|
211
212
|
});
|
|
212
213
|
await server.connect(new StdioServerTransport());
|
|
213
214
|
if (runtimeClient !== null) {
|
|
@@ -299,9 +300,9 @@ async function main() {
|
|
|
299
300
|
throw new Error(usage());
|
|
300
301
|
return (await runDoctor()) ? 0 : 2;
|
|
301
302
|
}
|
|
302
|
-
const
|
|
303
|
-
if (
|
|
304
|
-
await startServer(
|
|
303
|
+
const runtime = parseRuntimeMode(args);
|
|
304
|
+
if (runtime !== null) {
|
|
305
|
+
await startServer(runtime);
|
|
305
306
|
return 0;
|
|
306
307
|
}
|
|
307
308
|
if (args.length !== 0)
|
package/dist/client-setup.js
CHANGED
|
@@ -26,7 +26,11 @@ export function clientDisplayName(client) {
|
|
|
26
26
|
return client === "codex" ? "Codex / ChatGPT desktop" : "Claude Code";
|
|
27
27
|
}
|
|
28
28
|
function mcpServerArgs(client) {
|
|
29
|
-
|
|
29
|
+
const args = ["-y", PACKAGE_SPEC, "serve", "--client", client];
|
|
30
|
+
return client === "claude" ? [...args, "--channel"] : args;
|
|
31
|
+
}
|
|
32
|
+
export function claudeChannelLaunchCommand() {
|
|
33
|
+
return `claude --dangerously-load-development-channels server:${MCP_SERVER_NAME}`;
|
|
30
34
|
}
|
|
31
35
|
export function manualSetupCommand(client) {
|
|
32
36
|
if (client === "codex") {
|
|
@@ -149,7 +153,9 @@ function isManagedSomaCheckRegistration(client, stdout) {
|
|
|
149
153
|
|| packageArg === "@somacheck/vibecheck@0.6.6"
|
|
150
154
|
|| packageArg === "@somacheck/vibecheck@0.6.7"
|
|
151
155
|
|| packageArg === "@somacheck/vibecheck@0.6.8"
|
|
152
|
-
|| packageArg === "@somacheck/vibecheck@0.6.9"
|
|
156
|
+
|| packageArg === "@somacheck/vibecheck@0.6.9"
|
|
157
|
+
|| packageArg === "@somacheck/vibecheck@0.6.10"
|
|
158
|
+
|| packageArg === "@somacheck/vibecheck@0.6.11")
|
|
153
159
|
&& args.length === 5
|
|
154
160
|
&& args[0] === "-y"
|
|
155
161
|
&& args[1] === packageArg
|
package/dist/constants.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const SUPABASE_URL = "https://pbldcmniommltbdwuykk.supabase.co";
|
|
3
3
|
export const SUPABASE_PUBLISHABLE_KEY = "sb_publishable_af-lUNI2FqEcb-oGy-4uxQ_cnm6kY85";
|
|
4
4
|
export const PACKAGE_NAME = "@somacheck/vibecheck";
|
|
5
|
-
export const PACKAGE_VERSION = "0.6.
|
|
5
|
+
export const PACKAGE_VERSION = "0.6.12";
|
|
6
6
|
export const PACKAGE_SPEC = `${PACKAGE_NAME}@${PACKAGE_VERSION}`;
|
|
7
7
|
export const SOMACHECK_SETUP_URL = "https://testflight.apple.com/join/C4mAH3zz";
|
|
8
8
|
export const MCP_SERVER_NAME = "vibecheck";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Parse only the exact stdio runtime forms installed by this package.
|
|
2
|
+
* Claude Channels are local-only and must never be enabled for Codex. */
|
|
3
|
+
export function parseRuntimeMode(args) {
|
|
4
|
+
if (args[0] !== "serve" || args[1] !== "--client")
|
|
5
|
+
return null;
|
|
6
|
+
if (args.length === 3 && (args[2] === "codex" || args[2] === "claude")) {
|
|
7
|
+
return { client: args[2], claudeChannel: false };
|
|
8
|
+
}
|
|
9
|
+
if (args.length === 4 && args[2] === "claude" && args[3] === "--channel") {
|
|
10
|
+
return { client: "claude", claudeChannel: true };
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=runtime-mode.js.map
|
package/dist/server.js
CHANGED
|
@@ -105,6 +105,7 @@ const liveAskSchema = {
|
|
|
105
105
|
delivery_state: z.enum(["queued", "processing", "sent", "failed", "skipped"]).nullable(),
|
|
106
106
|
cooldown_until: z.string().datetime({ offset: true }).nullable(),
|
|
107
107
|
error_code: liveAskErrorCodeSchema.nullable(),
|
|
108
|
+
continuation_transport: z.enum(["poll", "claude_channel"]).nullable().optional(),
|
|
108
109
|
};
|
|
109
110
|
const agentContextTypeSchema = z.enum([
|
|
110
111
|
"goal", "project", "decision", "commitment", "tension", "question",
|
|
@@ -381,7 +382,15 @@ export function createVibecheckServer(dependencies) {
|
|
|
381
382
|
});
|
|
382
383
|
});
|
|
383
384
|
startClaudeChannelWatch(result, token, identity);
|
|
384
|
-
const
|
|
385
|
+
const channelArmed = supportsClaudeChannel
|
|
386
|
+
&& result.state === "pending"
|
|
387
|
+
&& result.delivery_state !== "failed"
|
|
388
|
+
&& result.delivery_state !== "skipped";
|
|
389
|
+
const structuredContent = {
|
|
390
|
+
...result,
|
|
391
|
+
error_code: null,
|
|
392
|
+
...(channelArmed ? { continuation_transport: "claude_channel" } : {}),
|
|
393
|
+
};
|
|
385
394
|
const text = result.state === "completed"
|
|
386
395
|
? `Vibecheck completed: ${result.verdict}, confidence ${formatChannelConfidence(result.confidence)}${formatUserFeedback(result.user_feedback)}.`
|
|
387
396
|
: result.state === "pending"
|
|
@@ -390,7 +399,7 @@ export function createVibecheckServer(dependencies) {
|
|
|
390
399
|
+ `Open SomaCheck on your phone, signed into the same account, and check Home. `
|
|
391
400
|
+ `If you do not have the app, install it at ${SOMACHECK_SETUP_URL} and finish phone setup. `
|
|
392
401
|
+ `Keep this request ID; do not create a duplicate or claim the phone received it. It expires at ${result.expires_at}.`
|
|
393
|
-
: pendingWaitText(result.request_id, result.expires_at,
|
|
402
|
+
: pendingWaitText(result.request_id, result.expires_at, channelArmed)
|
|
394
403
|
: `This vibecheck is ${result.state}.`;
|
|
395
404
|
return { content: [{ type: "text", text }], structuredContent };
|
|
396
405
|
}
|
package/package.json
CHANGED