opencode-session-port 0.1.1 → 0.1.3

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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  SessionPort is a local plugin for the OpenCode TUI. It captures the sessions of your current project into a single password-encrypted artifact and restores them in another checkout, worktree, or machine. Artifacts travel with Git or any other channel you choose — SessionPort never runs Git commands itself.
6
6
 
7
- > **Status: experimental pre-release (0.1.1).** SessionPort completed one bounded synthetic checkpoint/restore round trip on Windows with OpenCode v2.0.22. That test used test-only password and project-selector seams and staged source, not the npm tarball. Real modal interactions and loading the packed package in OpenCode have not been verified. The checkpoint format may change; no compatibility, security, or platform-support guarantee is made.
7
+ > **Status: experimental pre-release (0.1.3).** SessionPort completed one bounded synthetic checkpoint/restore round trip on Windows with OpenCode v2.0.22. That test used test-only password and project-selector seams and staged source, not the npm tarball. On one real Windows OpenCode v2.0.22 host, a bounded diagnostic observed both commands registered (`commands=yes`) but hidden from the command palette and slash list until the keymap layer opted into global mode; 0.1.2 applies that global-mode registration fix, with focused command-registration tests and the TUI build passing. 0.1.3 additionally enables the commands on macOS and Linux through an explicit platform allowlist (`win32`/`darwin`/`linux`); macOS and Linux have NOT been host-tested, and cross-OS artifact interchange is UNVERIFIED. End-to-end execution from the packed package has not been host-tested. Real modal interactions and loading the packed package in OpenCode have not been verified. The checkpoint format may change; no compatibility, security, or platform-support guarantee is made.
8
8
 
9
9
  ## Commands
10
10
 
@@ -16,26 +16,25 @@ Both commands are registered by the plugin as `sessionport.checkpoint` and `sess
16
16
  ## Requirements
17
17
 
18
18
  - OpenCode with the v2 TUI plugin API (exercised with OpenCode v2.0.22).
19
- - Windows. The current build enables the commands on Windows only; macOS and Linux are intended targets but are not yet enabled or validated.
19
+ - Windows, macOS, or Linux. The build enables the commands on all three through an explicit platform allowlist (`win32`/`darwin`/`linux`); other platforms are not enabled. Windows has the bounded host evidence above; macOS and Linux are enabled but NOT host-tested, and cross-OS artifact interchange is UNVERIFIED.
20
20
 
21
21
  ## Install
22
22
 
23
- Install the package plugin with the OpenCode CLI:
23
+ Add the plugin to the `plugins` array in your global CLI-only config (`cli.json`):
24
24
 
25
- ```sh
26
- opencode plugin add opencode-session-port@0.1.1
25
+ ```json
26
+ {
27
+ "plugins": ["opencode-session-port@0.1.3"]
28
+ }
27
29
  ```
28
30
 
29
- Or add it to the `plugins` array in your `opencode.jsonc` (or `opencode.json`):
31
+ Or install the package plugin with the OpenCode CLI:
30
32
 
