Not in the top 1,000 by GitHub stars

redwoodjs/local-ci

Run GitHub Actions locally — pause on failure, retry in place, and keep caches on your machine.

History

Review weekly changes to SKILL.md before updating. Dates mark the weeks in which we observed each version; checks apply to the recorded commits.

View weekly changes

.pi/skills/local-ci-dev/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

c8597bb695a4 → c8597bb695a4

Diff text is unavailable under the recorded licenses. Line counts and the GitHub link remain available.

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → c8597bb695a4

No earlier version was observed for comparison.

Compare on GitHub

packages/cli/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

c8597bb695a4 → c8597bb695a4

Diff text is unavailable under the recorded licenses. Line counts and the GitHub link remain available.

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → c8597bb695a4

No earlier version was observed for comparison.

Compare on GitHub

skills/local-ci/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

c8597bb695a4 → c8597bb695a4

Diff text is unavailable under the recorded licenses. Line counts and the GitHub link remain available.

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → c8597bb695a4

No earlier version was observed for comparison.

Compare on GitHub

View on GitHubAdd to my skills

Verified commit c8597bb695a4cab84002f5977dd22ec56156cbab

git clone --filter=blob:none --no-checkout https://github.com/redwoodjs/local-ci.git .hotskills/redwoodjs-local-ci && git -C .hotskills/redwoodjs-local-ci checkout --detach c8597bb695a4cab84002f5977dd22ec56156cbab # Copy each selected skill directory from .hotskills/redwoodjs-local-ci into .claude/skills/<skill-name>/
git clone --filter=blob:none --no-checkout https://github.com/redwoodjs/local-ci.git .hotskills/redwoodjs-local-ci && git -C .hotskills/redwoodjs-local-ci checkout --detach c8597bb695a4cab84002f5977dd22ec56156cbab # Copy each selected skill directory from .hotskills/redwoodjs-local-ci into .agents/skills/<skill-name>/
813GitHub stars
2stars in 7 days
3skills in this repository
0commits in 30 days

Heat

4.2
  • Star growth, last 7 daysNot available
  • Star growth, last 24 hoursNot available
  • Rank movement, last 7 daysNot available
  • Commits, last 30 daysNot available
  • Accounts asking about it through MCP, last 7 daysNot available
  • Hot votes this weekNot available

Heat never changes the order by stars, and sponsorship never touches it. How heat works

Stars over time

Jul 29, 2026Nov 7, 2026813

Individual skills in this repository

How it works

local-ci-dev

When your agent uses it

Run local CI via the in-tree dev build of local-ci (`pnpm local-ci-dev`) to verify changes to this repo before completing work. Runs `pnpm local-ci-dev run --all` in the background, watches the log for step failures, and retries failed runners after fixes. Use before reporting work as complete, or whenever the user asks to validate, run CI, or check that changes pass. Distinct from the published `local-ci` skill, which targets downstream users via `npx run-local-ci`.

What it loads into context

Frontmatter

113 tokens

Always available to the agent

SKILL.md

784 tokens

When the skill is activated

Reference documents

0 tokens

Loaded on request

Token counts are estimates. Scripts run separately; they are not counted as reference context.

The playbook

  1. Steps

Files

  • SKILL.mdcore3,163 bytes
  • SKILL.mdcore3,163 bytes
  • SKILL.mdcore3,163 bytes
  • SKILL.mdcore3,163 bytes

No excerpt is shown for this license. Read the source on GitHub.

View the complete source on GitHub

Skills included

  • local-ci-dev
  • local-ci
  • local-ci

Repository facts

License
No license detected
Created
Feb 9, 2026
Last pushed
Sep 10, 2026
Forks
21
Open issues
11
Project activity
Active

Rank over the last 12 weeks

Now #992 · best #652 · down 258 in 30 days

  1. #825 on Oct 13
  2. #841 on Oct 19
  3. #855 on Oct 20
  4. #843 on Oct 22
  5. #854 on Oct 23
  6. #992 since Oct 25
25 earlier periods
  1. #766 on Aug 1
  2. #661 on Aug 8
  3. #656 on Aug 9
  4. #678 on Aug 10
  5. #678 on Aug 12
  6. #652 on Aug 15
  7. #685 on Aug 17
  8. #699 on Aug 18
  9. #685 on Aug 21
  10. #698 on Aug 26
  11. #707 on Aug 27
  12. #675 on Aug 29
  13. #735 on Sep 1
  14. #721 on Sep 2
  15. #719 on Sep 6
  16. #753 on Sep 10
  17. #734 on Sep 20
  18. #782 on Sep 28
  19. #810 on Sep 29
  20. #796 on Sep 30
  21. #739 on Oct 1
  22. #758 on Oct 2
  23. #787 on Oct 6
  24. #795 on Oct 10
  25. #820 on Oct 12

Before you install

Network or broad shell

Automated signals, not a guarantee

Checked Nov 4, 2026

Not fully analyzed: some files were too long, unreadable or missing. This never lowers the level.

Show 6 notes
  • .pi/skills/local-ci-dev/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .pi/skills/local-ci-dev/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .pi/skills/local-ci-dev/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • skills/local-ci/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • skills/local-ci/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • skills/local-ci/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
Show all 399 signals by file

