@outerlayer/cli 0.34.0-next.20261024174615 → 0.34.0-next.20261024180339

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.
@@ -1 +1 @@
1
- {"id":"2026-10-24T17:47:37.980Z+5ab4e80","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
1
+ {"id":"2026-10-24T18:04:53.169Z+efc8cbd","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { probeCredentials } from './chunk-DFLHVTXI.js';
3
+ import { probeCredentials } from './chunk-43ZOV4OR.js';
4
4
  import './chunk-3JVYMD4G.js';
5
5
  import './chunk-PBIYM2Z6.js';
6
6
  import './chunk-E7R2GIAW.js';
7
- import './chunk-XLJHFZRL.js';
8
7
  import './chunk-DA3PLB5N.js';
9
8
  import './chunk-GH246BGV.js';
9
+ import './chunk-5HLA7KPK.js';
10
+ import './chunk-XLJHFZRL.js';
10
11
  import './chunk-ZVB57WI6.js';
11
12
  import './chunk-57L2YAJA.js';
12
13
  import './chunk-HVRQQOMH.js';
@@ -3,9 +3,10 @@ import { createRequire } from 'node:module';
3
3
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
4
4
  import { reportFailedStart, fitImageBuildMemory } from './chunk-PBIYM2Z6.js';
5
5
  import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-E7R2GIAW.js';
6
- import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, readProvisionOut, workdirProblem, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, startSender, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-XLJHFZRL.js';
7
6
  import { RUNNER_PROTOCOL } from './chunk-DA3PLB5N.js';
8
7
  import { writePendingUpdate } from './chunk-GH246BGV.js';
8
+ import { renderUpdateSteps } from './chunk-5HLA7KPK.js';
9
+ import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, readProvisionOut, workdirProblem, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, startSender, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-XLJHFZRL.js';
9
10
  import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
10
11
  import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-57L2YAJA.js';
11
12
  import { realBlockedProbes, checkBlockedWithSlots, keepsHostBuilder } from './chunk-ZADIXMKT.js';
@@ -15,7 +16,7 @@ import { leaseTimeLeftMs, createContainerRuntime, withTunnelLog, LEASE_SECONDS,
15
16
  import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-F5UL23I2.js';
16
17
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
17
18
  import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, resolveGoverningSource, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-6AQLRSYU.js';
18
- import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-MZBQTVFG.js';
19
+ import { imageTag, writeUpdateStatus, pullInstruction, tagToPull } from './chunk-MZBQTVFG.js';
19
20
  import { isVersion, compareVersions, satisfiesRange } from './chunk-TQMI335S.js';
20
21
  import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-3CKMB2UK.js';
21
22
  import { freeBytes, formatBytes, volumeBytes } from './chunk-ZYKFYNES.js';
@@ -1383,16 +1384,33 @@ function considerNamedImage(state, named) {
1383
1384
  const own = ownVersionOf(state.deps);
1384
1385
  if (named === void 0 || state.imageLogged === named || (compareVersions(own, named) ?? 0) >= 0) return;
1385
1386
  state.imageLogged = named;
1386
- logOf(state).line(`the factory names ${named}, newer than the ${own} this image runs \xB7 ${pullInstruction(imageTag(named))}`);
1387
+ logOf(state).line(`the factory names ${named}, newer than the ${own} this image runs \xB7 ${imageStepFor(state, named)}`);
1387
1388
  }
1388
1389
  function upgradeStepFor(state, floor) {
1389
1390
  const named = state.namedVersion ?? floor;
1390
1391
  const target = named !== void 0 && isVersion(named) ? named : void 0;
1391
- if (state.deps.image !== void 0) return pullInstruction(tagToPull(target));
1392
+ if (state.deps.image !== void 0) return imageStepFor(state, target);
1392
1393
  const npm = `npm install -g @outerlayer/cli@${target ?? "latest"}, then "$(npm prefix -g)/bin/outerlayer" runner install`;
1393
1394
  if (state.deps.update?.underService !== true) return `${npm}, then start the runner again`;
1394
1395
  return builtinKind(state.config.hooks.provision) === "own" ? npm : `${npm} --service`;
1395
1396
  }
1397
+ function imageStepFor(state, version) {
1398
+ const read = state.ownContainer?.read;
1399
+ return read === void 0 ? pullInstruction(tagToPull(version)) : renderUpdateSteps(read, version);
1400
+ }
1401
+ async function readOwnContainerOnce(state) {
1402
+ const reader = state.deps.image?.readContainer;
1403
+ if (reader === void 0) return;
1404
+ const held = state.ownContainer;
1405
+ const atMs = nowOf(state).getTime();
1406
+ const retryAfterMs2 = 5 * 6e4;
1407
+ if (held !== void 0 && (held.read.ok || atMs - held.atMs < retryAfterMs2)) return;
1408
+ try {
1409
+ state.ownContainer = { read: await reader(), atMs };
1410
+ } catch (err) {
1411
+ state.ownContainer = { read: { ok: false, reason: describeCallFailure(err) }, atMs };
1412
+ }
1413
+ }
1396
1414
  function recordImageStatus(state) {
1397
1415
  if (state.deps.image === void 0) return;
1398
1416
  const named = state.imageNamed;
@@ -1813,6 +1831,7 @@ async function housekeepingPass(state) {
1813
1831
  }
1814
1832
  }
1815
1833
  async function runTick(state) {
1834
+ await readOwnContainerOnce(state);
1816
1835
  state.restarting = false;
1817
1836
  state.holdingForUpdate = false;
1818
1837
  if (state.draining === true) return;
@@ -1939,11 +1958,10 @@ async function tryClaimAndStart(state, item, queue) {
1939
1958
  return { kind: "outdated" };
1940
1959
  }
1941
1960
  if (claim.code === "runner_upgrade_required") {
1942
- const tag = tagToPull(state.imageNamed);
1943
1961
  reportRepeating(
1944
1962
  state,
1945
1963
  "the runner protocol",
1946
- state.deps.image === void 0 ? claim.message ?? claim.reason : `${claim.message ?? claim.reason} \xB7 ${pullInstruction(tag)}`
1964
+ state.deps.image === void 0 ? claim.message ?? claim.reason : `${claim.message ?? claim.reason} \xB7 ${imageStepFor(state, state.imageNamed)}`
1947
1965
  );
1948
1966
  state.upgradeRefused = true;
1949
1967
  recordImageStatus(state);
@@ -3132,7 +3150,7 @@ async function startRunner(configPath, deps, startup) {
3132
3150
  check: update.check ? () => update.check(configPath) : async () => {
3133
3151
  const held = heldClaudeCredential();
3134
3152
  const env = held === void 0 ? process.env : { ...process.env, [held.variable]: held.value };
3135
- return (await import('./check-K4I4EBEK.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3153
+ return (await import('./check-HCKDHD2R.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3136
3154
  },
3137
3155
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
3138
3156
  log
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { stripTerminalControls } from './chunk-XLJHFZRL.js';
4
+ import { tagToPull, imageTag, pullInstruction, readUpdateStatus, runnerImageVersion } from './chunk-MZBQTVFG.js';
5
+ import { readFileSync } from 'fs';
6
+
7
+ createRequire(import.meta.url);
8
+ var COMPOSE_PROJECT_LABEL = "com.docker.compose.project";
9
+ var COMPOSE_SERVICE_LABEL = "com.docker.compose.service";
10
+ var COMPOSE_DIR_LABEL = "com.docker.compose.project.working_dir";
11
+ function firstLine(text) {
12
+ return text.trim().split("\n")[0] ?? "";
13
+ }
14
+ function candidateIds(env, readFile) {
15
+ const found = [];
16
+ const hostname = env.HOSTNAME?.trim();
17
+ if (hostname !== void 0 && hostname !== "") found.push(hostname);
18
+ try {
19
+ for (const match of readFile("/proc/self/mountinfo").matchAll(/\/containers\/([0-9a-f]{64})\//g)) {
20
+ if (!found.includes(match[1])) found.push(match[1]);
21
+ }
22
+ } catch {
23
+ }
24
+ return found;
25
+ }
26
+ function bindDestination(bind) {
27
+ const parts = bind.split(":");
28
+ if (parts.length >= 3 && !parts[parts.length - 1].startsWith("/")) parts.pop();
29
+ return parts[parts.length - 1];
30
+ }
31
+ function mountsOf(row) {
32
+ const binds = row.HostConfig?.Binds ?? [];
33
+ const covered = new Set(binds.map(bindDestination));
34
+ const values = [...binds];
35
+ for (const mount of row.Mounts ?? []) {
36
+ if (mount.Destination === void 0 || covered.has(mount.Destination)) continue;
37
+ const source = mount.Type === "volume" ? mount.Name : mount.Type === "bind" ? mount.Source : void 0;
38
+ if (source === void 0 || source === "") continue;
39
+ values.push(`${source}:${mount.Destination}${mount.RW === false ? ":ro" : ""}`);
40
+ }
41
+ return values;
42
+ }
43
+ function restartOf(row) {
44
+ const policy = row.HostConfig?.RestartPolicy;
45
+ if (policy?.Name === void 0 || policy.Name === "" || policy.Name === "no") return void 0;
46
+ return policy.Name === "on-failure" && (policy.MaximumRetryCount ?? 0) > 0 ? `on-failure:${policy.MaximumRetryCount}` : policy.Name;
47
+ }
48
+ function networkOf(row) {
49
+ const mode = row.HostConfig?.NetworkMode;
50
+ return mode === void 0 || mode === "" || mode === "default" || mode === "bridge" ? void 0 : mode;
51
+ }
52
+ function envNamesOf(row, imageEnv) {
53
+ const own = new Set(imageEnv);
54
+ const names = (row.Config?.Env ?? []).filter((entry) => !own.has(entry)).map((entry) => entry.split("=")[0]);
55
+ return [...new Set(names)].sort();
56
+ }
57
+ async function readOwnContainer(deps = {}) {
58
+ const run = deps.run ?? (await import('./docker-DJ73SZRC.js')).spawnRun;
59
+ const ids = candidateIds(deps.env ?? process.env, deps.readFile ?? ((path) => readFileSync(path, "utf8")));
60
+ if (ids.length === 0) return { ok: false, reason: "the runner cannot tell which container it runs in: HOSTNAME is empty and /proc/self/mountinfo names none" };
61
+ let problem = "";
62
+ let row;
63
+ for (const id of ids) {
64
+ try {
65
+ const result = await run("docker", ["inspect", id], { timeoutMs: 2e4 });
66
+ if (result.status !== 0) {
67
+ problem ||= firstLine(result.stderr) || `docker inspect exited with status ${result.status}`;
68
+ continue;
69
+ }
70
+ const parsed = JSON.parse(result.stdout)[0];
71
+ if (parsed?.Id !== void 0 && parsed.Id.startsWith(id)) {
72
+ row = parsed;
73
+ break;
74
+ }
75
+ problem ||= `docker inspect ${id} named another container`;
76
+ } catch (err) {
77
+ problem ||= err instanceof Error ? err.message : String(err);
78
+ }
79
+ }
80
+ if (row === void 0) {
81
+ return { ok: false, reason: `the runner could not read its container with \`docker inspect\` (is the Docker socket mounted?): ${problem}` };
82
+ }
83
+ const name = row.Name?.replace(/^\//, "");
84
+ const image = row.Config?.Image;
85
+ if (name === void 0 || name === "" || image === void 0 || image === "") {
86
+ return { ok: false, reason: "docker inspect gave no name or image for the container" };
87
+ }
88
+ let imageEnv = [];
89
+ if (row.Image !== void 0) {
90
+ try {
91
+ const result = await run("docker", ["image", "inspect", row.Image], { timeoutMs: 2e4 });
92
+ if (result.status === 0) imageEnv = JSON.parse(result.stdout)[0]?.Config?.Env ?? [];
93
+ } catch {
94
+ }
95
+ }
96
+ const labels = row.Config?.Labels ?? {};
97
+ const project = labels[COMPOSE_PROJECT_LABEL];
98
+ return {
99
+ ok: true,
100
+ container: {
101
+ name,
102
+ image,
103
+ mounts: mountsOf(row),
104
+ ...restartOf(row) === void 0 ? {} : { restart: restartOf(row) },
105
+ ...networkOf(row) === void 0 ? {} : { network: networkOf(row) },
106
+ envNames: envNamesOf(row, imageEnv),
107
+ ...project === void 0 || project === "" ? {} : { compose: { project, service: labels[COMPOSE_SERVICE_LABEL], workingDir: labels[COMPOSE_DIR_LABEL] } }
108
+ }
109
+ };
110
+ }
111
+ function shellWord(raw) {
112
+ const value = stripTerminalControls(raw);
113
+ return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, "'\\''")}'`;
114
+ }
115
+ function variablesNote(names) {
116
+ return names.length === 0 ? ["The container sets no variables of its own."] : [`The container sets these variables. Check that your env file sets each one: ${names.map(stripTerminalControls).join(", ")}`];
117
+ }
118
+ function renderUpdateSteps(read, version) {
119
+ const tag = version === void 0 ? tagToPull(void 0) : imageTag(version);
120
+ if (!read.ok) return `${pullInstruction(tag)} \xB7 the runner could not print exact commands: ${stripTerminalControls(read.reason)}`;
121
+ const c = read.container;
122
+ const lines = [];
123
+ if (c.compose !== void 0) {
124
+ const dir = c.compose.workingDir === void 0 ? "" : stripTerminalControls(c.compose.workingDir);
125
+ const where = dir === "" ? "" : ` in ${dir}`;
126
+ lines.push(
127
+ `Update the runner that Docker Compose started (project ${stripTerminalControls(c.compose.project)}). Run these commands${where}:`,
128
+ `1. Set the image of the runner service in your Compose file to ${tag}. Skip this step when it names a tag that moves, such as latest.`,
129
+ "2. docker compose pull",
130
+ "3. docker compose up -d",
131
+ `4. Check that the new runner is up: docker logs ${shellWord(c.name)}`,
132
+ ` Look for no line that says the gateway refuses work from this runner. docker exec ${shellWord(c.name)} outerlayer --version prints ${version ?? "the new version"}.`,
133
+ ...variablesNote(c.envNames)
134
+ );
135
+ return lines.join("\n");
136
+ }
137
+ const name = shellWord(c.name);
138
+ const old = shellWord(`${c.name}-old`);
139
+ const run = [
140
+ `docker run -d --name ${name}`,
141
+ ...c.restart === void 0 ? [] : [`--restart ${shellWord(c.restart)}`],
142
+ ...c.network === void 0 ? [] : [`--network ${shellWord(c.network)}`],
143
+ ...c.mounts.map((mount) => `-v ${shellWord(mount)}`),
144
+ "--env-file <the file you started it with>",
145
+ tag
146
+ ];
147
+ lines.push(
148
+ `Update the runner to ${tag}. The steps keep the old container as ${stripTerminalControls(c.name)}-old until the new one runs.`,
149
+ `1. docker pull ${tag}`,
150
+ `2. docker stop ${name}`,
151
+ ` docker rename ${name} ${old}`,
152
+ `3. ${run.join(" \\\n ")}`,
153
+ `4. Check that the new runner is up: docker logs ${name}`,
154
+ ` Look for no line that says the gateway refuses work from this runner. docker exec ${name} outerlayer --version prints ${version ?? "the new version"}.`,
155
+ "5. Only after that check, remove the old container:",
156
+ ` docker rm ${old}`,
157
+ ...variablesNote(c.envNames)
158
+ );
159
+ return lines.join("\n");
160
+ }
161
+ async function runUpdateSteps(deps) {
162
+ const env = deps.env ?? process.env;
163
+ const named = readUpdateStatus(deps.runnerDirPath)?.named;
164
+ if (runnerImageVersion(env) === void 0) {
165
+ return `npm install -g @outerlayer/cli@${named ?? "latest"}, then "$(npm prefix -g)/bin/outerlayer" runner install, then start the runner again \xB7 this runner is not in the container image, so there is no container to read. A service runner uses \`runner install --service\` and updates itself.`;
166
+ }
167
+ return renderUpdateSteps(await readOwnContainer({ ...deps, env }), named);
168
+ }
169
+
170
+ export { readOwnContainer, renderUpdateSteps, runUpdateSteps };
@@ -5109,7 +5109,7 @@ function registerRunnerCommands(program2) {
5109
5109
  const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
5110
5110
  runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
5111
5111
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-WRHQDGVI.js');
5112
- const { start, RunnerStartError } = await import('./loop-E4YJ6BLL.js');
5112
+ const { start, RunnerStartError } = await import('./loop-X3ANDLQU.js');
5113
5113
  const { RunnerAlreadyRunningError } = await import('./pidfile-5UDLYPMC.js');
5114
5114
  const configPath = opts.config ?? defaultRunnerConfigPath();
5115
5115
  try {
@@ -5128,8 +5128,8 @@ function registerRunnerCommands(program2) {
5128
5128
  "\nReads OUTERLAYER_URL, OUTERLAYER_APP_ID, OUTERLAYER_API_KEY, OUTERLAYER_RUNNER_NAME and one Claude credential\n(CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY) from the environment. OUTERLAYER_AGENT\nis optional and defaults to claude. On a later start it refuses variables that disagree with the config in the volume.\nThe image sets OUTERLAYER_RUNNER_IMAGE; outside the image, use `runner start`.\n"
5129
5129
  ).action(async () => {
5130
5130
  const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-WRHQDGVI.js');
5131
- const { containerStart } = await import('./container-start-V5WVSWAB.js');
5132
- const { start, RunnerStartError } = await import('./loop-E4YJ6BLL.js');
5131
+ const { containerStart } = await import('./container-start-W4VEGRL5.js');
5132
+ const { start, RunnerStartError } = await import('./loop-X3ANDLQU.js');
5133
5133
  const { RunnerAlreadyRunningError } = await import('./pidfile-5UDLYPMC.js');
5134
5134
  try {
5135
5135
  const result = await containerStart({
@@ -5147,9 +5147,20 @@ function registerRunnerCommands(program2) {
5147
5147
  throw err;
5148
5148
  }
5149
5149
  });
5150
+ runnerCmd.command("update-steps").description("Print the commands that update this runner, with the container's own mounts").option("--config <path>", configOption).addHelpText(
5151
+ "after",
5152
+ "\nIn the runner image, run it with `docker exec <container> outerlayer runner update-steps`. It reads the\ncontainer with `docker inspect` and changes nothing. The steps rename the old container and never remove it\nbefore the new one runs. They name the container's variables and never print a value.\n"
5153
+ ).action(async (opts) => {
5154
+ const { defaultRunnerConfigPath } = await import('./config-WRHQDGVI.js');
5155
+ const { runnerDir } = await import('./paths-7HVTDE6J.js');
5156
+ const { runUpdateSteps } = await import('./update-steps-4M2GIB4A.js');
5157
+ const text = await runUpdateSteps({ runnerDirPath: runnerDir(opts.config ?? defaultRunnerConfigPath()) });
5158
+ process.stdout.write(`${text}
5159
+ `);
5160
+ });
5150
5161
  runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
5151
5162
  const { defaultRunnerConfigPath } = await import('./config-WRHQDGVI.js');
5152
- const { runRunnerCheck } = await import('./check-K4I4EBEK.js');
5163
+ const { runRunnerCheck } = await import('./check-HCKDHD2R.js');
5153
5164
  const configPath = opts.config ?? defaultRunnerConfigPath();
5154
5165
  const result = await runRunnerCheck(configPath);
5155
5166
  if (!result.ok) {
@@ -5549,7 +5560,7 @@ Next:
5549
5560
  });
5550
5561
  runnerCmd.command("stop").description("Take no more work; finish running jobs, 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) => {
5551
5562
  const { defaultRunnerConfigPath } = await import('./config-WRHQDGVI.js');
5552
- const { requestStop } = await import('./loop-E4YJ6BLL.js');
5563
+ const { requestStop } = await import('./loop-X3ANDLQU.js');
5553
5564
  const configPath = opts.config ?? defaultRunnerConfigPath();
5554
5565
  const { runnerImageVersion } = await import('./image-tag-ADSLWXBA.js');
5555
5566
  await requestStop(configPath, Boolean(opts.now), void 0, { image: runnerImageVersion() !== void 0 });
@@ -5557,7 +5568,7 @@ Next:
5557
5568
  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) => {
5558
5569
  const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-WRHQDGVI.js');
5559
5570
  const { jobsDir, runnerDir } = await import('./paths-7HVTDE6J.js');
5560
- const { listJobFiles, runnerProcessState } = await import('./loop-E4YJ6BLL.js');
5571
+ const { listJobFiles, runnerProcessState } = await import('./loop-X3ANDLQU.js');
5561
5572
  const { renderStatus } = await import('./status-6ISCZDBX.js');
5562
5573
  const { readHousekeepingRecord } = await import('./record-PPZEXAVA.js');
5563
5574
  const path2 = await import('path');
@@ -5618,7 +5629,7 @@ Next:
5618
5629
  });
5619
5630
  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) => {
5620
5631
  const { defaultRunnerConfigPath } = await import('./config-WRHQDGVI.js');
5621
- const { listJobFiles } = await import('./loop-E4YJ6BLL.js');
5632
+ const { listJobFiles } = await import('./loop-X3ANDLQU.js');
5622
5633
  const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-HI46FO6Z.js');
5623
5634
  const configPath = opts.config ?? defaultRunnerConfigPath();
5624
5635
  const item = parseTrackerNumber(itemArg);
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { reportFailedStart, BUILD_MEMORY_VARIABLE } from './chunk-PBIYM2Z6.js';
4
+ import { readOwnContainer } from './chunk-5HLA7KPK.js';
4
5
  import './chunk-XLJHFZRL.js';
5
6
  import './chunk-ZVB57WI6.js';
6
7
  import './chunk-HVRQQOMH.js';
@@ -245,7 +246,7 @@ Change the variables to match the volume, or use a new volume to make a new runn
245
246
  if (err instanceof RunnerInitError) return refuse(err.message);
246
247
  throw err;
247
248
  }
248
- await deps.start(configPath, { fetchImpl: deps.fetchImpl ?? fetch, image: { version, ...deps.exit === void 0 ? {} : { exit: deps.exit } } });
249
+ await deps.start(configPath, { fetchImpl: deps.fetchImpl ?? fetch, image: { version, readContainer: deps.readContainer ?? readOwnContainer, ...deps.exit === void 0 ? {} : { exit: deps.exit } } });
249
250
  return { ok: true };
250
251
  }
251
252
 
package/dist/index.js CHANGED
@@ -26,5 +26,5 @@ if (argv[0] === "claude") {
26
26
  process.exit(await runClaudeLauncher(argv.slice(1)));
27
27
  }
28
28
  (await import('./hook-fast-WENTLDMA.js')).recordLinkExitFailure(argv);
29
- var { runCli } = await import('./cli-KDAKXVVE.js');
29
+ var { runCli } = await import('./cli-ADIMCYPF.js');
30
30
  await runCli(process.argv);
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, runtimeOf, sampleUsage, start, tick, watchTick } from './chunk-DFLHVTXI.js';
3
+ export { RunnerStartError, leaseTimeLeftFor, listJobFiles, logUnusableHelper, probeBuild, probeCredentials, requestStop, runnerProcessState, runtimeOf, sampleUsage, start, tick, watchTick } from './chunk-43ZOV4OR.js';
4
4
  import './chunk-3JVYMD4G.js';
5
5
  import './chunk-PBIYM2Z6.js';
6
6
  import './chunk-E7R2GIAW.js';
7
- import './chunk-XLJHFZRL.js';
8
7
  import './chunk-DA3PLB5N.js';
9
8
  import './chunk-GH246BGV.js';
9
+ import './chunk-5HLA7KPK.js';
10
+ import './chunk-XLJHFZRL.js';
10
11
  import './chunk-ZVB57WI6.js';
11
12
  import './chunk-57L2YAJA.js';
12
13
  import './chunk-HVRQQOMH.js';
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ export { readOwnContainer, renderUpdateSteps, runUpdateSteps } from './chunk-5HLA7KPK.js';
4
+ import './chunk-XLJHFZRL.js';
5
+ import './chunk-ZVB57WI6.js';
6
+ import './chunk-HVRQQOMH.js';
7
+ import './chunk-6LBSAW6I.js';
8
+ import './chunk-I3LTIAOR.js';
9
+ import './chunk-SMAZA7DM.js';
10
+ import './chunk-HBVHRC3A.js';
11
+ import './chunk-5XZ6BUPH.js';
12
+ import './chunk-ESVW4MJY.js';
13
+ import './chunk-TBT347UY.js';
14
+ import './chunk-TFKROYY2.js';
15
+ import './chunk-2PGI6RDE.js';
16
+ import './chunk-2JB4GD34.js';
17
+ import './chunk-ZVLSYWDF.js';
18
+ import './chunk-F5UL23I2.js';
19
+ import './chunk-JBJTC3UU.js';
20
+ import './chunk-OGFGZQA3.js';
21
+ import './chunk-5THSC6BD.js';
22
+ import './chunk-L26V6ILJ.js';
23
+ import './chunk-6AQLRSYU.js';
24
+ import './chunk-MZBQTVFG.js';
25
+ import './chunk-TQMI335S.js';
26
+ import './chunk-AMEM2ZLL.js';
27
+ import './chunk-3CKMB2UK.js';
28
+ import './chunk-ZYKFYNES.js';
29
+ import './chunk-43I7PXDP.js';
30
+ import './chunk-3Z3MPR55.js';
31
+ import './chunk-ES4ULBAL.js';
32
+ import './chunk-HIGP4WOC.js';
33
+ import './chunk-IP7BIBXJ.js';
34
+ import './chunk-OHJDH5GV.js';
35
+ import './chunk-NVDPSH72.js';
36
+ import './chunk-MECW77XP.js';
37
+ import './chunk-6ZFY2L2T.js';
38
+ import './chunk-TIRHZC2M.js';
39
+ import './chunk-Y5YCX6AL.js';
40
+ import './chunk-G2JWZDFA.js';
41
+ import './chunk-ANPNT6PM.js';
42
+ import './chunk-B44BFR2Q.js';
43
+ import './chunk-UF2FU3CM.js';
44
+ import './chunk-6RKD7YZ6.js';
45
+ import './chunk-PJDQPF5N.js';
46
+ import './chunk-SOI6K5DY.js';
47
+ import './chunk-PA6CK6WQ.js';
48
+ import './chunk-BALIE3BA.js';
49
+ import './chunk-SHIGGHZO.js';
50
+ import './chunk-ZJSNLVCE.js';
51
+ import './chunk-2O5KA67H.js';
52
+ import './chunk-BKO6JEZI.js';
53
+ import './chunk-FGF52V4V.js';
54
+ import './chunk-HCVLP7XA.js';
55
+ import './chunk-BJ3KTMDH.js';
56
+ import './chunk-ZGB4ZJ5E.js';
57
+ import './chunk-5BHIBJDA.js';
58
+ import './chunk-CDDED64E.js';
59
+ import './chunk-RA3O54FC.js';
60
+ import './chunk-T2Q7ISPE.js';
61
+ import './chunk-WZBHBH3J.js';
62
+ import './chunk-CRB3POP4.js';
63
+ import './chunk-URIZRCRY.js';
64
+ import './chunk-YQR6E6OV.js';
65
+ import './chunk-TUSYOL2O.js';
66
+ import './chunk-CQRPR4WZ.js';
67
+ import './chunk-EOTMDIYC.js';
68
+ import './chunk-VNVZDWO3.js';
69
+ import './chunk-HACGUL52.js';
70
+ import './chunk-MESOOLF4.js';
71
+ import './chunk-Z5GEFMRW.js';
72
+
73
+ createRequire(import.meta.url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outerlayer/cli",
3
- "version": "0.34.0-next.20261024174615",
3
+ "version": "0.34.0-next.20261024180339",
4
4
  "description": "OuterLayer CLI — commands: init, claude, connect, doctor, login, logout, sync, daemon (alias: watch), emit, findings, work, spec, runner, hooks, mcp, 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.",