@subshell-ai/plugin-claude-code 0.0.1 → 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/dist/index.d.ts +31 -8
- package/dist/index.js +23 -11
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../../plugin-api/dist/types-
|
|
1
|
+
//#region ../../plugin-api/dist/types-CzNsDcbd.d.ts
|
|
2
2
|
//#region src/types.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* The contract a Subshell plugin implements.
|
|
@@ -81,8 +81,8 @@ interface BuildCommandInput {
|
|
|
81
81
|
* declares the `resume` capability. `mode: "start"` means the conversation
|
|
82
82
|
* is NEW and must be created under exactly this id (pin it, because the host
|
|
83
83
|
* stores it and later resumes by it); `mode: "resume"` names an EXISTING
|
|
84
|
-
* conversation to continue (the host only asks after {@link HarnessResume.
|
|
85
|
-
*
|
|
84
|
+
* conversation to continue (the host only asks after {@link HarnessResume.resumePath}
|
|
85
|
+
* pointed at a file the host found there).
|
|
86
86
|
*/
|
|
87
87
|
harnessSession?: {
|
|
88
88
|
id: string;
|
|
@@ -95,18 +95,31 @@ interface BuildCommandInput {
|
|
|
95
95
|
*
|
|
96
96
|
* The ids here are HARNESS conversation ids (a claude transcript uuid, say),
|
|
97
97
|
* never subshell ids: the host pins {@link allocateHarnessSessionId} at launch,
|
|
98
|
-
* stores it on the subshell row, and consults {@link
|
|
98
|
+
* stores it on the subshell row, and consults {@link resumePath} before every
|
|
99
99
|
* restart to choose between continuing and starting fresh.
|
|
100
|
+
*
|
|
101
|
+
* Both members are PURE, and that is the load-bearing property (spec
|
|
102
|
+
* 2026-09-10 §5): a resume runs on the CONTROL PLANE, for a pane that lives on
|
|
103
|
+
* a machine the plane cannot see. Computing (rather than checking) is what
|
|
104
|
+
* lets one plugin implementation serve local and remote restarts identically.
|
|
100
105
|
*/
|
|
101
106
|
interface HarnessResume {
|
|
102
107
|
/** Allocates the HARNESS conversation id to pin at launch (a uuid for claude). */
|
|
103
108
|
allocateHarnessSessionId(): string;
|
|
104
109
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
110
|
+
* Where the resumable transcript would be, given the target machine's
|
|
111
|
+
* environment. PURE: it computes a path and never touches a filesystem, so
|
|
112
|
+
* the control plane can build it for a machine it cannot see. The HOST
|
|
113
|
+
* checks existence.
|
|
108
114
|
*/
|
|
109
|
-
|
|
115
|
+
resumePath(harnessSessionId: string, cwd: string, hostEnv: HostEnv): string;
|
|
116
|
+
}
|
|
117
|
+
/** The parts of a target machine's environment a plugin may compute against. */
|
|
118
|
+
interface HostEnv {
|
|
119
|
+
/** The node's home directory */
|
|
120
|
+
homeDir: string;
|
|
121
|
+
/** Values for the variables this plugin's manifest declared it needs */
|
|
122
|
+
env: Record<string, string>;
|
|
110
123
|
}
|
|
111
124
|
/** How to spawn the `subshell mcp` stdio server. */
|
|
112
125
|
interface McpLaunchSpec {
|
|
@@ -299,6 +312,16 @@ interface SubshellManifest {
|
|
|
299
312
|
detect?: DetectSpec;
|
|
300
313
|
/** Install guidance shown when the binary is missing */
|
|
301
314
|
install?: InstallSpec;
|
|
315
|
+
/**
|
|
316
|
+
* Environment variables this plugin computes against (spec 2026-09-10 §5).
|
|
317
|
+
*
|
|
318
|
+
* The node reports the VALUES of exactly these names at `ready`, so the
|
|
319
|
+
* reported set grows by declaration rather than a machine shipping its
|
|
320
|
+
* whole environment to the control plane. Declaring data is deliberate: a
|
|
321
|
+
* WRONG name is silent, yielding an absent key and the plugin's own
|
|
322
|
+
* fallback, i.e. a resume that quietly never offers itself (§11).
|
|
323
|
+
*/
|
|
324
|
+
hostEnv?: string[];
|
|
302
325
|
}
|
|
303
326
|
//#endregion
|
|
304
327
|
//#region src/manifest.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
1
|
import { join, resolve } from "node:path";
|
|
4
|
-
//#region ../../plugin-api/dist/manifest-
|
|
2
|
+
//#region ../../plugin-api/dist/manifest-UFScnYqn.js
|
|
5
3
|
/** Every {@link PluginType}, for anything that has to iterate or validate them. */
|
|
6
4
|
const PLUGIN_TYPES = ["agent-harness", "terminal"];
|
|
7
5
|
/**
|
|
@@ -62,6 +60,11 @@ function parseManifest(pkgJson) {
|
|
|
62
60
|
docsUrl: i.docsUrl
|
|
63
61
|
};
|
|
64
62
|
}
|
|
63
|
+
let hostEnv;
|
|
64
|
+
if (block.hostEnv !== void 0) {
|
|
65
|
+
if (!Array.isArray(block.hostEnv) || !block.hostEnv.every((k) => typeof k === "string" && k.trim() !== "")) return { error: "`subshell.hostEnv` must be an array of environment variable names" };
|
|
66
|
+
hostEnv = [...block.hostEnv];
|
|
67
|
+
}
|
|
65
68
|
return {
|
|
66
69
|
apiVersion: block.apiVersion,
|
|
67
70
|
id: block.id,
|
|
@@ -71,7 +74,8 @@ function parseManifest(pkgJson) {
|
|
|
71
74
|
...typeof block.icon === "string" ? { icon: block.icon } : {},
|
|
72
75
|
entry: block.entry,
|
|
73
76
|
...detect ? { detect } : {},
|
|
74
|
-
...install ? { install } : {}
|
|
77
|
+
...install ? { install } : {},
|
|
78
|
+
...hostEnv ? { hostEnv } : {}
|
|
75
79
|
};
|
|
76
80
|
}
|
|
77
81
|
//#endregion
|
|
@@ -115,7 +119,7 @@ function validateGenericProfile(profile) {
|
|
|
115
119
|
const parsed = parseManifest({
|
|
116
120
|
name: "@subshell-ai/plugin-claude-code",
|
|
117
121
|
description: "Claude Code harness plugin for Subshell",
|
|
118
|
-
version: "0.0
|
|
122
|
+
version: "1.0.0",
|
|
119
123
|
license: "Apache-2.0",
|
|
120
124
|
type: "module",
|
|
121
125
|
main: "dist/index.js",
|
|
@@ -162,6 +166,7 @@ const parsed = parseManifest({
|
|
|
162
166
|
".npm-global/bin/claude"
|
|
163
167
|
]
|
|
164
168
|
},
|
|
169
|
+
"hostEnv": ["CLAUDE_CONFIG_DIR"],
|
|
165
170
|
"install": {
|
|
166
171
|
"command": "curl -fsSL https://claude.ai/install.sh | bash",
|
|
167
172
|
"docsUrl": "https://code.claude.com/docs/en/setup"
|
|
@@ -387,11 +392,6 @@ const ATTENTION_HOOKS = {
|
|
|
387
392
|
command: sessionReportPing()
|
|
388
393
|
}] }]
|
|
389
394
|
};
|
|
390
|
-
/** Claude's state dir: the documented override, else `~/.claude`. */
|
|
391
|
-
function claudeConfigDir() {
|
|
392
|
-
const override = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
393
|
-
return override ? resolve(override) : join(homedir(), ".claude");
|
|
394
|
-
}
|
|
395
395
|
/** Claude's transcript folder name for a project dir: every non-alphanumeric → `-`. */
|
|
396
396
|
function projectSlug(cwd) {
|
|
397
397
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
@@ -431,7 +431,19 @@ const createPlugin = (_host) => ({
|
|
|
431
431
|
*/
|
|
432
432
|
resume: {
|
|
433
433
|
allocateHarnessSessionId: () => crypto.randomUUID(),
|
|
434
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Claude's state dir: the documented override, else `<homeDir>/.claude`.
|
|
436
|
+
* Both halves come from the TARGET machine's `ready` report, never from
|
|
437
|
+
* this process, and no filesystem is touched (spec 2026-09-10 §5) — that
|
|
438
|
+
* is what lets the control plane build the path for a node it cannot
|
|
439
|
+
* see. The host stats the result and decides; this member cannot answer
|
|
440
|
+
* whether the transcript exists.
|
|
441
|
+
*/
|
|
442
|
+
resumePath: (harnessSessionId, cwd, hostEnv) => {
|
|
443
|
+
const override = hostEnv.env.CLAUDE_CONFIG_DIR?.trim();
|
|
444
|
+
const configDir = override ? resolve(override) : join(hostEnv.homeDir, ".claude");
|
|
445
|
+
return join(configDir, "projects", projectSlug(cwd), `${harnessSessionId}.jsonl`);
|
|
446
|
+
}
|
|
435
447
|
},
|
|
436
448
|
buildCommand(input) {
|
|
437
449
|
const { binary, profile, subshellName, extraFlags, mcp, harnessSession } = input;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subshell-ai/plugin-claude-code",
|
|
3
3
|
"description": "Claude Code harness plugin for Subshell",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
".npm-global/bin/claude"
|
|
55
55
|
]
|
|
56
56
|
},
|
|
57
|
+
"hostEnv": ["CLAUDE_CONFIG_DIR"],
|
|
57
58
|
"install": {
|
|
58
59
|
"command": "curl -fsSL https://claude.ai/install.sh | bash",
|
|
59
60
|
"docsUrl": "https://code.claude.com/docs/en/setup"
|