@outerlayer/cli 0.10.1 → 0.10.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @outerlayer/cli
2
2
 
3
+ ## 0.10.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 4e309ad: `outerlayer init` now also adds the OuterLayer docs MCP server, `outerlayer-docs` at `https://docs.outerlayer.ai/mcp`, beside the `outerlayer` one, so your coding agent can look up how OuterLayer works. It goes into the same file, `.mcp.json` or `.outerlayer/mcp.json`, and an entry of that name already there is left as it is. `outerlayer mcp install` is unchanged.
8
+ - a1b7ec0: `outerlayer work list --startable` help now says what makes an item startable: a build request, no open pull request, and no live lease. An item with an open pull request is no longer offered to the implement queue. `outerlayer work build --item <n>` on such an item reruns the amend when a review waits on an agent, and is otherwise refused with `nothing_to_rerun`.
9
+ - 854a747: A runner now updates itself to a release that has no npm provenance attestation. The tarball must still match the registry's digest and pass `npm audit signatures`. An attestation that is present must still name this repository's release workflow and cover the same tarball, and one that cannot be read refuses the release.
10
+
3
11
  ## 0.10.1
4
12
 
5
13
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { addStdioMcpEntryIfAbsent } from './chunk-47RS42OZ.js';
3
+ import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-A56PYPDF.js';
4
4
  import { installStarterPack } from './chunk-SUMWRA7K.js';
5
5
  import { runEmit } from './chunk-YU5GL7QS.js';
6
6
  import { C } from './chunk-YRYMNBGQ.js';
@@ -119,6 +119,9 @@ function runAgentSetup(opts) {
119
119
  const mcp = addStdioMcpEntryIfAbsent(repoRoot);
120
120
  if (mcp.added) written.add(mcp.path);
121
121
  else kept.push(`${mcp.path} (already has an outerlayer server)`);
122
+ const docs = addDocsMcpEntryIfAbsent(repoRoot);
123
+ if (docs.added) written.add(docs.path);
124
+ else kept.push(`${docs.path} (already has an ${DOCS_MCP_SERVER_NAME} server)`);
122
125
  } catch (err) {
123
126
  problems.push(errorMessage(err));
124
127
  }
