Commit Graph

378 Commits

Author SHA1 Message Date
Peter Steinberger
fe87142d89
fix(daemon): preserve replacement socket ownership
Some checks are pending
CI / build (${{ matrix.os }}) (windows-latest) (push) Waiting to run
CI / build (${{ matrix.os }}) (macos-15) (push) Waiting to run
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Waiting to run
2026-06-25 13:46:49 -07:00
Vincent Koc
7491ed5a85
fix: harden CLI parsing and generated artifacts 2026-06-22 14:03:17 +08:00
Peter Steinberger
c1b58296db
feat: support file-backed call arguments (#213) 2026-06-18 07:54:31 +02:00
Loveacup
6f3f42ca42
fix: skip imported servers with unresolvable env placeholders (#209)
Some checks failed
CI / build (${{ matrix.os }}) (macos-15) (push) Has been cancelled
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
* fix: skip imported servers with unresolvable env placeholders

When importing MCP server configs from external sources (Cursor, Claude),
some entries reference editor-specific variables like ${workspaceFolder}
that are not available as environment variables outside the editor.

Previously, normalizeServerEntry would throw on unresolvable placeholders,
crashing the entire config loading. Now imported servers that fail to
resolve are silently skipped; locally-defined servers still fail fast.

Fixes: Cursor mcp.json with codegraph server using ${workspaceFolder}
prevents mcporter from loading any servers.

* fix(config): fall back from invalid imported duplicates

---------

Co-authored-by: Loveacup <loveacup@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
2026-06-17 17:32:49 +08:00
Krasimir Kralev
53747cac63
fix(oauth): degrade to re-auth on corrupt credential cache instead of crashing (#208)
* fix(oauth): degrade to re-auth on corrupt credential cache instead of crashing

DirectoryPersistence.readTokens/readClientInfo/readState routed a corrupt
(truncated or malformed) cache file's JSON.parse SyntaxError straight up
through CompositePersistence, crashing the MCP connection instead of degrading
to re-auth. Every sibling reader already tolerates this: VaultPersistence
(oauth-vault.ts) catches SyntaxError to rebuild, and the daemon/server-proxy
readers wrap in catch-all. These three were the lone outliers.

Wrap the three JSON readers in a narrow helper that maps only SyntaxError to
undefined; genuine I/O faults still propagate. readJsonFile is left untouched so
the vault keeps distinguishing corrupt-from-missing for its repair path.

Fixes #207.

* fix(oauth): keep corrupt OAuth state failing closed (addresses Codex P2)

Codex review on #208 noted that making readState() corrupt-tolerant skips the
CSRF state check on the authorization callback: oauth.ts only rejects when the
stored expectedState is truthy, so a corrupt state.txt degrading to undefined
would let a mismatched/absent callback state through.

Narrow the tolerance to the credential caches only (readTokens/readClientInfo).
readState() keeps throwing on corrupt input so the OAuth flow fails closed.
Test now asserts state reads reject with SyntaxError while tokens/client degrade.

* test(oauth): preserve callback cleanup for read errors

---------

Co-authored-by: KrasimirKralev <krasi@idrobots.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
2026-06-17 17:32:24 +08:00
Peter Steinberger
870df28717
fix(fs): serialize same-process file locks 2026-06-10 06:44:18 +01:00
Qi Zhang
4813cdfe7a
fix(cli): keep CloudBase authentication alive (#193)
Keep CloudBase device-code polling alive after `AUTH_PENDING` while preserving explicit ephemeral lifecycle overrides.

Co-authored-by: Qi Zhang <sevenzhang51@gmail.com>
2026-06-09 22:07:47 -07:00
Sebastian B Otaegui
3e27b64021
fix(runtime): preserve disableOAuth across headless paths (#198)
Some checks failed
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (macos-15) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
pages / Deploy docs (push) Has been cancelled
* feat(runtime): add `disableOAuth` connect option (cache-friendly OAuth suppression)

Closes #197.

Long-running headless callers (daemons, scheduled jobs, CI workers) need
to suppress the interactive OAuth flow without losing connection caching.
The only existing knob — `maxOAuthAttempts: 0` — couples those two concerns
because `useCache` is gated on `options.maxOAuthAttempts === undefined`.
Daemons that wrap `connect` to force `maxOAuthAttempts: 0` end up spawning
a fresh transport per `callTool`/`listTools` and `runtime.close()` cannot
reap any of them.

Add an additive `disableOAuth: boolean` option that suppresses OAuth at
the transport layer (short-circuits `shouldEstablishOAuth` and
`maybePromoteHttpDefinition`) but preserves caching. The cache entry
metadata gains a `disableOAuth` field so connections established with
the flag don't share a slot with connections that could refresh into an
OAuth flow — switching the flag between calls evicts and re-establishes,
mirroring the existing `allowCachedAuth` mismatch path.

Backward compatibility:

* `maxOAuthAttempts: 0` keeps its legacy escape-the-cache contract
  unchanged. Existing callers see no behavior change.
* `skipCache: true` keeps its behavior unchanged.
* `disableOAuth` defaults to undefined; only opt-in changes behavior.

Also export `ConnectOptions` from `runtime.ts` and add the parameter to
the `Runtime.connect` interface signature — the implementation already
accepted options at runtime but the interface only exposed
`connect(server)`, so callers couldn't pass options through the type
system. (Pre-existing gap surfaced by adding the new test coverage.)

Tests added to `tests/runtime-integration.test.ts`:

* `reuses cached connection when disableOAuth: true is passed` — two
  calls return the same ClientContext, `close()` reaps it.
* `maxOAuthAttempts: 0 still bypasses the cache (existing contract
  preserved)` — regression guard.
* `evicts and re-establishes the cached client when disableOAuth flag
  changes` — the core eviction semantic.

`pnpm test` (709 pass / 3 skip), `pnpm lint`, `pnpm typecheck` all
green.

* fix(runtime): preserve disableOAuth across helper calls

* fix(daemon): forward disableOAuth through keep-alive paths

* feat(cli): expose disableOAuth for headless commands

* fix(runtime): preserve cached slot across connect(disableOAuth) → callTool/listTools

Addresses PR #198 review comment r3366238654.

The documented headless setup is:

    await runtime.connect(server, { disableOAuth: true });
    await runtime.callTool(server, 'foo', { ... });

The first call stored the cache slot with `allowCachedAuth: undefined`,
but `callTool()` internally calls `this.connect(server, {
allowCachedAuth: true, disableOAuth: <effective>: true })` and the
cache-match check treated the two options shapes as structurally
different:

    existing.allowCachedAuth (undefined)
       !== options.allowCachedAuth (true)
       && options.allowCachedAuth !== undefined
    => MISMATCH => evict + reopen transport

Every first callTool / listTools after a pre-connect spawned a fresh
transport, defeating the pooling guarantee that motivated the
disableOAuth option in the first place. Same shape affected `listTools`
(which defaults `allowCachedAuth: options.allowCachedAuth ?? true`).

Fix: normalize at the connect() entrypoint. A `disableOAuth: true`
caller has no path to interactive OAuth, so cached-token application
is the only auth they can ever use — default `allowCachedAuth: true`
when the caller didn't pick a side. Explicit `false` is honored
(header-only / anonymous callers). The normalized value flows through
both the cache lookup and the cache write so subsequent internal
callers compose without eviction.

Two regression tests added to `tests/runtime-integration.test.ts`:

  - `preserves the cached client across connect(disableOAuth:true) →
    callTool() (no implicit eviction)`
  - `preserves the cached client across connect(disableOAuth:true) →
    listTools() (no implicit eviction)`

Both call `runtime.connect(disableOAuth:true)`, then invoke the
internal-cached path (callTool or listTools), then re-call
`runtime.connect(disableOAuth:true)` and assert the resulting
ClientContext is `=== ` the first one. Both tests fail without this
fix (the second connect returns a new ClientContext because the first
was evicted).

`pnpm test` 723 pass / 3 skip / 0 fail. `pnpm lint` + `pnpm
typecheck` clean. No push.

* docs(examples): add headless-pooling-demo for disableOAuth verification

Demonstrates the three patterns under the new `disableOAuth` option
against a local mock MCP server (no real auth). Reproducible artifact
for PR #198 review proof.

Patterns demonstrated:

* Legacy `maxOAuthAttempts: 0` (uncached): 5 connect() calls produce
  5 distinct ClientContexts. Existing contract preserved.
* `disableOAuth: true` on every connect: 5 calls produce 1
  ClientContext. Cache reuse under cache-friendly suppression.
* Documented headless setup — pre-connect(disableOAuth: true) +
  5 callTool() — proves the pre-connected slot survives the implicit
  internal connect path. Directly demonstrates the fix from b0e3e2e.

Run: `pnpm tsx examples/headless-pooling-demo.ts`

Sample output is intentionally redacted to no PII / no secrets: a local
http://127.0.0.1:<random-port>/mcp server with a public `add` tool.

* style(examples): oxfmt headless-pooling-demo (CI fix)

* fix(server-proxy): thread disableOAuth through schema-discovery listTools

Addresses PR #198 review comment r3366307210 (clawsweeper proxy gap).

The Proxy returned by `createServerProxy` calls `ensureMetadata()` on
every tool invocation, which fires `runtime.listTools(server, {
includeSchema: true })` for schema discovery. That call ran BEFORE the
proxy parsed the caller's options bag, so a `proxy.tool({ ... }, {
disableOAuth: true })` invocation on an OAuth server with no cached
schema could still trigger an interactive OAuth flow during metadata
fetch — defeating the no-browser guarantee the option was meant to
provide.

Fix:

* Pre-scan callArgs once for `disableOAuth: true` before invoking
  `ensureMetadata`. The scan is a single linear pass over the
  already-present argument list and short-circuits on the first match.
* Extend `ensureMetadata(toolName, { disableOAuth? })` and forward the
  flag to the underlying `runtime.listTools(serverName, { includeSchema:
  true, disableOAuth: true })` call.
* The schema-fetch path that was vulnerable now inherits the same
  no-OAuth posture as the eventual `runtime.callTool` invocation. End-
  to-end no-browser guarantee is preserved across the proxy interface.

Regression test in `tests/server-proxy.test.ts`:

  > threads disableOAuth through schema discovery so
  > proxy.tool({disableOAuth:true}) cannot trigger OAuth during
  > metadata fetch

Asserts BOTH:
- `runtime.listTools` called with `{ includeSchema: true, disableOAuth:
  true }`
- `runtime.callTool` called with the eventual tool args and
  `disableOAuth: true`

Locks the contract on both halves so a future refactor that re-introduces
the gap on either side will fail loudly.

Full suite: 724 pass / 3 skipped / 0 fail. `pnpm check` (format + lint
+ typecheck) clean.

* refactor(cli): drop --disable-oauth alias; keep only --no-oauth

The PR originally exposed two CLI names for the same intent:
--disable-oauth (mirroring the JS option `disableOAuth: true`) and
--no-oauth (the GNU-style boolean opt-out). Two names for one
behavior is noise — documentation has to mention both, users have to
learn both, and they invite drift.

--no-oauth is the right shape for a per-invocation boolean opt-out:
- Matches the dominant unix convention (git --no-verify, npm --no-save,
  bun --no-cache, curl --no-progress-meter).
- Shorter to type.
- Composes naturally with other flags in scripts.

The JS option name stays `disableOAuth: boolean` — that's the right
shape for a JS option (verb+noun, no Boolean-negation prefix
ambiguity), and the JS and CLI naming conventions are genuinely
different domains.

Removed CLI registrations + help text + internal forwarding for
--disable-oauth across:
- src/cli/call-arguments.ts (FLAG_HANDLERS registration)
- src/cli/call-command.ts (internal listArgs forwarding, 2 sites)
- src/cli/call-help.ts (help text)
- src/cli/list-command.ts (help text)
- src/cli/list-flags.ts (token check)
- src/cli/resource-command.ts (token check + help text)
- docs/cli-reference.md (3 references)

Renamed test cases that exclusively exercised --disable-oauth to
exercise --no-oauth instead, preserving regression coverage:
- tests/call-arguments.test.ts
- tests/cli-list-flags.test.ts
- tests/cli-resource-command.test.ts

The internal cache-key fragment `disable-oauth:` in
src/cli/tool-cache.ts is kept — it mirrors the JS option name (which
stays `disableOAuth`), not the CLI flag.

Tests: 724 passed, 3 skipped, 0 failed.
Lint: 0 warnings, 0 errors.
Typecheck: clean.

* fix(runtime): forward disableOAuth through callOnce

* chore: update dependencies

* fix(server-proxy): preserve schema-owned option fields

* fix(runtime): isolate OAuth cache variants safely

* fix(server-proxy): isolate schema discovery posture

* fix(server-proxy): preserve OAuth posture during discovery

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-08 16:11:23 -07:00
Peter Steinberger
0fb13581fb docs(serve): document per-server HTTP endpoints 2026-06-08 12:16:38 -07:00
zm2231
2c04671b92 feat(serve): expose per-server endpoints at /mcp/<server> with unprefixed tools
Add per-server HTTP routes alongside the aggregate /mcp endpoint. /mcp/<server>
serves a single server's tools under their original (unprefixed) names so the
server can be registered under its own client key, while /mcp keeps the
server__tool namespacing. Unknown servers 404; malformed paths 400.
2026-06-08 12:16:38 -07:00
Peter Steinberger
14ff39a59b fix(cli): fail unknown list targets 2026-06-08 12:05:42 -07:00
Lil Z
68b228943c
fix(daemon): stop direct starts orphaning live daemon
Stop direct and foreground daemon starts from orphaning an already-running daemon by validating live daemon metadata, repairing missing metadata, and replacing stale-definition daemons only after they exit.

Proof:
- ./runner pnpm exec vitest run tests/daemon-host.test.ts tests/daemon.integration.test.ts
- ./runner pnpm check
- ./runner pnpm test
- autoreview --mode branch --base origin/main
- PR CI passed on macOS, Ubuntu, Windows, and Socket checks

Co-authored-by: zm2231 <25645999+zm2231@users.noreply.github.com>
2026-06-08 11:35:22 -07:00
Sebastian B Otaegui
f37a642a80
feat(runtime): re-export RuntimeOptions
Some checks failed
CI / build (${{ matrix.os }}) (macos-15) (push) Has been cancelled
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
Re-export `RuntimeOptions` from the public package entry so consumers can name the `createRuntime` options shape directly.

Proof:
- `pnpm docs:list`
- `pnpm check`
- `pnpm test` (123 files passed, 1 skipped; 706 tests passed, 3 skipped)
- `pnpm build`
- `rg -n "RuntimeOptions" dist/index.d.ts dist/runtime.d.ts` confirmed the built declaration barrel exports the type.
- Autoreview branch vs `origin/main`: clean, no accepted/actionable findings.
- Existing PR CI green: ubuntu-latest, macos-15, windows-latest.

Co-authored-by: Sebastian Otaegui <feniix@gmail.com>
2026-06-06 22:32:42 -07:00
LDMB123
2bf7a5eab2
fix(replay): rewrite response ids during replay (#192)
Some checks failed
CI / build (${{ matrix.os }}) (macos-15) (push) Has been cancelled
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
pages / Deploy docs (push) Has been cancelled
* feat(record): capture MCP call streams to NDJSON and replay deterministically

mcporter record <session> wraps the runtime transport and appends every
JSON-RPC request, response, and notification to a per-session NDJSON file
under ~/.mcporter/recordings/. mcporter replay <session> reconstructs an
in-memory transport from the recording and matches requests by method +
deep-equal params, returning the recorded response without contacting
the live server.

Use cases:
- Reproduce MCP-backed agent bugs offline (no live Linear quota, no
  Vercel API rate limits)
- Build test fixtures from real call sequences
- Share a session for a postmortem without sharing credentials

The format is plain JSON-RPC over NDJSON with a small _meta field
(direction, server, timestamp). No proprietary blob. Env-var passthrough
(MCPORTER_RECORD=<name>, MCPORTER_REPLAY=<name>) lets the existing
runtime constructor wrap any transport when set.

* fix(replay): attach cause to wrapped errors to satisfy preserve-caught-error lint

* fix(replay): rewrite response ids during replay

* fix(replay): harden record replay modes

Clear conflicting record/replay env vars when spawning wrapped commands, force those commands off the daemon fast path, truncate each recording file at session start, and fail replay close when recorded requests remain unused.

* fix(cli): preserve wrapped command flags

Stop global flag extraction at -- so record/replay wrappers do not consume child command flags, and drop the release-owned changelog entry from the PR diff.

* fix(replay): propagate cleanup failures through cli

Ensure replay-mode transport close failures escape normal runtime and CLI cleanup after best-effort shutdown has completed. Add runtime and CLI regressions for partial recordings that leave requests unreplayed.

* fix: harden record replay runtime paths

* test: align replay fixtures with windows home

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 08:52:02 +01:00
Peter Steinberger
56be50f763
fix(daemon): keep stdio list requests warm
Some checks failed
CI / build (${{ matrix.os }}) (macos-15) (push) Has been cancelled
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
2026-05-29 05:18:32 +01:00
Peter Steinberger
f4f209317f
fix: reconcile daemon lifecycle starts 2026-05-28 16:45:31 +01:00
Peter Steinberger
49dc62b9ee
fix: harden OAuth vault recovery (#190)
Some checks failed
CI / build (${{ matrix.os }}) (macos-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (ubuntu-latest) (push) Has been cancelled
CI / build (${{ matrix.os }}) (windows-latest) (push) Has been cancelled
* fix: harden OAuth vault recovery

* style: format OAuth recovery code
2026-05-26 15:47:31 +01:00
Peter Steinberger
67e3f5250f
fix: fall back to legacy config after empty xdg home (#185) 2026-05-21 22:15:13 +01:00
Peter Steinberger
de7c811271
feat: add list health check flags (#183) 2026-05-20 20:55:21 +01:00
Peter Steinberger
a1201d1955
fix: support daemon idle timeout config 2026-05-20 17:34:42 +01:00
Peter Steinberger
31bbaa804f
fix: preserve valid cached OAuth tokens 2026-05-20 17:21:05 +01:00
Peter Steinberger
ccfaa2f4f0
Merge pull request #182 from bradhallett/fix/daemon-allowCachedAuth
fix(daemon): pass allowCachedAuth to runtime for OAuth token reuse
2026-05-20 17:10:33 +01:00
Peter Steinberger
86e19f4413
fix: use cached auth for daemon OAuth calls 2026-05-20 17:09:14 +01:00
Peter Steinberger
524e0a2d2f
fix: make generated cli bundles deterministic 2026-05-20 16:53:37 +01:00
Brad Hallett
1e6ce66d22 fix(daemon): pass allowCachedAuth to runtime for OAuth token reuse
The daemon host never passed allowCachedAuth when calling
runtime.callTool() or runtime.listTools(), and the KeepAliveRuntime
callTool wrapper did not forward it to the daemon client either.

Without allowCachedAuth, createClientContext skips
applyCachedAuthIfAvailable, so cached OAuth tokens are never read
and every daemon-managed OAuth server fails after token expiry.

Changes:
- protocol.ts: add allowCachedAuth to CallToolParams
- host.ts: pass allowCachedAuth in callTool and listTools handlers
- runtime-wrapper.ts: forward allowCachedAuth in callTool daemon path

Fixes openclaw/mcporter#181
Related openclaw/mcporter#179
2026-05-20 08:23:26 -04:00
Peter Steinberger
46cc31cafe
fix: harden generated cli bundles 2026-05-14 19:22:37 +01:00
Peter Steinberger
7f1e9a8ce0
feat: support refreshable bearer stdio auth 2026-05-14 18:29:43 +01:00
Peter Steinberger
3e06e582ef
fix: add HTTP fetch compatibility mode 2026-05-14 17:31:36 +01:00
Peter Steinberger
2171c1f209
Merge pull request #171 from feniix/feat/headless-oauth-no-browser
feat: add headless OAuth browser suppression
2026-05-14 16:48:57 +01:00
Peter Steinberger
33afa744e0
fix: preserve headless auth stdout 2026-05-14 16:47:03 +01:00
Peter Steinberger
23565e2166
fix: harden concurrent config writes 2026-05-14 16:32:37 +01:00
Peter Steinberger
8d962fbd79
Merge remote-tracking branch 'origin/main' into feat/mcporter-serve
# Conflicts:
#	CHANGELOG.md
2026-05-14 13:40:29 +01:00
Peter Steinberger
907ba78d98
fix: keep served tool names readable 2026-05-14 13:39:05 +01:00
Peter Steinberger
eee954e4a1
fix: patch chrome-devtools auto-connect hang 2026-05-14 12:51:16 +01:00
zm2231
89f5053c15 fix: disambiguate bridged tool names 2026-05-13 21:01:25 -04:00
zm2231
bfe727150c fix: cover serve daemon edge cases 2026-05-13 20:32:33 -04:00
zm2231
6879a69f49 feat: add mcporter serve bridge 2026-05-13 20:26:12 -04:00
Sebastian Otaegui
7ddb433479
docs: document headless OAuth auth flow 2026-05-12 23:59:45 -03:00
Sebastian Otaegui
b29854ebf2
feat: add no-browser auth CLI contract 2026-05-12 23:59:41 -03:00
Sebastian Otaegui
033abb4358
feat: add OAuth no-browser session support 2026-05-12 23:59:34 -03:00
Peter Steinberger
f9f60d7cc4
fix(oauth): refresh expired cached access tokens
Some checks failed
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
pages / Deploy docs (push) Has been cancelled
2026-05-11 03:13:09 +01:00
Peter Steinberger
a64e29b4fe
feat: add headless OAuth vault seeding
Some checks are pending
CI / build (macos-latest) (push) Waiting to run
CI / build (ubuntu-latest) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
pages / Deploy docs (push) Waiting to run
2026-05-09 14:55:44 +01:00
Peter Steinberger
ea91086273
fix: resolve config env placeholders 2026-05-09 13:14:09 +01:00
Peter Steinberger
c0e251babe
fix: harden live mcp cli paths 2026-05-09 12:23:33 +01:00
Peter Steinberger
6012708bf3
perf: keep list non-interactive 2026-05-09 12:04:25 +01:00
Peter Steinberger
e6b451aee3
perf: speed up daemon fast-path calls 2026-05-09 11:54:05 +01:00
clawSean
e2c0641c1e
fix: keep mcporter JSON stdout parseable
Move keep-alive daemon retry diagnostics to stderr so mcporter call --output json keeps stdout parseable after daemon recovery. Current main already covers the structuredContent and raw-envelope JSON fallbacks from the same issue; this PR adds explicit regression coverage for MCP isError envelopes and daemon retry logging.\n\nVerified locally with:\n- pnpm exec vitest run tests/cli-output-utils.test.ts tests/keep-alive-runtime.test.ts tests/result-utils.test.ts\n- pnpm check\n- PNPM_CONFIG_LOGLEVEL=error npm_config_loglevel=error pnpm test\n- pnpm build\n- git diff --check\n\nFixes #160.\n\nCo-authored-by: clawSean <260045960+clawSean@users.noreply.github.com>
2026-05-09 04:45:56 -04:00
Peter Steinberger
6f063bf585
perf(daemon): route warm keep-alive calls directly 2026-05-09 08:31:16 +01:00
Peter Steinberger
761c11cb3b
perf(daemon): skip warm status preflight 2026-05-09 08:19:31 +01:00
Peter Steinberger
3269b7c1c3
fix: recognize Windows command paths
Some checks are pending
pages / Deploy docs (push) Waiting to run
CI / build (macos-latest) (push) Waiting to run
CI / build (ubuntu-latest) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
2026-05-08 16:37:28 +01:00