# Cowork probe Plan Step 1 (M1). An empirical record of what this operator's Cowork installation actually does, measured before any code depends on it. Operator decision 7 — Python as a CLI plus a host-side stdio MCP server — is void if host-side servers never appear in a Cowork session. That is not knowable from Claude Code, so it is measured here first, and the milestone that depends on it carries a written degradation branch either way. **Status: unanswered.** All four questions require the operator sitting in a Cowork session on this Mac. The executor session built the probe vehicle and this checklist; it did not and could not answer them. The verify command for this step is written so an unanswered checklist *fails*: ```bash test "$(grep -cE '^- (Sesjonsmodus|Host-MCP|python3|CLAUDE_PLUGIN_ROOT): +(lokal VM|sky|ja|nei)\b' docs/cowork-probe.md)" = 4 ``` A bullet still reading `ubesvart` does not match, the count drops below four, and the command exits non-zero. That is the intended behaviour until the operator has run the probe. ## Results Overwrite `ubesvart` with one of the allowed answers, and put the date of the measurement in the Measured column. A `nei` is a result, not a failure — it selects the degradation branch below. - Sesjonsmodus: ubesvart - Host-MCP: ubesvart - python3: ubesvart - CLAUDE_PLUGIN_ROOT: ubesvart | Bullet | What the operator does in Cowork | Allowed answer | Measured | |---|---|---|---| | `- Sesjonsmodus:` | Open a Cowork session and read whether it is a local VM or cloud | `lokal VM` or `sky` | | | `- Host-MCP:` | Upload `jobbsok-probe.plugin` via Customize -> Plugins; does `probe-tools` appear as a connector, and does `probe_ping` return? | `ja` or `nei` | | | `- python3:` | Run the `probe-versjon` skill; does it succeed in invoking `python3`, and which version does it report? | `ja` or `nei`, followed by the reported version | | | `- CLAUDE_PLUGIN_ROOT:` | Run `probe-versjon`; does it print a resolved absolute path, or the literal variable name? | `ja` or `nei` | | ### What is already known, and what is not Measured 2026-09-04 from Claude Code, before the probe was built: - Cowork is installed and available on this Intel Mac. - The **session mode is not readable from disk.** `cowork_settings.json` carries only `extraKnownMarketplaces`; the desktop config carries `coworkNetworkMode` and a trusted-folder list, and neither states where a session runs. So `- Sesjonsmodus:` cannot be answered by reading files — it has to be read off a live session. - The other three each require a plugin installed in a live Cowork session. Nothing about them is decidable from Claude Code. ## The probe vehicle `jobbsok-probe` — a throwaway test plugin, deliberately **not** the `jobbsok` plugin itself. `jobbsok`'s own `.mcp.json` (Step 12) and packaging script (Step 13) land eleven steps later, and this probe must not wait for them. It holds exactly four files, under `tests/fixtures/cowork-probe/`: | File | What it is for | |---|---| | `.claude-plugin/plugin.json` | Manifest. Name `jobbsok-probe`, version `0.0.1`. The version is what `probe-versjon` echoes, so a mismatch reveals a cached build. | | `skills/probe-versjon/SKILL.md` | A skill that reports the manifest version, the resolved `${CLAUDE_PLUGIN_ROOT}`, and whether it can invoke `python3`. Answers three of the four questions. | | `.mcp.json` | Declares one stdio server, `probe-tools`. Its appearance in the session is the whole `- Host-MCP:` question. | | `probe_tools.py` | Standard-library JSON-RPC server exposing one tool, `probe_ping`, returning the interpreter actually running it. No third-party imports: a server that failed on a missing dependency would answer a different question than the one asked. | Verified from Claude Code 2026-09-04: the server completes an `initialize` handshake, lists `probe_ping`, returns an interpreter version on `tools/call`, and rejects an unknown tool name. What is unverified is whether Cowork ever starts it. ### Building the archive Run from the repository root. The file list is explicit, and that is the point: ```bash cd tests/fixtures/cowork-probe && \ zip -X /tmp/jobbsok-probe.plugin \ .claude-plugin/plugin.json \ .mcp.json \ probe_tools.py \ skills/probe-versjon/SKILL.md ``` Never `zip -r` over the repository root. A recursive archive of the repo would ship `.git`, `STATE.md`, `.claude/` and the virtualenv into an uploaded plugin. The include list above names the four files and can carry nothing else. ## Running the probe, step by step Everything below happens in Claude Cowork on this Mac, not in Claude Code. Where a UI path is named it comes from Anthropic's own documentation (`research/03-cowork-plugin-compatibility.md`, dimensions 1 and 6); where the wording in the app turns out to differ, trust the app and note what you saw -- a changed menu label is itself a finding worth recording. ### A. Read the session mode -> answers `- Sesjonsmodus:` Open Cowork and find its session-location setting (Cowork -> Settings). You are looking for whether sessions run **on this machine** or **in the cloud**. - On this machine: shell commands execute in a dedicated local Linux VM (Apple Virtualization.framework), which needs working hardware virtualization; Claude runs a readiness check for exactly that. - In the cloud: code runs on Anthropic's servers. This has been the default since 2026-07-07, so do not assume local just because the Mac is capable. Write `lokal VM` or `sky`. **Do this one first**, because it very likely decides question B below: Anthropic's documentation states that local MCP servers do not run in cloud sessions. If you answer `sky` here and `ja` to `- Host-MCP:`, that combination contradicts the documentation and is a much more interesting result than either answer alone -- say so in the Measured column. ### B. Install the probe plugin (needed for C, D and E) Two documented routes; either is fine. 1. Customize -> Plugins, choose the install-from-file / upload option, and pick `/tmp/jobbsok-probe.plugin`. 2. Or drag the `.plugin` file into the Cowork chat. Anthropic's own plugin packaging skill says a `.plugin` file appears in the chat as a rich preview with a button to accept it. Known wrinkle, not your mistake if it happens: uploaded plugins have been reported not to survive an app relaunch (claude-code#65426, June 2026). If the plugin disappears later, re-upload it rather than concluding anything about the probe. ### C. Confirm you are testing the build you just uploaded In the Cowork chat, type `/` (or `+`) to list available skills, and run `probe-versjon`. The first thing it reports is the manifest version. It must be **`0.0.1`**. If it reports anything else, Cowork served a cached build rather than the one you uploaded (claude-code#69020, open) -- and then every answer below is about some *other* build. Uninstall, re-upload, and re-run before continuing. This check exists because a stale cache produces confident, wrong measurements. ### D. Read the skill's output -> answers `- python3:` and `- CLAUDE_PLUGIN_ROOT:` Both come from that same `probe-versjon` run. **`- python3:`** -- did the skill succeed in running `python3 -c 'import sys; print(sys.version)'`, and what did it print? Write `ja` followed by the version, or `nei` followed by the error text. One thing to be precise about, because it changes what the answer means: in Cowork, shell commands run inside the sandbox (the local VM, or the cloud environment), **not on your Mac**. So this measures the sandbox's `python3`, not the host's. That is the right thing to measure here -- it tells us whether a skill-invoked script can run in Cowork at all -- but it is not evidence about the interpreter that `scripts/bootstrap.sh` just built a virtualenv for. **`- CLAUDE_PLUGIN_ROOT:`** -- did the skill print a resolved absolute path, or the literal unexpanded string `${CLAUDE_PLUGIN_ROOT}`? Write `ja` or `nei`. An absolute path is the pass; anything literal or empty is `nei`. ### E. Look for the connector -> answers `- Host-MCP:` This is the load-bearing one: it is the entire Cowork half of operator decision 7, and the reason this probe is the first step of the build. A server declared in `.mcp.json` does **not** show up as a skill. In Cowork it appears as a **Connector**. Two checks, and both must hold: 1. **Is it listed?** Customize -> Plugins, open `jobbsok-probe`, and look at its connectors page. Is `probe-tools` there? 2. **Does it answer?** In the chat, ask Claude to call the `probe_ping` tool. It should return JSON containing `python_version` and `python_executable`. Write `ja` only if both hold. If `probe-tools` is listed but never answers, write `nei` and note that it appeared but did not respond -- a connector that does not respond is not a working host-side server, and the difference between "absent" and "present but mute" points at different causes. Unlike D, this one *does* run on your Mac: Anthropic moved local MCP servers out of the sandbox in May 2026 and runs them as ordinary host software. So a `ja` here means the host Python, the host filesystem and `~/jobbsok-workspace` are all reachable from Cowork -- which is what decision 7 is built on. ### F. Record and verify Edit the four bullets under "Results" above, replacing `ubesvart`, and fill in the Measured column with today's date. Then, from the repository root: ```bash test "$(grep -cE '^- (Sesjonsmodus|Host-MCP|python3|CLAUDE_PLUGIN_ROOT): +(lokal VM|sky|ja|nei)\b' docs/cowork-probe.md)" = 4 ``` Exit 0 means the probe is complete and plan Step 1 can be closed. Exit 1 means at least one bullet is still unanswered or was written in a form the grep does not recognise -- check that the answer follows the label directly, with a space, and starts with one of the four allowed words. ## Degradation branch Written now, so the answer does not get decided under pressure later. **If `- Host-MCP:` is `nei`** — host-side stdio servers do not appear in this Cowork installation: 1. Operator decision 7's Cowork half is unavailable. Nothing changes for Claude Code, where the scripts are invoked directly. 2. Every script-backed skill degrades to reading files that the Claude Code CLI produced. The skills stay useful; they stop being able to compute. 3. `Verifiser i Cowork` for the affected milestones means "the skills load and read files produced from Claude Code" — not "the connector answers". 4. The degradation is recorded in `STATE.md`. This is risk H12's mitigation, and it is why the probe is the first step of the build rather than a later check. **If `- python3:` is `nei`** — a skill cannot invoke `python3` in a Cowork session: the same degradation applies, and more broadly, since it removes the CLI half too. Escalate to the operator before building further on decision 7. **If `- CLAUDE_PLUGIN_ROOT:` is `nei`** — the variable does not resolve: every intra-plugin path in the plan is affected, not just this milestone's. Escalate; do not paper over it with hardcoded paths. **If `- Sesjonsmodus:` is `sky`** — sessions run in the cloud, and host-side servers cannot reach this machine at all. `- Host-MCP:` should then read `nei`, and its branch applies. If the two disagree, the disagreement is the finding.