@@ -186,9 +189,9 @@ function renderPaths(paths, kept) {
186
189
  `;
187
190
  }
188
191
  function renderDone(paths, kept, mcpKept) {
189
- const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer entry was not added to .mcp.json, so its MCP server is not set up. Add it to .mcp.json by hand, or move the servers you wrote into .outerlayer/mcp.json and run \`outerlayer context emit\`.
192
+ const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer and ${DOCS_MCP_SERVER_NAME} entries were not added to .mcp.json, so their MCP servers are not set up. Add them to .mcp.json by hand, or move the servers you wrote into .outerlayer/mcp.json and run \`outerlayer context emit\`.
190
193
  ` : "";
191
- const what = mcpKept ? "the OuterLayer skills" : "the OuterLayer skills and MCP server";
194
+ const what = mcpKept ? "the OuterLayer skills" : "the OuterLayer skills and MCP servers";
192
195
  if (paths.length === 0) {
193
196
  return `${C.green}\u2713${C.reset} Agent setup: already in place, nothing changed
194
197
  ${renderPaths(paths, kept)}${mcpNote}`;
@@ -1 +1 @@
1
- {"id":"2026-10-07T13:16:15.617Z+e27c8d7","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
1
+ {"id":"2026-10-07T19:14:32.738Z+adc613b","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { probeCredentials } from './chunk-4AVAETSU.js';
3
+ import { probeCredentials } from './chunk-ERHJETKP.js';
4
4
  import './chunk-3JVYMD4G.js';
5
5
  import './chunk-I2UOAV7X.js';
6
- import './chunk-ABIWDUMS.js';
6
+ import './chunk-YETTWTAY.js';
7
7
  import './chunk-KZ5M4QOB.js';
8
8
  import './chunk-T6OIJQRT.js';
9
9
  import './chunk-PDTSUOVT.js';
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
4
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
5
- import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'fs';
5
+ import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
6
6
  import { join, dirname } from 'path';
7
7
 
8
8
  createRequire(import.meta.url);
@@ -47,7 +47,7 @@ function readMcpDoc(absPath, relPath) {
47
47
  function mcpTargetPath(repoRoot) {
48
48
  return existsSync(join(repoRoot, ".outerlayer", "mcp.json")) ? ".outerlayer/mcp.json" : ".mcp.json";
49
49
  }
50
- function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
50
+ function addMcpEntryIfAbsent(repoRoot, name, entry) {
51
51
  const relPath = mcpTargetPath(repoRoot);
52
52
  const absPath = join(repoRoot, relPath);
53
53
  const doc = readMcpDoc(absPath, relPath);
@@ -57,12 +57,19 @@ function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
57
57
  }
58
58
  const existing = servers ?? {};
59
59
  if (name in existing) return { path: relPath, added: false };
60
- const entry = buildStdioServerEntry(DEFAULT_MCP_COMMAND, void 0, void 0);
61
60
  mkdirSync(dirname(absPath), { recursive: true });
62
61
  writeFileSync(absPath, `${JSON.stringify({ ...doc, mcpServers: { ...existing, [name]: entry } }, null, 2)}
63
62
  `);
64
63
  return { path: relPath, added: true };
65
64
  }
65
+ function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
66
+ return addMcpEntryIfAbsent(repoRoot, name, buildStdioServerEntry(DEFAULT_MCP_COMMAND, void 0, void 0));
67
+ }
68
+ var DOCS_MCP_SERVER_NAME = "outerlayer-docs";
69
+ var DOCS_MCP_URL = "https://docs.outerlayer.ai/mcp";
70
+ function addDocsMcpEntryIfAbsent(repoRoot) {
71
+ return addMcpEntryIfAbsent(repoRoot, DOCS_MCP_SERVER_NAME, { type: "http", url: DOCS_MCP_URL });
72
+ }
66
73
  function runMcpInstall(opts = {}) {
67
74
  const cwd = opts.cwd ?? process.cwd();
68
75
  if (!existsSync(cwd)) throw new McpInstallError(`no such directory: ${cwd}`);
@@ -92,4 +99,4 @@ function handleMcpInstallError(err) {
92
99
  process.exitCode = 1;
93
100
  }
94
101
 
95
- export { DEFAULT_MCP_COMMAND, McpInstallError, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
102
+ export { DEFAULT_MCP_COMMAND, DOCS_MCP_SERVER_NAME, McpInstallError, addDocsMcpEntryIfAbsent, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
4
4
  import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
5
- import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-ABIWDUMS.js';
5
+ import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
6
6
  import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-KZ5M4QOB.js';
7
7
  import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-T6OIJQRT.js';
8
8
  import { RUNNER_PROTOCOL } from './chunk-PDTSUOVT.js';
@@ -225,15 +225,17 @@ async function verifyInto(staging, version, deps) {
225
225
  const digest = await fetchTarballDigest(meta.tarball, deps.fetchImpl);
226
226
  if (digest !== expected) return failed(`the tarball for ${version} does not match the registry's integrity digest`);
227
227
  const provenance = await fetchProvenance(version, deps.fetchImpl);
228
- if (provenance === void 0) return failed(`${version} has no provenance attestation`);
229
- if (provenance.repository !== RELEASE_REPOSITORY) {
230
- return failed(`the provenance of ${version} names the repository ${provenance.repository}, not ${RELEASE_REPOSITORY}`);
231
- }
232
- if (provenance.workflowPath !== RELEASE_WORKFLOW_PATH) {
233
- return failed(`the provenance of ${version} names the workflow ${provenance.workflowPath}, not ${RELEASE_WORKFLOW_PATH}`);
234
- }
235
- if (Buffer.from(provenance.subjectSha512, "hex").toString("base64") !== digest) {
236
- return failed(`the provenance of ${version} covers a different package than the tarball`);
228
+ if (provenance.kind === "unreadable") return failed(`the provenance of ${version} could not be read`);
229
+ if (provenance.kind === "found") {
230
+ if (provenance.repository !== RELEASE_REPOSITORY) {
231
+ return failed(`the provenance of ${version} names the repository ${provenance.repository}, not ${RELEASE_REPOSITORY}`);
232
+ }
233
+ if (provenance.workflowPath !== RELEASE_WORKFLOW_PATH) {
234
+ return failed(`the provenance of ${version} names the workflow ${provenance.workflowPath}, not ${RELEASE_WORKFLOW_PATH}`);
235
+ }
236
+ if (Buffer.from(provenance.subjectSha512, "hex").toString("base64") !== digest) {
237
+ return failed(`the provenance of ${version} covers a different package than the tarball`);
238
+ }
237
239
  }
238
240
  mkdirSync(staging, { recursive: true, mode: RUNNER_DIR_MODE });
239
241
  const npm = await npmVersion(deps.runNpm, staging);
@@ -1972,7 +1974,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
1972
1974
  const outcome = await onStartUnderMarker({
1973
1975
  configPath,
1974
1976
  own: ownVersionOf(deps),
1975
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-RBRRI77E.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
1977
+ check: update.check ? () => update.check(configPath) : async () => (await import('./check-NQYQHITZ.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
1976
1978
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
1977
1979
  log
1978
1980
  });
@@ -34,17 +34,17 @@ async function fetchTarballDigest(url, fetchImpl) {
34
34
  }
35
35
  async function fetchProvenance(version, fetchImpl) {
36
36
  const response = await get(`${REGISTRY_URL}/-/npm/v1/attestations/${PACKAGE_PATH}@${encodeURIComponent(version)}`, fetchImpl);
37
- if (response.status === 404) return void 0;
37
+ if (response.status === 404) return { kind: "absent" };
38
38
  if (!response.ok) throw new Error(`the registry answered HTTP ${response.status} for the attestations of ${PACKAGE_NAME}@${version}`);
39
39
  const body = await response.json();
40
40
  const slsa = (body.attestations ?? []).find((a) => a.predicateType === SLSA_PREDICATE);
41
41
  const payload = slsa?.bundle?.dsseEnvelope?.payload;
42
- if (typeof payload !== "string") return void 0;
42
+ if (typeof payload !== "string") return { kind: "unreadable" };
43
43
  const statement = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
44
44
  const workflow = statement.predicate?.buildDefinition?.externalParameters?.workflow;
45
45
  const subjectSha512 = statement.subject?.[0]?.digest?.sha512;
46
- if (typeof workflow?.repository !== "string" || typeof workflow.path !== "string" || typeof subjectSha512 !== "string") return void 0;
47
- return { repository: workflow.repository, workflowPath: workflow.path, subjectSha512 };
46
+ if (typeof workflow?.repository !== "string" || typeof workflow.path !== "string" || typeof subjectSha512 !== "string") return { kind: "unreadable" };
47
+ return { kind: "found", repository: workflow.repository, workflowPath: workflow.path, subjectSha512 };
48
48
  }
49
49
 
50
50
  // src/runner/update/npm.ts
@@ -3820,7 +3820,7 @@ function buildProgram(argv = process.argv) {
3820
3820
  program2.name("outerlayer").description("OuterLayer \u2014 see what your coding agents actually do").enablePositionalOptions().version(resolveVersion()).option(NO_COLOR_FLAG, "disable color (NO_COLOR=1 does the same)").addHelpText("after", SUPPORT_TEXT);
3821
3821
  program2.command("init").description("Connect this repository, install hooks and agent skills, run doctor").option("--user", "install into user settings [default]").option("--project", "install into project settings (./.claude/settings.json)").option("--org", "print a managed-settings.json snippet for MDM/GPO rollout").option("--remove", "uninstall OuterLayer hooks").option("--local", "install the hooks only: no connect step and no network call").option("--factory <org/factory>", "the factory to connect this repository to (see `outerlayer connect`)").option("--gitignore", "also add .outerlayer/ to .gitignore (project scope)").option("--template <name>", "install the starter skills and a policy file (only: default)").option("--no-wrap-hooks", "leave PreToolUse/PostToolUse hooks unwrapped").option("--statusline", "install the status-line segment [default]").option("--no-statusline", "leave the statusLine slot untouched").option("--json", "machine-readable JSON output").addHelpText(
3822
3822
  "after",
3823
- "\nIn a repository, init runs four steps: connect the repository to a\nfactory (`outerlayer connect`), install the hooks, set up the coding agent,\nand run `outerlayer doctor`. It never signs in and asks nothing. With no\nlogin it skips the connect step and says to run `outerlayer login`. With\n--json it prints one document naming the outcome of each step: done,\nskipped or failed. The exit code is 1 when a step failed.\n\nThe agent setup step installs the starter skills and the `outerlayer` skill\ninto .outerlayer/skills/, writes .outerlayer/config.json for Claude Code when\nthere is none, runs `outerlayer context emit` so the skills appear in\n.claude/skills/, and adds the OuterLayer MCP server to .mcp.json. Nothing you\nwrote is changed: an existing config, policy, edited skill, MCP entry or root\nCLAUDE.md and AGENTS.md is left as it is, and a hand-written file the emit\nwould replace is kept and listed. The files are left uncommitted.\nThe step is skipped outside a git repository and in a repository whose\ncontext comes from a control plane, where it arrives at session start.\n\n--local installs only the hooks: no connect step, no agent setup and no\nnetwork call. Add `--template default` to also write the starter skills and\na policy file into .outerlayer/ without compiling them; `outerlayer context\nemit` does that.\n\nIdempotent: settings are backed up before any write, and a second run\nchanges nothing. Wrapping adds one spawn per hook firing; undo it with\n`outerlayer hooks unwrap`. An occupied status-line slot is wrapped, never\nreplaced.\n\nThree of the starter skills are copied once and are yours to edit. The\nothers are rewritten from this CLI on every `context emit`.\n"
3823
+ "\nIn a repository, init runs four steps: connect the repository to a\nfactory (`outerlayer connect`), install the hooks, set up the coding agent,\nand run `outerlayer doctor`. It never signs in and asks nothing. With no\nlogin it skips the connect step and says to run `outerlayer login`. With\n--json it prints one document naming the outcome of each step: done,\nskipped or failed. The exit code is 1 when a step failed.\n\nThe agent setup step installs the starter skills and the `outerlayer` skill\ninto .outerlayer/skills/, writes .outerlayer/config.json for Claude Code when\nthere is none, runs `outerlayer context emit` so the skills appear in\n.claude/skills/, and adds the outerlayer and outerlayer-docs MCP servers to\n.mcp.json. Nothing you wrote is changed: an existing config, policy, edited\nskill, MCP entry or root CLAUDE.md and AGENTS.md is left as it is, and a\nhand-written file the emit would replace is kept and listed. The files are\nleft uncommitted.\nThe step is skipped outside a git repository and in a repository whose\ncontext comes from a control plane, where it arrives at session start.\n\n--local installs only the hooks: no connect step, no agent setup and no\nnetwork call. Add `--template default` to also write the starter skills and\na policy file into .outerlayer/ without compiling them; `outerlayer context\nemit` does that.\n\nIdempotent: settings are backed up before any write, and a second run\nchanges nothing. Wrapping adds one spawn per hook firing; undo it with\n`outerlayer hooks unwrap`. An occupied status-line slot is wrapped, never\nreplaced.\n\nThree of the starter skills are copied once and are yours to edit. The\nothers are rewritten from this CLI on every `context emit`.\n"
3824
3824
  ).action(async (opts) => {
3825
3825
  let starterTemplate;
3826
3826
  if (opts.template !== void 0) {
@@ -3867,7 +3867,7 @@ function buildProgram(argv = process.argv) {
3867
3867
  return { ok, text, detail };
3868
3868
  },
3869
3869
  runAgentSetup: async () => {
3870
- const { runAgentSetup } = await import('./agent-setup-ODTDC3US.js');
3870
+ const { runAgentSetup } = await import('./agent-setup-YEFN74Y4.js');
3871
3871
  return runAgentSetup({ cwd: process.cwd() });
3872
3872
  },
3873
3873
  runDoctorChecks: gatherDoctorChecks
@@ -4349,7 +4349,7 @@ live addition remains on it.
4349
4349
  throw err;
4350
4350
  }
4351
4351
  });
4352
- workCmd.command("list").description("List live work items for this factory").option("--stage <spec|build|review>", "filter by stage").option("--section <attention|waiting|flowing>", "filter by Queue section").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--unclaimed", "only items with no live lease").option("--claimed", "only items with a live lease, held by a host or a local session").option("--startable", "only items with an unused build request and no live lease").option("--needs <amend>", "only items with a thread waiting on an agent").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
4352
+ workCmd.command("list").description("List live work items for this factory").option("--stage <spec|build|review>", "filter by stage").option("--section <attention|waiting|flowing>", "filter by Queue section").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--unclaimed", "only items with no live lease").option("--claimed", "only items with a live lease, held by a host or a local session").option("--startable", "only items a host can start: a build request, no open PR, no live lease").option("--needs <amend>", "only items with a thread waiting on an agent").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
4353
4353
  warnIfApiKeyFlag(opts);
4354
4354
  const { runWorkList, WorkCommandError } = await import('./work-cmd-ZJY3NA2G.js');
4355
4355
  try {
@@ -4452,11 +4452,11 @@ function registerRunnerCommands(program2) {
4452
4452
  const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
4453
4453
  runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
4454
4454
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-X45X7AS4.js');
4455
- const { start, RunnerStartError } = await import('./loop-ZNUQT736.js');
4455
+ const { start, RunnerStartError } = await import('./loop-DBF3UJAD.js');
4456
4456
  const { RunnerAlreadyRunningError } = await import('./pidfile-UZRH774M.js');
4457
4457
  const configPath = opts.config ?? defaultRunnerConfigPath();
4458
4458
  try {
4459
- const { realUpdateDeps } = await import('./real-deps-LS64D3M6.js');
4459
+ const { realUpdateDeps } = await import('./real-deps-KNNBQC75.js');
4460
4460
  await start(configPath, { update: realUpdateDeps(), fetchImpl: fetch });
4461
4461
  } catch (err) {
4462
4462
  if (err instanceof RunnerConfigError || err instanceof RunnerAlreadyRunningError || err instanceof RunnerStartError) {
@@ -4468,7 +4468,7 @@ function registerRunnerCommands(program2) {
4468
4468
  });
4469
4469
  runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
4470
4470
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4471
- const { runRunnerCheck } = await import('./check-RBRRI77E.js');
4471
+ const { runRunnerCheck } = await import('./check-NQYQHITZ.js');
4472
4472
  const configPath = opts.config ?? defaultRunnerConfigPath();
4473
4473
  const result = await runRunnerCheck(configPath);
4474
4474
  if (!result.ok) {
@@ -4563,7 +4563,7 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
4563
4563
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-X45X7AS4.js');
4564
4564
  const { runRunnerInit, RunnerInitError } = await import('./init-OKCDXEOG.js');
4565
4565
  const { detectMachine } = await import('./machine-TBJKZ6TN.js');
4566
- const { chooseVm, runVmInit, VmInitError } = await import('./init-ORDCPTFD.js');
4566
+ const { chooseVm, runVmInit, VmInitError } = await import('./init-MJ2PO2VQ.js');
4567
4567
  const configPath = opts.config ?? defaultRunnerConfigPath();
4568
4568
  try {
4569
4569
  const machine = detectMachine();
@@ -4768,14 +4768,14 @@ Next:
4768
4768
  });
4769
4769
  runnerCmd.command("stop").description("Take no more work; wait for running jobs to finish, then exit").option("--config <path>", "the cloud config file naming the runner to stop").option("--now", "end running jobs immediately, with outcome stopped").action(async (opts) => {
4770
4770
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4771
- const { requestStop } = await import('./loop-ZNUQT736.js');
4771
+ const { requestStop } = await import('./loop-DBF3UJAD.js');
4772
4772
  const configPath = opts.config ?? defaultRunnerConfigPath();
4773
4773
  await requestStop(configPath, Boolean(opts.now));
4774
4774
  });
4775
4775
  runnerCmd.command("status").description("List running jobs; with --recent, finished ones too").option("--config <path>", "the cloud config file naming the runner to inspect").option("--recent", "also list finished jobs, newest first, capped at 20").option("--json", "machine-readable JSON output").action(async (opts) => {
4776
4776
  const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-X45X7AS4.js');
4777
4777
  const { jobsDir, runnerDir } = await import('./paths-OYKMVYJP.js');
4778
- const { listJobFiles, runnerProcessState } = await import('./loop-ZNUQT736.js');
4778
+ const { listJobFiles, runnerProcessState } = await import('./loop-DBF3UJAD.js');
4779
4779
  const { renderStatus } = await import('./status-KPDVZMJ6.js');
4780
4780
  const { readHousekeepingRecord } = await import('./record-C43U4PKS.js');
4781
4781
  const path2 = await import('path');
@@ -4828,7 +4828,7 @@ Next:
4828
4828
  });
4829
4829
  runnerCmd.command("logs").argument("<item>", "the work item's number in the factory").description("Print the newest attempt's log for one item").option("--config <path>", "the cloud config file naming the runner to inspect").option("-f, --follow", "keep printing as the log grows").action(async (itemArg, opts) => {
4830
4830
  const { defaultRunnerConfigPath } = await import('./config-X45X7AS4.js');
4831
- const { listJobFiles } = await import('./loop-ZNUQT736.js');
4831
+ const { listJobFiles } = await import('./loop-DBF3UJAD.js');
4832
4832
  const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-H55NWW4H.js');
4833
4833
  const configPath = opts.config ?? defaultRunnerConfigPath();
4834
4834
  const item = parseTrackerNumber(itemArg);
@@ -5052,7 +5052,7 @@ function registerMcpCommands(program2) {
5052
5052
  "after",
5053
5053
  "\nThe API key is never a flag and never written to .mcp.json as a literal value.\n stdio (default): the client spawns `outerlayer mcp serve`, which reads the key\n from ~/.outerlayer/config.json (or OUTERLAYER_API_KEY) on every connect, so a\n rotated key is picked up without rewriting the entry.\n http: the entry carries the ${OUTERLAYER_API_KEY} placeholder, which the client\n resolves from the environment it was launched with.\n\n--command: use an absolute or ${HOME}-relative path when the CLI is not on PATH.\n--url: with stdio the endpoint resolves from OUTERLAYER_URL / the config file at\nconnect time; for self-host pass your gateway-node origin + /v1/mcp.\nSelf-host deployments also need --app-id: without a key service to resolve the\ncaller from the bearer token, the gateway answers 401 without that header.\n"
5054
5054
  ).action(async (opts) => {
5055
- const { runMcpInstall, handleMcpInstallError, McpInstallError } = await import('./mcp-install-cmd-4AQMSIGY.js');
5055
+ const { runMcpInstall, handleMcpInstallError, McpInstallError } = await import('./mcp-install-cmd-XZARXNYT.js');
5056
5056
  try {
5057
5057
  if (opts.transport !== void 0 && opts.transport !== "stdio" && opts.transport !== "http") {
5058
5058
  throw new McpInstallError(`--transport must be "stdio" or "http", got "${opts.transport}"`);
package/dist/index.js CHANGED
@@ -22,5 +22,5 @@ if (argv[0] === "statusline") {
22
22
  process.exit(0);
23
23
  }
24
24
  (await import('./hook-fast-AQCAQIA6.js')).recordLinkExitFailure(argv);
25
- var { runCli } = await import('./cli-G6TH4YMK.js');
25
+ var { runCli } = await import('./cli-ZCWMJCEK.js');
26
26
  await runCli(process.argv);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { npmSupportsProvenance } from './chunk-ABIWDUMS.js';
3
+ import { npmSupportsProvenance } from './chunk-YETTWTAY.js';
4
4
  import { readConfigObject, RunnerInitError } from './chunk-MC6J453K.js';
5
5
  import './chunk-472KC6JV.js';
6
6
  import './chunk-BREEX2Z7.js';
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { RunnerStartError, listJobFiles, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick } from './chunk-4AVAETSU.js';
3
+ export { RunnerStartError, listJobFiles, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick } from './chunk-ERHJETKP.js';
4
4
  import './chunk-3JVYMD4G.js';
5
5
  import './chunk-I2UOAV7X.js';
6
- import './chunk-ABIWDUMS.js';
6
+ import './chunk-YETTWTAY.js';
7
7
  import './chunk-KZ5M4QOB.js';
8
8
  import './chunk-T6OIJQRT.js';
9
9
  import './chunk-PDTSUOVT.js';
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ export { DEFAULT_MCP_COMMAND, DOCS_MCP_SERVER_NAME, McpInstallError, addDocsMcpEntryIfAbsent, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall } from './chunk-A56PYPDF.js';
4
+ import './chunk-YRYMNBGQ.js';
5
+ import './chunk-EABW6AJQ.js';
6
+ import './chunk-VNVZDWO3.js';
7
+ import './chunk-Z5GEFMRW.js';
8
+
9
+ createRequire(import.meta.url);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { startedByService } from './chunk-3JVYMD4G.js';
4
- import { realRunNode, realRunNpm } from './chunk-ABIWDUMS.js';
4
+ import { realRunNode, realRunNpm } from './chunk-YETTWTAY.js';
5
5
  import './chunk-Z5GEFMRW.js';
6
6
 
7
7
  createRequire(import.meta.url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outerlayer/cli",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "OuterLayer CLI — commands: init, connect, doctor, login, logout, sync, daemon (alias: watch), emit, work, runner, hooks, mcp, import, context. Capture and sync coding-agent sessions, and record proof of factory work.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Magu Studios, Inc.",
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createRequire } from 'node:module';
3
- export { DEFAULT_MCP_COMMAND, McpInstallError, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall } from './chunk-47RS42OZ.js';
4
- import './chunk-YRYMNBGQ.js';
5
- import './chunk-EABW6AJQ.js';
6
- import './chunk-VNVZDWO3.js';
7
- import './chunk-Z5GEFMRW.js';
8
-
9
- createRequire(import.meta.url);