packages/cli/CHANGELOG.md

  • Access to secretsline 315
    [Credential-related source omitted]
  • Dangerous shell operationline 501
    - e320288: fix(runner): nested agent-ci sibling containers collide on `agent-ci-1` when multiple outer runs execute in parallel. Each nested run has its own filesystem so it always allocated `agent-ci-1`, and the pre-spawn `docker rm -f` th
  • Network accessline 529
    - 12220be: Run `runs-on: macos-*` jobs in a real macOS VM via [tart](https://github.com/cirruslabs/tart) on Apple Silicon hosts.
  • Network accessline 564
    Tracking:   - https://github.com/redwoodjs/agent-ci/issues/254 (this guardrail)
  • Network accessline 565
    - https://github.com/redwoodjs/agent-ci/issues/254 (this guardrail)
  • Network accessline 566
    - https://github.com/redwoodjs/agent-ci/issues/258 (real macOS runner support)
  • Dangerous shell operationline 590
    Also: when a step fails with `tar: ...: Cannot open: Permission denied` (typically from a stale `/opt/hostedtoolcache` bind mount left by a previous run), surface an actionable hint showing the host-side toolcache path and an `rm -rf` comma
  • Access to secretsline 704
    [Credential-related source omitted]

packages/cli/README.md

  • Network accessline 5
    <p align="center">   <img src="https://raw.githubusercontent.com/redwoodjs/local-ci/main/.docs/marketing/demo.gif" alt="Local CI demo — pause on failure, fix, retry" width="700" />
  • Network accessline 6
    <img src="https://raw.githubusercontent.com/redwoodjs/local-ci/main/.docs/marketing/demo.gif" alt="Local CI demo — pause on failure, fix, retry" width="700" />
  • Network accessline 9
    Local CI is a ground-up rewrite of the GitHub Actions orchestration layer that runs entirely on your own machine. It doesn't wrap or shim the runner: it **replaces the cloud API** that the official [GitHub Actions Runner](https://github.com
  • Network accessline 52
    - **Docker** — a running Docker provider:   - **macOS:** [OrbStack](https://orbstack.dev/) (recommended) or Docker Desktop
  • Network accessline 53
    - **macOS:** [OrbStack](https://orbstack.dev/) (recommended) or Docker Desktop
  • Network accessline 54
    - **Linux:** Native Docker Engine or Docker Desktop - **Optional — for `runs-on: macos-*` jobs** (Apple Silicon Macs only):   - [tart](https://github.com/cirruslabs/tart) — `brew install cirruslabs/cli/tart`
  • Network accessline 55
    - **Optional — for `runs-on: macos-*` jobs** (Apple Silicon Macs only):   - [tart](https://github.com/cirruslabs/tart) — `brew install cirruslabs/cli/tart`   - `sshpass` — `brew install hudochenkov/sshpass/sshpass`
  • Network accessline 56
    - [tart](https://github.com/cirruslabs/tart) — `brew install cirruslabs/cli/tart`
  • Access to secretsline 126
    [Credential-related source omitted]
  • Network accessline 209
    local-ci run -w .github/workflows/deploy.yml \   --var DEPLOY_ENV=production \   --var API_URL=https://api.example.com
  • Network accessline 211
    --var API_URL=https://api.example.com
  • Network accessline 217
    {   "DEPLOY_ENV": "production",   "API_URL": "https://api.example.com"
  • Network accessline 218
    "DEPLOY_ENV": "production",   "API_URL": "https://api.example.com" }
  • Network accessline 219
    "API_URL": "https://api.example.com"
  • Dangerous shell operationline 276
    RUN sudo apt-get update \
  • Dangerous shell operationline 277
    && sudo apt-get install -y --no-install-recommends <your-packages> \
  • Dangerous shell operationline 278
    && sudo rm -rf /var/lib/apt/lists/*
  • Network accessline 283
    For the full guide — directory form with `COPY` support, per-job overrides, common recipes (Rust, Node native modules, Go, Ruby, Nix), the `LOCAL_CI_RUNNER_IMAGE` escape hatch, and build caching details — see [runner-image.md](https://githu
  • Network accessline 289
    Jobs with `runs-on: macos-*` run in a real, throwaway macOS VM on Apple Silicon hosts with [tart](https://github.com/cirruslabs/tart) and `sshpass` installed. On any other host (Linux, Intel Mac, or missing tools), macOS jobs are skipped wi
  • Network accessline 291
    The VM uses the official [cirruslabs](https://github.com/cirruslabs/macos-image-templates) images and is destroyed after the job finishes. The runner binary is fetched once and cached on the host.
  • Network accessline 355
    See [compatibility.md](https://github.com/redwoodjs/local-ci/blob/main/packages/cli/compatibility.md) for detailed GitHub Actions workflow syntax support.
  • Network accessline 370
    - Output goes to **stderr** so stdout stays clean for piping. - If `DEBUG` is unset or empty, all debug loggers become **no-ops** (zero overhead). - Pattern matching uses [minimatch](https://github.com/isaacs/minimatch) globs, so `local-ci:
  • Network accessline 372
    - Pattern matching uses [minimatch](https://github.com/isaacs/minimatch) globs, so `local-ci:*` matches all four namespaces.
  • Network accessline 433
    This works with Claude Code, Cursor, Codex, and [40+ other agents](https://agentskills.io). Then add to your agent instructions (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, etc.):

packages/cli/compatibility.json

  • Network accessline 1
    {   "$schema": "./compatibility.schema.json",   "intro": "Local CI aims to run real GitHub Actions workflows locally. The table below shows current support against the [official workflow syntax](https://docs.github.com/en/actions/using-work
  • Network accessline 2
    "$schema": "./compatibility.schema.json",   "intro": "Local CI aims to run real GitHub Actions workflows locally. The table below shows current support against the [official workflow syntax](https://docs.github.com/en/actions/using-workflow
  • Network accessline 3
    "intro": "Local CI aims to run real GitHub Actions workflows locally. The table below shows current support against the [official workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions).",
  • Network accessline 170
    "key": "`jobs.<id>.runs-on`",           "status": "partial",           "notes": "`ubuntu-*` / `linux` (and unspecified `self-hosted` / custom labels) run in a Linux container — the default image is minimal, see [runner-image.md](./runner-im
  • Network accessline 171
    "status": "partial",           "notes": "`ubuntu-*` / `linux` (and unspecified `self-hosted` / custom labels) run in a Linux container — the default image is minimal, see [runner-image.md](./runner-image.md) to add system tools. `macos-*` r
  • Network accessline 172
    "notes": "`ubuntu-*` / `linux` (and unspecified `self-hosted` / custom labels) run in a Linux container — the default image is minimal, see [runner-image.md](./runner-image.md) to add system tools. `macos-*` runs in a real macOS VM on Apple
  • Access to secretsline 271
    [Credential-related source omitted]
  • Access to secretsline 423
    [Credential-related source omitted]

packages/cli/compatibility.md

  • Network accessline 3
    Local CI aims to run real GitHub Actions workflows locally. The table below shows current support against the [official workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions).
  • Network accessline 36
    | `jobs.<id>.needs`                     | ✅     | Jobs are sorted topologically into dependency waves                                                                                                                                           
  • Network accessline 37
    | `jobs.<id>.if`                        | ✅     | `success()`, `failure()`, `always()`, `cancelled()`, `==`/`!=`, `&&`/`\|\|`, `!`, `needs.*.outputs.*`, `needs.*.result`                                                                       
  • Network accessline 38
    | `jobs.<id>.runs-on`                   | ⚠<U+FE0F>     | `ubuntu-*` / `linux` (and unspecified `self-hosted` / custom labels) run in a Linux container — the default image is minimal, see [runner-image.md](./runner-image.md) to add system tools. `
  • Access to secretsline 52
    [Credential-related source omitted]
  • Access to secretsline 89
    [Credential-related source omitted]

packages/cli/docs/docker-socket.md

  • Dangerous shell operationline 43
    sudo ln -sf "$HOME/.colima/docker.sock" /var/run/docker.sock
  • Dangerous shell operationline 50
    `/var/run/docker.sock` should already exist — that's where dockerd creates it. If it's missing, check that the Docker daemon is running (`systemctl status docker`). If it exists but you can't R/W it, add yourself to the `docker` group (`sud

packages/cli/package.json

  • Executable scriptline 1
    Executable file
  • Network accessline 20
    "repository": {     "type": "git",     "url": "https://github.com/redwoodjs/local-ci.git",
  • Network accessline 21
    "type": "git",     "url": "https://github.com/redwoodjs/local-ci.git",     "directory": "packages/cli"
  • Network accessline 22
    "url": "https://github.com/redwoodjs/local-ci.git",

packages/cli/runner-image.md

  • Network accessline 5
    This is very different from GitHub's hosted `ubuntu-latest` runner, which is a ~30GB VM image preloaded with hundreds of tools (see [`actions/runner-images`](https://github.com/actions/runner-images)). That VM is **not published as a contai
  • Dangerous shell operationline 15
    RUN sudo apt-get update \
  • Dangerous shell operationline 16
    && sudo apt-get install -y --no-install-recommends \
  • Dangerous shell operationline 19
    && sudo rm -rf /var/lib/apt/lists/*
  • Dangerous shell operationline 43
    RUN sudo update-ca-certificates \
  • Dangerous shell operationline 44
    && sudo apt-get update && sudo apt-get install -y build-essential
  • Dangerous shell operationline 59
    RUN sudo apt-get update \
  • Dangerous shell operationline 60
    && sudo apt-get install -y --no-install-recommends build-essential pkg-config \
  • Dangerous shell operationline 61
    && sudo rm -rf /var/lib/apt/lists/*
  • Dangerous shell operationline 68
    RUN sudo apt-get update \
  • Dangerous shell operationline 69
    && sudo apt-get install -y --no-install-recommends build-essential python3 \
  • Dangerous shell operationline 70
    && sudo rm -rf /var/lib/apt/lists/*
  • Dangerous shell operationline 77
    RUN sudo apt-get update \
  • Dangerous shell operationline 78
    && sudo apt-get install -y --no-install-recommends build-essential \
  • Dangerous shell operationline 79
    && sudo rm -rf /var/lib/apt/lists/*
  • Dangerous shell operationline 86
    RUN sudo apt-get update \
  • Dangerous shell operationline 87
    && sudo apt-get install -y --no-install-recommends xz-utils \
  • Dangerous shell operationline 88
    && sudo rm -rf /var/lib/apt/lists/*
  • Dangerous shell operationline 95
    RUN sudo apt-get update \
  • Dangerous shell operationline 96
    && sudo apt-get install -y --no-install-recommends build-essential libffi-dev libyaml-dev \
  • Dangerous shell operationline 97
    && sudo rm -rf /var/lib/apt/lists/*

packages/cli/shim.sh

  • Executable scriptline 1
    #!/bin/bash

packages/cli/src/cli.ts

  • Executable scriptline 1
    #!/usr/bin/env node
  • Access to secretsline 91
    [Credential-related source omitted]

packages/cli/src/commands/clean.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/commands/retry-abort.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/commands/run-prewarm.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/commands/run.ts

  • Executable scriptline 1
    Executable file
  • Access to secretsline 297
    [Credential-related source omitted]
  • Access to secretsline 303
    [Credential-related source omitted]
  • Access to secretsline 375
    [Credential-related source omitted]
  • Access to secretsline 376
    [Credential-related source omitted]
  • Network accessline 764
    // Check whether it's already cached — if not, pull with visible progress   // so first-time users understand what's happening instead of seeing a   // frozen spinner. See https://github.com/redwoodjs/local-ci/issues/242
  • Network accessline 766
    // frozen spinner. See https://github.com/redwoodjs/local-ci/issues/242
  • Network accessline 1557
    // silently landing them there and failing at the first OS-specific step,   // we skip them with a visible warning. See:   //   https://github.com/redwoodjs/local-ci/issues/254  (this guardrail)
  • Network accessline 1558
    // we skip them with a visible warning. See:   //   https://github.com/redwoodjs/local-ci/issues/254  (this guardrail)   //   https://github.com/redwoodjs/local-ci/issues/258  (real macOS support)
  • Network accessline 1559
    //   https://github.com/redwoodjs/local-ci/issues/254  (this guardrail)
  • Network accessline 1560
    //   https://github.com/redwoodjs/local-ci/issues/258  (real macOS support)

packages/cli/src/commit-status.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 56
    `-f context=local-ci ` +         `-f description=${JSON.stringify(description)} ` +         `-f target_url=https://local-ci.dev`,
  • Network accessline 57
    `-f description=${JSON.stringify(description)} ` +         `-f target_url=https://local-ci.dev`,       { stdio: "ignore" },
  • Network accessline 58
    `-f target_url=https://local-ci.dev`,

packages/cli/src/config.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 15
    describe("parseRepoSlug", () => {   it.each([     ["https://github.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],
  • Network accessline 16
    it.each([     ["https://github.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],     ["https://github.com/redwoodjs/local-ci", "redwoodjs/local-ci"],
  • Network accessline 17
    ["https://github.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],
  • Network accessline 18
    ["https://github.com/redwoodjs/local-ci", "redwoodjs/local-ci"],
  • Network accessline 19
    ["https://github.com/redwoodjs/local-ci/", "redwoodjs/local-ci"],
  • Network accessline 23
    ["ssh://git@github.com/redwoodjs/local-ci", "redwoodjs/local-ci"],     ["ssh://git@github.com:22/redwoodjs/local-ci.git", "redwoodjs/local-ci"],     ["https://github.example.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],
  • Network accessline 24
    ["ssh://git@github.com:22/redwoodjs/local-ci.git", "redwoodjs/local-ci"],     ["https://github.example.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],     ["git@github.example.com:redwoodjs/local-ci.git", "redwoodjs/local-ci"],
  • Network accessline 25
    ["https://github.example.com/redwoodjs/local-ci.git", "redwoodjs/local-ci"],
  • Network accessline 49
    it("returns origin URL when origin exists", async () => {     execSync("git remote add origin https://github.com/test/repo.git", {
  • Network accessline 50
    execSync("git remote add origin https://github.com/test/repo.git", {
  • Network accessline 52
    stdio: "pipe",     });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/repo.git");
  • Network accessline 53
    });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/repo.git");   });
  • Network accessline 54
    expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/repo.git");
  • Network accessline 57
    it("falls back to first remote when origin does not exist", async () => {     execSync("git remote add upstream https://github.com/test/upstream.git", {
  • Network accessline 58
    execSync("git remote add upstream https://github.com/test/upstream.git", {
  • Network accessline 60
    stdio: "pipe",     });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/upstream.git");
  • Network accessline 61
    });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/upstream.git");   });
  • Network accessline 62
    expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/upstream.git");
  • Network accessline 65
    it("prefers origin over other remotes", async () => {     execSync("git remote add upstream https://github.com/test/upstream.git", {
  • Network accessline 66
    execSync("git remote add upstream https://github.com/test/upstream.git", {
  • Network accessline 68
    stdio: "pipe",     });     execSync("git remote add origin https://github.com/test/origin.git", {
  • Network accessline 69
    });     execSync("git remote add origin https://github.com/test/origin.git", {       cwd: tmpDir,
  • Network accessline 70
    execSync("git remote add origin https://github.com/test/origin.git", {
  • Network accessline 72
    stdio: "pipe",     });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/origin.git");
  • Network accessline 73
    });     expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/origin.git");   });
  • Network accessline 74
    expect(await getFirstRemoteUrl(tmpDir)).toBe("https://github.com/test/origin.git");
  • Network accessline 103
    it("detects owner/repo from remote URL", async () => {     execSync("git remote add origin https://github.com/acme/widgets.git", {
  • Network accessline 104
    execSync("git remote add origin https://github.com/acme/widgets.git", {
  • Network accessline 138
    it("uses non-origin remote when origin is absent", async () => {     execSync("git remote add upstream https://github.com/acme/upstream.git", {
  • Network accessline 139
    execSync("git remote add upstream https://github.com/acme/upstream.git", {
  • Network accessline 162
    it("env var overrides auto-detection", () => {     execSync("git remote add origin https://github.com/detected/repo.git", {
  • Network accessline 163
    execSync("git remote add origin https://github.com/detected/repo.git", {
  • Network accessline 174
    it("auto-detects when env var is not set", async () => {     execSync("git remote add origin https://github.com/detected/repo.git", {
  • Network accessline 175
    execSync("git remote add origin https://github.com/detected/repo.git", {
  • Access to secretsline 242
    [Credential-related source omitted]
  • Access to secretsline 266
    [Credential-related source omitted]
  • Access to secretsline 285
    [Credential-related source omitted]
  • Access to secretsline 407
    [Credential-related source omitted]
  • Access to secretsline 413
    [Credential-related source omitted]

packages/cli/src/config.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 66
    } = {   GITHUB_REPO: process.env.GITHUB_REPO,   GITHUB_API_URL: process.env.GITHUB_API_URL || "http://localhost:8910",
  • Network accessline 67
    GITHUB_REPO: process.env.GITHUB_REPO,   GITHUB_API_URL: process.env.GITHUB_API_URL || "http://localhost:8910", };
  • Network accessline 68
    GITHUB_API_URL: process.env.GITHUB_API_URL || "http://localhost:8910",

packages/cli/src/docker/container-config.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 14
    containerName: "runner-1",       registrationToken: "tok",       repoUrl: "http://dtu:3000/org/repo",
  • Network accessline 15
    registrationToken: "tok",       repoUrl: "http://dtu:3000/org/repo",       dockerApiUrl: "http://dtu:3000",
  • Network accessline 16
    repoUrl: "http://dtu:3000/org/repo",
  • Network accessline 17
    dockerApiUrl: "http://dtu:3000",
  • Network accessline 36
    containerName: "runner-1",       registrationToken: "tok",       repoUrl: "http://dtu:3000/org/repo",
  • Network accessline 37
    registrationToken: "tok",       repoUrl: "http://dtu:3000/org/repo",       dockerApiUrl: "http://dtu:3000",
  • Network accessline 38
    repoUrl: "http://dtu:3000/org/repo",
  • Network accessline 39
    dockerApiUrl: "http://dtu:3000",
  • Network accessline 247
    it("replaces localhost with the DTU host", async () => {     const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://localhost:3000", "172.17.0.2")).toBe(
  • Network accessline 248
    const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://localhost:3000", "172.17.0.2")).toBe(       "http://172.17.0.2:3000",
  • Network accessline 249
    expect(resolveDockerApiUrl("http://localhost:3000", "172.17.0.2")).toBe(
  • Network accessline 250
    "http://172.17.0.2:3000",
  • Network accessline 254
    it("replaces 127.0.0.1 with the DTU host", async () => {     const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://127.0.0.1:3000", "host.docker.internal")).toBe(
  • Network accessline 255
    const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://127.0.0.1:3000", "host.docker.internal")).toBe(       "http://host.docker.internal:3000",
  • Network accessline 256
    expect(resolveDockerApiUrl("http://127.0.0.1:3000", "host.docker.internal")).toBe(
  • Network accessline 257
    "http://host.docker.internal:3000",
  • Network accessline 261
    it("preserves path and query components", async () => {     const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://localhost:8910/api/v1?foo=bar", "10.0.0.8")).toBe(
  • Network accessline 262
    const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("http://localhost:8910/api/v1?foo=bar", "10.0.0.8")).toBe(       "http://10.0.0.8:8910/api/v1?foo=bar",
  • Network accessline 263
    expect(resolveDockerApiUrl("http://localhost:8910/api/v1?foo=bar", "10.0.0.8")).toBe(
  • Network accessline 264
    "http://10.0.0.8:8910/api/v1?foo=bar",
  • Network accessline 268
    it("keeps implicit https default port behavior", async () => {     const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("https://localhost", "host.docker.internal")).toBe(
  • Network accessline 269
    const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(resolveDockerApiUrl("https://localhost", "host.docker.internal")).toBe(       "https://host.docker.internal",
  • Network accessline 270
    expect(resolveDockerApiUrl("https://localhost", "host.docker.internal")).toBe(
  • Network accessline 271
    "https://host.docker.internal",
  • Network accessline 276
    const { resolveDockerApiUrl } = await import("./container-config.ts");     expect(       resolveDockerApiUrl("https://dtu.internal.example.com:8910", "host.docker.internal"),
  • Network accessline 277
    expect(       resolveDockerApiUrl("https://dtu.internal.example.com:8910", "host.docker.internal"),     ).toBe("https://dtu.internal.example.com:8910");
  • Network accessline 278
    resolveDockerApiUrl("https://dtu.internal.example.com:8910", "host.docker.internal"),
  • Network accessline 279
    ).toBe("https://dtu.internal.example.com:8910");

packages/cli/src/docker/container-config.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 175
    const dtuBaseUrl = `http://${dtuHost}:${dtuPort}`;
  • Possible obfuscationline 182
    : `echo '{"agentId":1,"agentName":"${containerName}","poolId":1,"poolName":"Default","serverUrl":"${dtuBaseUrl}","gitHubUrl":"${dtuBaseUrl}/'$GITHUB_REPOSITORY'","workFolder":"_work","ephemeral":true}' > /home/runner/.runner && echo '{"sche
  • Dangerous shell operationline 189
    `MAYBE_SUDO() { if command -v sudo >/dev/null 2>&1; then sudo -n "$@"; else "$@"; fi; }`,

packages/cli/src/docker/docker-socket.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/docker/docker-socket.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 7
    const DEFAULT_SOCKET = "/var/run/docker.sock"; const DOCS_URL =   "https://github.com/redwoodjs/local-ci/blob/main/packages/cli/docs/docker-socket.md";
  • Network accessline 9
    "https://github.com/redwoodjs/local-ci/blob/main/packages/cli/docs/docker-socket.md";

packages/cli/src/docker/image-pull.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 63
    it("uses Docker's canonical registry address for Docker Hub images", () => {     expect(registryServerAddress("ubuntu:latest")).toBe("https://index.docker.io/v1/");
  • Network accessline 64
    expect(registryServerAddress("ubuntu:latest")).toBe("https://index.docker.io/v1/");
  • Network accessline 65
    expect(registryServerAddress("redwoodjs/local-ci:latest")).toBe("https://index.docker.io/v1/");

packages/cli/src/docker/image-pull.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 32
    * the Docker daemon can handle each registry's authentication challenge.  *  * Reproduces: https://github.com/redwoodjs/local-ci/issues/203
  • Network accessline 33
    *  * Reproduces: https://github.com/redwoodjs/local-ci/issues/203  */
  • Network accessline 34
    * Reproduces: https://github.com/redwoodjs/local-ci/issues/203
  • Network accessline 101
    if (usesDockerHub || firstSegment === "docker.io" || firstSegment === "index.docker.io") {     return "https://index.docker.io/v1/";
  • Network accessline 102
    return "https://index.docker.io/v1/";

packages/cli/src/docker/repro-126.test.ts

  • Network accessline 1
    /**  * Reproduction for https://github.com/redwoodjs/local-ci/issues/126
  • Executable scriptline 1
    Executable file
  • Network accessline 2
    * Reproduction for https://github.com/redwoodjs/local-ci/issues/126

packages/cli/src/docker/repro-197.test.ts

  • Network accessline 1
    /**  * Reproduction for https://github.com/redwoodjs/local-ci/issues/197
  • Executable scriptline 1
    Executable file
  • Network accessline 2
    * Reproduction for https://github.com/redwoodjs/local-ci/issues/197

packages/cli/src/docker/service-containers.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 88
    it("uses defaults when interval/timeout/retries are missing", () => {     const options = `--health-cmd="curl -f http://localhost/"`;
  • Network accessline 89
    const options = `--health-cmd="curl -f http://localhost/"`;

packages/cli/src/docker/service-containers.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 184
    `sudo -n python3 -c "
  • Network accessline 193
    finally: s.close();d.close() def handle(c):  s=socket.socket();s.connect(('${containerName}',${fwdPort}));threading.Thread(target=fwd,args=(c,s),daemon=True).start();fwd(s,c)
  • Network accessline 194
    def handle(c):  s=socket.socket();s.connect(('${containerName}',${fwdPort}));threading.Thread(target=fwd,args=(c,s),daemon=True).start();fwd(s,c) srv=socket.socket();srv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1);srv.bind(('127.0.0
  • Network accessline 195
    s=socket.socket();s.connect(('${containerName}',${fwdPort}));threading.Thread(target=fwd,args=(c,s),daemon=True).start();fwd(s,c)
  • Network accessline 196
    srv=socket.socket();srv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1);srv.bind(('127.0.0.1',${fwdPort}));srv.listen(32)

packages/cli/src/docker/shutdown.test.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 169
    cmd.includes("docker rm -f local-ci-runner-1"),
  • Dangerous shell operationline 193
    cmd.includes("docker rm -f"),
  • Dangerous shell operationline 211
    cmd.includes("docker rm -f local-ci-runner-3"),
  • Dangerous shell operationline 230
    cmd.includes("docker rm -f local-ci-2307-j2"),
  • Dangerous shell operationline 258
    cmd.includes("docker rm -f local-ci-500-j1"),
  • Dangerous shell operationline 380
    execSync(`docker rm -f ${containerName}`, { stdio: "pipe" });
  • Dangerous shell operationline 385
    execSync(`docker network rm local-ci-net-${runnerName}`, { stdio: "pipe" });

packages/cli/src/docker/shutdown.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 16
    execSync(`docker rm -f ${runnerName}`, {
  • Dangerous shell operationline 30
    execSync(`docker rm -f ${ids.split("\n").join(" ")}`, {
  • Dangerous shell operationline 41
    execSync(`docker network rm ${prefix}-net-${runnerName}`, {
  • Dangerous shell operationline 79
    execSync(`docker rm -f ${stoppedIds.split("\n").join(" ")}`, {
  • Dangerous shell operationline 98
    // docker network rm fails if containers are still attached — that's fine.
  • Dangerous shell operationline 99
    execSync(`docker network rm ${netId}`, {
  • Dangerous shell operationline 205
    * co-located, so a single rm removes everything for that run.

packages/cli/src/hooks/json-loader.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/launcher.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/launcher.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/log-prune.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/log-prune.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/native-launcher.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/native-launcher.ts

  • Executable scriptline 1
    #!/usr/bin/env node

packages/cli/src/output/agent-mode.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/agent-mode.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/cleanup.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/cleanup.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/concurrency.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/concurrency.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/debug.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/diff-renderer.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/logger.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/logger.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/logs-directory.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/reporter.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/reporter.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/run-state.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/run-state.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/state-renderer.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/state-renderer.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/tree-renderer.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/tree-renderer.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/working-directory.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/output/working-directory.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 15
    * Linux + Docker Desktop: `/tmp` is not in Docker Desktop's default shared-folder  * list (only `$HOME` is shared). Detect this cell and use XDG cache instead.  * See https://github.com/redwoodjs/local-ci/issues/215
  • Network accessline 16
    * list (only `$HOME` is shared). Detect this cell and use XDG cache instead.  * See https://github.com/redwoodjs/local-ci/issues/215  */
  • Network accessline 17
    * See https://github.com/redwoodjs/local-ci/issues/215

packages/cli/src/run-result-writer.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/run-result-writer.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/directory-setup.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/directory-setup.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/dirty-sha.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/dirty-sha.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/git-shim.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 54
    it.each([false, true])(     "creates FETCH_HEAD after fetch (existing commit: %s)",
  • Network accessline 55
    "creates FETCH_HEAD after fetch (existing commit: %s)",

packages/cli/src/runner/git-shim.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 25
    if [[ "$*" == *"config --local --get remote.origin.url"* || "$*" == *"config --get remote.origin.url"* ]]; then   echo "https://github.com/\${GITHUB_REPOSITORY}"
  • Network accessline 26
    echo "https://github.com/\${GITHUB_REPOSITORY}"
  • Dangerous shell operationline 65
    # Intercept clean and rm which can destroy workspace files

packages/cli/src/runner/job-result.test.ts

  • Executable scriptline 1
    Executable file
  • Access to secretsline 79
    [Credential-related source omitted]
  • Access to secretsline 89
    [Credential-related source omitted]

packages/cli/src/runner/job-result.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/local-job-ssh.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/local-job.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/local-job.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 675
    await fetch(`${dtuUrl}/_dtu/start-runner`, {
  • Network accessline 752
    t0 = Date.now();     const seedResponse = await fetch(`${dtuUrl}/_dtu/seed`, {
  • Network accessline 753
    const seedResponse = await fetch(`${dtuUrl}/_dtu/seed`, {
  • Dangerous shell operationline 809
    await execAsync(`chmod -R 777 "${dirs.containerWorkDir}" "${dirs.diagDir}"`);

packages/cli/src/runner/macos-vm/host-capability.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/host-capability.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/image-mapping.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/image-mapping.ts

  • Network accessline 1
    // Map GitHub Actions `runs-on` macOS labels to cirruslabs tart image tags. // Reference: https://github.com/orgs/cirruslabs/packages?repo_name=macos-image-templates
  • Executable scriptline 1
    Executable file
  • Network accessline 2
    // Reference: https://github.com/orgs/cirruslabs/packages?repo_name=macos-image-templates

packages/cli/src/runner/macos-vm/macos-vm-job.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 112
    const dtuCacheDir = path.resolve(getWorkingDirectory(), "cache", "dtu");   const dtu = await startEphemeralDtu(dtuCacheDir, { allowedLogRoot: path.dirname(logDir) });   const dtuHostUrl = dtu.url; // for our own fetch() calls on the host
  • Network accessline 113
    const dtu = await startEphemeralDtu(dtuCacheDir, { allowedLogRoot: path.dirname(logDir) });   const dtuHostUrl = dtu.url; // for our own fetch() calls on the host   const dtuVmUrl = `http://${VM_HOST_IP}:${dtu.port}`; // what the VM runner 
  • Network accessline 114
    const dtuHostUrl = dtu.url; // for our own fetch() calls on the host
  • Network accessline 115
    const dtuVmUrl = `http://${VM_HOST_IP}:${dtu.port}`; // what the VM runner connects to
  • Network accessline 140
    await fetch(`${dtuHostUrl}/_dtu/start-runner`, {
  • Network accessline 166
    const seedResponse = await fetch(`${dtuHostUrl}/_dtu/seed`, {

packages/cli/src/runner/macos-vm/repro-329.test.ts

  • Network accessline 1
    /**  * Reproduction for https://github.com/redwoodjs/local-ci/issues/329
  • Executable scriptline 1
    Executable file
  • Network accessline 2
    * Reproduction for https://github.com/redwoodjs/local-ci/issues/329

packages/cli/src/runner/macos-vm/runner-binary.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 9
    it("builds the GitHub release URL for the given version", () => {     expect(macosRunnerTarballUrl("2.331.0")).toBe(       "https://github.com/actions/runner/releases/download/v2.331.0/actions-runner-osx-arm64-2.331.0.tar.gz",
  • Network accessline 10
    expect(macosRunnerTarballUrl("2.331.0")).toBe(       "https://github.com/actions/runner/releases/download/v2.331.0/actions-runner-osx-arm64-2.331.0.tar.gz",     );
  • Network accessline 11
    "https://github.com/actions/runner/releases/download/v2.331.0/actions-runner-osx-arm64-2.331.0.tar.gz",

packages/cli/src/runner/macos-vm/runner-binary.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 16
    export function macosRunnerTarballUrl(version: string): string {   return `https://github.com/actions/runner/releases/download/v${version}/actions-runner-osx-arm64-${version}.tar.gz`;
  • Network accessline 17
    return `https://github.com/actions/runner/releases/download/v${version}/actions-runner-osx-arm64-${version}.tar.gz`;
  • Network accessline 65
    async function downloadToFile(url: string, dst: string): Promise<void> {   const res = await fetch(url);
  • Network accessline 66
    const res = await fetch(url);

packages/cli/src/runner/macos-vm/semaphore.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/semaphore.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/tart.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/macos-vm/tart.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 307
    echo "${creds.password}" | sudo -S networksetup -setdnsservers Ethernet ${dns.join(" ")}

packages/cli/src/runner/metadata.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/metadata.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/node-modules-cache.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/node-modules-cache.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/result-builder.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/result-builder.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/runner-credentials.ts

  • Executable scriptline 1
    Executable file
  • Possible obfuscationline 48
    d: "CQpCI+sO2GD1N/JsHHI9zEhMlu5Fcc8mU4O2bO6iscOsagFjvEnTesJgydC/Go1HuOBlx+GT9EG2h7+juS0z2o5n8Mvt5BBxlK+tqoDOs8VfQ9CSUl3hqYRPeNdBfnA1w8ovLW0wqfPO08FWTLI0urYsnwjZ5BQrBM+D7zYeA0aCsKdo75bKmaEKnmqrtIEhb7hE45XQa32Yt0RPCPi8QcQAY2HLHbdWdZYDj6k/UuDv
  • Possible obfuscationline 49
    dp: "A0sY1oOz1+3uUMiy+I5xGuHGHOrEQPYspd1xGClBYYsa/Za0UDWS7V0Tn1cbRWfWtNe5vTpxcvwQd6UZBwrtHF6R2zyXFhE++PLPhCe0tH4C5FY9i9jUw9Vo8t44i/s5JUHU2B1mEptXFUA0GcVrLKS8toZSgqELSS2Q/YLRxoE=",
  • Possible obfuscationline 50
    dq: "GrLC9dPJ5n3VYw51ghCH7tybUN9/Oe4T8d9v4dLQ34RQEWHwRd4g3U3zkvuhpXFPloUTMmkxS7MF5pS1evrtzkay4QUTDv+28s0xRuAsw5qNTzuFygg8t93MvpvTVZ2TNApW6C7NFvkL9NbxAnU8+I61/3ow7i6a7oYJJ0hWAxE=",
  • Possible obfuscationline 53
    "8DVz9FSvEdt5W4B9OjgakZHwGfnhn2VLDUxrsR5ilC5tPC/IgA8C2xEfKQM1t+K/N3pAYHBYQ6EPgtW4kquBS/Sy102xbRI7GSCnUbRtTpWYPOaCn6EaxBNzwWzbp5vCbCGvFqlSu4+OBYRVe+iCj+gAnkmT/TKPhHHbTjJHvw==",
  • Possible obfuscationline 55
    "x0eoW2DD7xsW5YiorMN8pNHVvZk4ED1SHlA/bmVnRz5FjEDnQloMn0nBgIUHxoNArksknrp/FOVJv5sJHJTiRZkOp+ZmH7d3W3gmw63IxK2C5pV+6xfav9jR2+Wt/6FMYMgG2utBdF95oif1f2XREFovHoXkWms2l0CPLLHVPO44Hh9EEmBmjOeMJEZkulHJ44z9y8e+GZ2nYqO0ZiRWQcRObZ0vlRaGg6PPOl4ltay0BfN
  • Possible obfuscationline 56
    p: "8fgAdmWy+sTzAN19fYkWMQqeC7t1BCQMo5z5knfVLg8TtwP9ZGqDtoe+r0bGv3UgVsvvDdP/QwRvRVP+5G9l999Y6b4VbSdUbrfPfOgjpPDmRTQzHDve5jh5xBENQoRXYm7PMgHGmjwuFsE/tKtSGTrvt2Z3qcYAo0IOqLLhYmE=",
  • Possible obfuscationline 57
    q: "0tXx4+P7gUWePf92UJLkzhNBClvdnmDbIt52Lui7YCARczbN/asCDJxcMy6Bh3qmIx/bNuOUrfzHkYZHfnRw8AGEK80qmiLLPI6jrUBOGRajmzemGQx0W8FWalEQfGdNIv9R2nsegDRoMq255Zo/qX60xQ6abpp0c6UNhVYSjTE=",

packages/cli/src/runner/runner-image.test.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 250
    it("matches tar `Cannot open: Permission denied` and returns an rm command", () => {
  • Dangerous shell operationline 258
    expect(hint).toContain("sudo rm -rf");

packages/cli/src/runner/runner-image.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 253
    `To fix this, create a .github/local-ci.Dockerfile in your repo that`,     `installs the missing tool. See the runner image docs for recipes:`,     `https://github.com/redwoodjs/local-ci/blob/main/packages/cli/runner-image.md`,
  • Network accessline 254
    `installs the missing tool. See the runner image docs for recipes:`,     `https://github.com/redwoodjs/local-ci/blob/main/packages/cli/runner-image.md`,   ].join("\n");
  • Network accessline 255
    `https://github.com/redwoodjs/local-ci/blob/main/packages/cli/runner-image.md`,
  • Dangerous shell operationline 287
    `    sudo rm -rf ${shellQuote(toolCacheDir)}`,

packages/cli/src/runner/runs-on-compat.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/runs-on-compat.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 6
    * Windows runners, silently landing them in a Linux container produces  * confusing failures — typically "command not found" at the first OS-specific  * step (see https://github.com/redwoodjs/local-ci/issues/254).
  • Network accessline 7
    * confusing failures — typically "command not found" at the first OS-specific  * step (see https://github.com/redwoodjs/local-ci/issues/254).  *
  • Network accessline 8
    * step (see https://github.com/redwoodjs/local-ci/issues/254).
  • Network accessline 10
    * This module classifies a job's `runs-on:` labels so the caller can skip  * unsupported jobs with a clear warning instead. Real macOS runner support  * is tracked separately in https://github.com/redwoodjs/local-ci/issues/258.
  • Network accessline 11
    * unsupported jobs with a clear warning instead. Real macOS runner support  * is tracked separately in https://github.com/redwoodjs/local-ci/issues/258.  */
  • Network accessline 12
    * is tracked separately in https://github.com/redwoodjs/local-ci/issues/258.
  • Network accessline 73
    hostCapability?.reason ?? "This host cannot run macOS VMs.",           hostCapability?.hint,           "Tracking: https://github.com/redwoodjs/local-ci/issues/258",
  • Network accessline 74
    hostCapability?.hint,           "Tracking: https://github.com/redwoodjs/local-ci/issues/258",         ]
  • Network accessline 75
    "Tracking: https://github.com/redwoodjs/local-ci/issues/258",
  • Network accessline 77
    : [           "local-ci currently only runs jobs in a Linux container, so this job",           "cannot execute locally. Tracking: https://github.com/redwoodjs/local-ci/issues/254",
  • Network accessline 78
    "local-ci currently only runs jobs in a Linux container, so this job",           "cannot execute locally. Tracking: https://github.com/redwoodjs/local-ci/issues/254",         ];
  • Network accessline 79
    "cannot execute locally. Tracking: https://github.com/redwoodjs/local-ci/issues/254",

packages/cli/src/runner/step-wrapper.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/step-wrapper.ts

  • Executable scriptline 1
    Executable file
  • Dangerous shell operationline 35
    rm -f "$__SIGNALS/from-step"
  • Dangerous shell operationline 51
    if [ -f "$__SIGNALS/abort" ]; then rm -f "$__SIGNALS/abort" "$__SIGNALS/paused"; exit $__EC; fi
  • Dangerous shell operationline 52
    rm -f "$__SIGNALS/retry" "$__SIGNALS/paused"

packages/cli/src/runner/sync.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/runner/workspace.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 66
    await execAsync(`git config user.name "local-ci"`, opts);   await execAsync(`git config user.email "local-ci@example.com"`, opts);   await execAsync(`git remote add origin http://127.0.0.1/${githubRepo}`, opts);
  • Network accessline 67
    await execAsync(`git config user.email "local-ci@example.com"`, opts);   await execAsync(`git remote add origin http://127.0.0.1/${githubRepo}`, opts);   await execAsync(`git add . && git commit -m "workspace" || true`, opts);
  • Network accessline 68
    await execAsync(`git remote add origin http://127.0.0.1/${githubRepo}`, opts);

packages/cli/src/types.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow-vars.test.ts

  • Executable scriptline 1
    Executable file
  • Network accessline 9
    expect(       parseVarFileContent(         JSON.stringify({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" }),
  • Network accessline 10
    parseVarFileContent(         JSON.stringify({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" }),         "vars.json",
  • Network accessline 11
    JSON.stringify({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" }),
  • Network accessline 12
    "vars.json",       ),     ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });
  • Network accessline 13
    ),     ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });   });
  • Network accessline 14
    ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });
  • Network accessline 19
    parseVarFileContent(         JSON.stringify([           { name: "API_URL", value: "https://api.example.com" },
  • Network accessline 20
    JSON.stringify([           { name: "API_URL", value: "https://api.example.com" },           { name: "DEPLOY_ENV", value: "staging" },
  • Network accessline 21
    { name: "API_URL", value: "https://api.example.com" },
  • Network accessline 24
    "stdin",       ),     ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });
  • Network accessline 25
    ),     ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });   });
  • Network accessline 26
    ).toEqual({ API_URL: "https://api.example.com", DEPLOY_ENV: "staging" });
  • Network accessline 62
    const first = path.join(tmpDir, "first.json");     const second = path.join(tmpDir, "second.json");     fs.writeFileSync(first, JSON.stringify({ API_URL: "https://api.example.com", SHARED: "one" }));
  • Network accessline 63
    const second = path.join(tmpDir, "second.json");     fs.writeFileSync(first, JSON.stringify({ API_URL: "https://api.example.com", SHARED: "one" }));     fs.writeFileSync(second, JSON.stringify({ DEPLOY_ENV: "staging", SHARED: "two" }));
  • Network accessline 64
    fs.writeFileSync(first, JSON.stringify({ API_URL: "https://api.example.com", SHARED: "one" }));
  • Network accessline 67
    expect(loadVarFiles([first, second])).toEqual({       API_URL: "https://api.example.com",
  • Network accessline 68
    API_URL: "https://api.example.com",

packages/cli/src/workflow-vars.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/fixture-plan.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/job-scheduler.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/job-scheduler.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/matrix-collapse.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/remote-workflow-fetch.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/remote-workflow-fetch.ts

  • Executable scriptline 1
    Executable file
  • Access to secretsline 62
    [Credential-related source omitted]
  • Network accessline 143
    try {         const url = `https://api.github.com/repos/${ref.owner}/${ref.repo}/contents/${ref.path}?ref=${ref.ref}`;
  • Network accessline 144
    const url = `https://api.github.com/repos/${ref.owner}/${ref.repo}/contents/${ref.path}?ref=${ref.ref}`;
  • Network accessline 153
    const response = await fetch(url, { headers });

packages/cli/src/workflow/resource-classifier.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/resource-classifier.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/reusable-workflow.test.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/reusable-workflow.ts

  • Executable scriptline 1
    Executable file

packages/cli/src/workflow/workflow-parser.test.ts

  • Executable scriptline 1
    Executable file
  • Access to secretsline 741
    [Credential-related source omitted]
  • Access to secretsline 749
    [Credential-related source omitted]
  • Network accessline 766
    it("handles values containing equals signs", () => {     const dir = writeMachineEnv("URL=https://example.com?foo=bar&baz=qux\n");
  • Network accessline 767
    const dir = writeMachineEnv("URL=https://example.com?foo=bar&baz=qux\n");
  • Network accessline 768
    const secrets = loadMachineSecrets(dir);     expect(secrets["URL"]).toBe("https://example.com?foo=bar&baz=qux");   });
  • Network accessline 769
    expect(secrets["URL"]).toBe("https://example.com?foo=bar&baz=qux");
  • Network accessline 1949
    // Adapted from the GitHub Actions env context docs:   // https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#example-usage-of-the-env-context
  • Network accessline 1950
    // https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#example-usage-of-the-env-context
  • Access to secretsline 2243
    [Credential-related source omitted]
  • Network accessline 2432
    - run: echo hi `);     const vars = { API_URL: "https://api.example.com" };
  • Network accessline 2433
    `);     const vars = { API_URL: "https://api.example.com" };     const steps = await parseWorkflowSteps(
  • Network accessline 2434
    const vars = { API_URL: "https://api.example.com" };
  • Network accessline 2442
    vars,     );     expect((steps[0] as any).Env).toEqual({ API_URL: "https://api.example.com" });
  • Network accessline 2443
    );     expect((steps[0] as any).Env).toEqual({ API_URL: "https://api.example.com" });   });
  • Network accessline 2444
    expect((steps[0] as any).Env).toEqual({ API_URL: "https://api.example.com" });

packages/cli/src/workflow/workflow-parser.ts

  • Executable scriptline 1
    Executable file

packages/cli/vitest.config.ts

  • Executable scriptline 1
    Executable file

How the signals fit together

Facts from a static read of the files at the pinned commit. They describe what the code does, not why.

Some files could not be read; the facts below still hold.

No combined signals at this commit.

Works with

Agent compatibility, from the files in this repository
AgentStatusEvidenceInstall to
Claude CodeNativePath .claude/commands/local-ci-dev.md.claude/skills/<skill-name>/
CodexNativeManifest AGENTS.md.agents/skills/<skill-name>/
CursorCompatibleStandard SKILL.md .pi/skills/local-ci-dev/SKILL.md.cursor/skills/<skill-name>/
Gemini CLICompatibleStandard SKILL.md .pi/skills/local-ci-dev/SKILL.md.gemini/skills/<skill-name>/
GitHub CopilotCompatibleStandard SKILL.md .pi/skills/local-ci-dev/SKILL.md.github/skills/<skill-name>/
OpenCodeCompatibleStandard SKILL.md .pi/skills/local-ci-dev/SKILL.md.opencode/skills/<skill-name>/
  • Native The repository ships a manifest, folder or frontmatter field for this agent.
  • Compatible A standard SKILL.md that this agent can read.
  • Unknown No evidence either way.

Derived automatically from paths, manifests and frontmatter. Not tested on each agent.