31
- ```jsonc
32
- {
33
- "$schema": "https://opencode.ai/config.json",
34
- "plugins": ["opencode-session-port@0.1.1"]
35
- }
33
+ ```sh
34
+ opencode plugin add opencode-session-port@0.1.3
36
35
  ```
37
36
 
38
- These are the documented OpenCode v2 setup paths; the published tarball has not yet been loaded by OpenCode. The final tarball passed npm consumer checks, but a direct Bun package-manager install timed out in the verification environment, so that install path remains unverified.
37
+ `cli.json` is the documented OpenCode v2 config for CLI-only plugins: they run locally in the terminal and remain active when the CLI connects to a remote server. No published tarball exists yet, so no published artifact has been loaded by OpenCode. The 0.1.1 tarball passed npm consumer checks, but a direct Bun package-manager install timed out in the verification environment, so that install path remains unverified. The 0.1.2 tarball passed manifest/allowlist and packed-entry checks only. The 0.1.3 metadata/platform-allowlist update has not been package-verified, published, or loaded by OpenCode.
39
38
 
40
39
  ## Usage
41
40
 
package/dist/tui.js CHANGED
@@ -10149,6 +10149,7 @@ function installSessionPortCommands(context, handlers) {
10149
10149
  append: "app",
10150
10150
  render() {
10151
10151
  context.keymap.layer(() => ({
10152
+ mode: "global",
10152
10153
  commands: [{
10153
10154
  id: SESSIONPORT_COMMAND_IDS.checkpoint,
10154
10155
  title: "Checkpoint project sessions",
@@ -10193,7 +10194,7 @@ var init_sessionport_commands = __esm(() => {
10193
10194
 
10194
10195
  // src/tui/wiring/install.ts
10195
10196
  async function installSessionPortWiring(context, options = {}) {
10196
- if ((options.platform ?? process.platform) !== "win32")
10197
+ if (!SUPPORTED_PLATFORMS.includes(options.platform ?? process.platform))
10197
10198
  return;
10198
10199
  const cryptoFactory = await (options.createCryptoFactory ?? createExperimentalCryptoFactory)();
10199
10200
  const idDeriver = await (options.createIdDeriver ?? createRemappedIdDeriver)();
@@ -10221,6 +10222,7 @@ async function installSessionPortWiring(context, options = {}) {
10221
10222
  async function createExperimentalCryptoFactory() {
10222
10223
  return createCheckpointCryptoFactory([EXPERIMENTAL_CRYPTO_POLICY_DEFINITION]);
10223
10224
  }
10225
+ var SUPPORTED_PLATFORMS;
10224
10226
  var init_install = __esm(() => {
10225
10227
  init_crypto();
10226
10228
  init_restore();
@@ -10230,6 +10232,7 @@ var init_install = __esm(() => {
10230
10232
  init_sessionport_commands();
10231
10233
  init_composition();
10232
10234
  init_experimental_profile();
10235
+ SUPPORTED_PLATFORMS = ["win32", "darwin", "linux"];
10233
10236
  });
10234
10237
 
10235
10238
  // src/tui/wiring/index.ts
@@ -10262,10 +10265,11 @@ var init_wiring = __esm(() => {
10262
10265
 
10263
10266
  // src/tui.ts
10264
10267
  import { Plugin } from "@opencode/plugin/tui";
10268
+ var SUPPORTED_PLATFORMS2 = ["win32", "darwin", "linux"];
10265
10269
  var tui_default = Plugin.define({
10266
10270
  id: "sessionport",
10267
10271
  async setup(context) {
10268
- if (process.platform !== "win32")
10272
+ if (!SUPPORTED_PLATFORMS2.includes(process.platform))
10269
10273
  return;
10270
10274
  const { installSessionPortWiring: installSessionPortWiring2 } = await Promise.resolve().then(() => (init_wiring(), exports_wiring));
10271
10275
  return installSessionPortWiring2(context);
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "opencode-session-port",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "license": "MIT",
6
- "description": "SessionPort: experimental Windows-first OpenCode TUI plugin for password-encrypted session checkpoint and restore.",
6
+ "description": "SessionPort: experimental OpenCode TUI plugin for password-encrypted session checkpoint and restore.",
7
7
  "keywords": [
8
8
  "opencode",
9
9
  "opencode-plugin",
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Experimental project-location resolver over the public TUI client
3
- * `context.client.location.get` method (Windows-first experimental lane).
3
+ * `context.client.location.get` method (experimental wiring lane).
4
4
  *
5
5
  * Scope and boundaries (owner decision 2026-10-11, decision-log F):
6
6
  * - `Plugin.Context.location` carries only a directory, so the experimental
@@ -17,7 +17,10 @@ export interface SessionPortCommandHost {
17
17
  }
18
18
 
19
19
  /**
20
- * Register native slash commands from an app-slot component scope. The slot
20
+ * Register native slash commands from an app-slot component scope. The layer
21
+ * opts out of the default `base` input mode with `mode: "global"` so the
22
+ * commands are reachable from every OpenCode input mode (palette and slash
23
+ * discovery included); without it the host hides them outside `base`. The slot
21
24
  * disposer is returned unchanged so the plugin can clean up its contribution.
22
25
  * Command input is forwarded as received; parsing belongs to the injected
23
26
  * handlers.
@@ -30,6 +33,7 @@ export function installSessionPortCommands(
30
33
  append: "app",
31
34
  render() {
32
35
  context.keymap.layer(() => ({
36
+ mode: "global",
33
37
  commands: [
34
38
  {
35
39
  id: SESSIONPORT_COMMAND_IDS.checkpoint,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SessionPort TUI command composition (Phase 2 experimental Windows wiring).
2
+ * SessionPort TUI command composition (Phase 2 experimental wiring).
3
3
  *
4
4
  * `createSessionPortHandlers` composes the completed Phase 2-4 seams into the
5
5
  * two injected command callbacks consumed by `installSessionPortCommands`:
@@ -112,7 +112,7 @@ export interface SessionPortHandlerDependencies {
112
112
  readonly showRestoreReport: (model: RestoreReportPresentationModel) => void;
113
113
  /** Masked password provider (real UI or a fake in tests). */
114
114
  readonly requestPassword: SessionPortPasswordProvider;
115
- /** Initialized crypto factory; production uses the experimental Windows profile. */
115
+ /** Initialized crypto factory; production uses the experimental profile (historical `-win-` selector name). */
116
116
  readonly cryptoFactory: CheckpointCryptoFactory;
117
117
  /** Remapped-ID deriver for restore planning. */
118
118
  readonly idDeriver: RemappedIdDeriver;
@@ -1,10 +1,17 @@
1
1
  /**
2
- * Windows-first experimental runtime defaults (Phase 2 wiring).
2
+ * Experimental runtime defaults (Phase 2 wiring; originally recorded for the
3
+ * Windows-first lane).
4
+ *
5
+ * The `sessionport-experimental-win-v1` selector name is historical and is NOT
6
+ * portability evidence: enabling macOS/Linux changes no profile, format, or cap
7
+ * value below.
3
8
  *
4
9
  * These are the explicitly selected, owner-authorized experimental values
5
- * recorded in `docs/v1/decision-log.md` (2026-10-11 entries) for a Windows
6
- * experimental build only. They are NOT a production approval, not a format
7
- * freeze, and not a general memory budget, compatibility, or support claim.
10
+ * recorded in `docs/v1/decision-log.md` (2026-10-11 entries) for the Windows
11
+ * experimental build; they now apply unchanged to the experimental macOS/Linux
12
+ * enablement, which is NOT host-tested. They are NOT a production approval, not
13
+ * a format freeze, and not a general memory budget, compatibility, or support
14
+ * claim.
8
15
  *
9
16
  * - Crypto profile `sessionport-experimental-win-v1`: profile code 1,
10
17
  * Argon2id13 `crypto_pwhash`, `opslimit=2`, `memlimit=128 MiB`, the current
@@ -22,7 +29,7 @@ import type { CryptoPolicy } from "../../core/contracts/index.ts";
22
29
  import type { CryptoPolicyDefinition } from "../../core/crypto/index.ts";
23
30
  import type { SessionCollectionPolicy } from "../../core/sessions/index.ts";
24
31
 
25
- /** Explicit allow-listed policy id for the Windows experimental profile. */
32
+ /** Explicit allow-listed policy id for the experimental profile (historical `-win-` name). */
26
33
  export const EXPERIMENTAL_CRYPTO_POLICY_ID = "sessionport-experimental-win-v1";
27
34
 
28
35
  /** The explicit policy selector passed to the crypto factory; never read from an artifact. */
@@ -2,10 +2,10 @@
2
2
  * SessionPort TUI wiring (Phase 2 experimental Windows lane).
3
3
  *
4
4
  * Public surface:
5
- * - `installSessionPortWiring(context, options?)` — Windows-only install root:
6
- * pinned-sodium initialization, real adapters/artifact I/O/password modal,
7
- * command registration through the existing component-scoped seam, and the
8
- * slot disposer returned unchanged.
5
+ * - `installSessionPortWiring(context, options?)` — install root gated to the
6
+ * explicit `win32`/`darwin`/`linux` allowlist: pinned-sodium initialization,
7
+ * real adapters/artifact I/O/password modal, command registration through the
8
+ * existing component-scoped seam, and the slot disposer returned unchanged.
9
9
  * - `createSessionPortHandlers(dependencies)` — fully injected composition of
10
10
  * the `/checkpoint` and `/restore` command callbacks (fake-based testable).
11
11
  * - Experimental runtime defaults (crypto profile + collection bounds +
@@ -16,7 +16,8 @@
16
16
  * is written, only encrypted artifacts are read, and every failure report is
17
17
  * generic/sanitized. No production approval, format freeze, or platform-support
18
18
  * claim is made (O-01/O-02/O-03 remain PARTIALLY RESOLVED for the experimental
19
- * Windows build only; OQ-16 stays OPEN).
19
+ * build only — the `-win-` profile selector name is historical; OQ-16 stays
20
+ * OPEN).
20
21
  */
21
22
 
22
23
  export {
@@ -1,13 +1,16 @@
1
1
  /// <reference types="node" />
2
2
  /**
3
- * SessionPort TUI install/composition root (Phase 2 experimental Windows wiring).
3
+ * SessionPort TUI install/composition root (Phase 2 experimental wiring).
4
4
  *
5
5
  * `installSessionPortWiring` is the only host-facing composition entry:
6
6
  *
7
- * - **Windows-first experimental only.** On any non-`win32` platform it returns
8
- * `undefined` immediately: no sodium initialization, no host-context access,
9
- * no command registration, and no platform-support claim.
10
- * - On Windows it initializes the pinned `libsodium-wrappers-sumo@0.8.4`
7
+ * - **Explicit platform allowlist (`win32`/`darwin`/`linux`), experimental
8
+ * only.** On any other platform it returns `undefined` immediately: no sodium
9
+ * initialization, no host-context access, no command registration, and no
10
+ * platform-support claim. Windows has bounded actual-host evidence; macOS and
11
+ * Linux are enabled but NOT host-tested, and cross-OS artifact interchange is
12
+ * UNVERIFIED.
13
+ * - On an allowed platform it initializes the pinned `libsodium-wrappers-sumo@0.8.4`
11
14
  * runtime first (`await sodium.ready` plus primitive/constant validation
12
15
  * through `createCheckpointCryptoFactory`; `createRemappedIdDeriver` also
13
16
  * awaits/validates it) and fails closed: a rejected initialization aborts
@@ -25,8 +28,8 @@
25
28
  * This module statically imports the designer-owned UI modules (password modal
26
29
  * and restore report dialog), which import the optional UI peers
27
30
  * (`@opentui/solid`, `solid-js`). The entry (`src/tui.ts`) imports this module
28
- * dynamically only after its `process.platform === "win32"` check, so
29
- * non-Windows plugin setup never evaluates those modules.
31
+ * dynamically only after its own allowlist check, so unsupported-platform
32
+ * plugin setup never evaluates those modules.
30
33
  *
31
34
  * Test seams (platform/factory/deriver/password provider) exist only for
32
35
  * fake-based tests; production calls use the real defaults. The real password
@@ -49,7 +52,7 @@ import { EXPERIMENTAL_CRYPTO_POLICY_DEFINITION } from "./experimental-profile.ts
49
52
  export interface SessionPortInstallOptions {
50
53
  /** Platform gate override for tests; defaults to `process.platform`. */
51
54
  readonly platform?: string;
52
- /** Crypto-factory seam; the default creates the experimental Windows profile and awaits pinned sodium. */
55
+ /** Crypto-factory seam; the default creates the experimental profile (historical `-win-` selector name) and awaits pinned sodium. */
53
56
  readonly createCryptoFactory?: () => Promise<CheckpointCryptoFactory>;
54
57
  /** Remapped-ID deriver seam; the default awaits/validates pinned sodium. */
55
58
  readonly createIdDeriver?: () => Promise<RemappedIdDeriver>;
@@ -57,18 +60,21 @@ export interface SessionPortInstallOptions {
57
60
  readonly requestPassword?: SessionPortPasswordProvider;
58
61
  }
59
62
 
63
+ /** Explicit platform allowlist; unsupported platforms fail closed before any host access. */
64
+ const SUPPORTED_PLATFORMS: readonly string[] = ["win32", "darwin", "linux"];
65
+
60
66
  /**
61
- * Installs the SessionPort commands for the experimental Windows lane and
62
- * returns the slot disposer, or `undefined` when this platform is not
63
- * registered. Fails closed (rejects) when the pinned runtime or the host
64
- * command surface is unavailable; nothing is registered in that case.
67
+ * Installs the SessionPort commands for the experimental lane and returns the
68
+ * slot disposer, or `undefined` when this platform is not registered. Fails
69
+ * closed (rejects) when the pinned runtime or the host command surface is
70
+ * unavailable; nothing is registered in that case.
65
71
  */
66
72
  export async function installSessionPortWiring(
67
73
  context: Plugin.Context,
68
74
  options: SessionPortInstallOptions = {},
69
75
  ): Promise<(() => void) | undefined> {
70
- // Windows-first experimental gate: no registration and no host access anywhere else.
71
- if ((options.platform ?? process.platform) !== "win32") return undefined;
76
+ // Explicit allowlist gate: no registration and no host access on unsupported platforms.
77
+ if (!SUPPORTED_PLATFORMS.includes(options.platform ?? process.platform)) return undefined;
72
78
 
73
79
  // Pinned-runtime initialization (fail closed): the default factory awaits
74
80
  // `sodium.ready` and validates every primitive the provisional format needs;
@@ -102,7 +108,11 @@ export async function installSessionPortWiring(
102
108
  return installSessionPortCommands(context, handlers);
103
109
  }
104
110
 
105
- /** Default factory: the experimental Windows profile over the pinned runtime. */
111
+ /**
112
+ * Default factory: the experimental profile over the pinned runtime. The
113
+ * `sessionport-experimental-win-v1` selector name is historical and is not
114
+ * portability evidence; macOS/Linux enablement changes no profile value.
115
+ */
106
116
  async function createExperimentalCryptoFactory(): Promise<CheckpointCryptoFactory> {
107
117
  return createCheckpointCryptoFactory([EXPERIMENTAL_CRYPTO_POLICY_DEFINITION]);
108
118
  }
package/src/tui.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { Plugin } from "@opencode/plugin/tui"
2
2
 
3
3
  /**
4
- * SessionPort TUI plugin entrypoint (Phase 2 experimental Windows wiring).
4
+ * SessionPort TUI plugin entrypoint (Phase 2 experimental wiring).
5
5
  *
6
- * Setup checks `process.platform` first and only on Windows dynamically imports
6
+ * Setup checks `process.platform` first and only on an explicitly allowed
7
+ * platform (`win32`, `darwin`, or `linux`) dynamically imports
7
8
  * `installSessionPortWiring`, which:
8
- * - registers `/checkpoint` and `/restore` only on Windows (`process.platform
9
- * === "win32"`); every other platform gets no registration and no
10
- * platform-support claim;
9
+ * - registers `/checkpoint` and `/restore` only on those platforms; every other
10
+ * platform gets no registration and no platform-support claim;
11
11
  * - initializes the pinned `libsodium-wrappers-sumo@0.8.4` runtime first and
12
12
  * fails closed if it is unavailable (setup rejects; nothing is registered);
13
13
  * - registers commands inside the existing app-slot/keymap component scope
@@ -15,19 +15,25 @@ import { Plugin } from "@opencode/plugin/tui"
15
15
  *
16
16
  * The platform gate deliberately runs before the dynamic import: the wiring
17
17
  * module statically imports the designer-owned UI modules, which import the
18
- * optional UI peers (`@opentui/solid`, `solid-js`). Non-Windows plugin setup
19
- * therefore never evaluates them, and no OpenTUI dependency is added to the
20
- * package surface.
18
+ * optional UI peers (`@opentui/solid`, `solid-js`). Unsupported-platform plugin
19
+ * setup therefore never evaluates them, and no OpenTUI dependency is added to
20
+ * the package surface.
21
21
  *
22
- * Command handlers own their errors and report sanitized copy; no raw host
23
- * error crosses to the host. The active Windows experimental defaults are
24
- * recorded in `docs/v1/decision-log.md`; this is not a production approval or
25
- * format freeze.
22
+ * Platform status: Windows has bounded actual-host evidence; macOS and Linux
23
+ * are owner-approved experimental targets enabled here but NOT host-tested, and
24
+ * cross-OS artifact interchange is UNVERIFIED. Command handlers own their
25
+ * errors and report sanitized copy; no raw host error crosses to the host. The
26
+ * active experimental defaults are recorded in `docs/v1/decision-log.md`; this
27
+ * is not a production approval or format freeze.
26
28
  */
29
+
30
+ /** Explicit allowlist; unsupported platforms fail closed before any host call. */
31
+ const SUPPORTED_PLATFORMS: readonly string[] = ["win32", "darwin", "linux"]
32
+
27
33
  export default Plugin.define({
28
34
  id: "sessionport",
29
35
  async setup(context) {
30
- if (process.platform !== "win32") return undefined
36
+ if (!SUPPORTED_PLATFORMS.includes(process.platform)) return undefined
31
37
  const { installSessionPortWiring } = await import("./tui/wiring/index.ts")
32
38
  return installSessionPortWiring(context)
33
39
  },
package/tui.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * SessionPort TUI entrypoint shim for the host's directory-based plugin
3
3
  * resolution (`Host.resolve` probes `<directory>/tui` by path, before any
4
4
  * package `exports` lookup). It re-exports the product entrypoint unchanged;
5
- * all behavior (Windows platform gate, pinned-sodium initialization, deferred
5
+ * all behavior (platform allowlist gate, pinned-sodium initialization, deferred
6
6
  * `./tui/wiring/index.ts` import) stays in `src/tui.ts`.
7
7
  *
8
8
  * This file is part of the packaged `files` allowlist so an installed copy of