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.
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.
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.
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.
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.
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.
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>/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
Individual skills in this repository
- local-ci-dev
.pi/skills/local-ci-dev - local-ci
packages/cli - local-ci
skills/local-ci
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 tokensAlways available to the agent
SKILL.md
784 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Steps
Files
SKILL.mdcore3,163 bytesSKILL.mdcore3,163 bytesSKILL.mdcore3,163 bytesSKILL.mdcore3,163 bytes
No excerpt is shown for this license. Read the source on GitHub.
View the complete source on GitHublocal-ci
When your agent uses it
Run GitHub Actions workflows locally with pause-on-failure for AI-agent-driven CI iteration
What it loads into context
Frontmatter
44 tokensAlways available to the agent
SKILL.md
476 tokensWhen the skill is activated
Reference documents
27,258 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- What local-ci does
- When to use local-ci (not `act`)
- Key commands
- Agent output mode
- Common mistakes
Scripts executed separately
package.jsonshim.shsrc/cli.tssrc/commands/clean.tssrc/commands/retry-abort.tssrc/commands/run-prewarm.test.tssrc/commands/run.tssrc/commit-status.tssrc/config.test.tssrc/config.tssrc/docker/container-config.test.tssrc/docker/container-config.tssrc/docker/docker-socket.test.tssrc/docker/docker-socket.tssrc/docker/image-pull.test.tssrc/docker/image-pull.tssrc/docker/repro-126.test.tssrc/docker/repro-197.test.tssrc/docker/service-containers.test.tssrc/docker/service-containers.tssrc/docker/shutdown.test.tssrc/docker/shutdown.tssrc/hooks/json-loader.tssrc/launcher.test.tssrc/launcher.tssrc/log-prune.test.tssrc/log-prune.tssrc/native-launcher.test.tssrc/native-launcher.tssrc/output/agent-mode.test.tssrc/output/agent-mode.tssrc/output/cleanup.test.tssrc/output/cleanup.tssrc/output/concurrency.test.tssrc/output/concurrency.tssrc/output/debug.tssrc/output/diff-renderer.tssrc/output/logger.test.tssrc/output/logger.tssrc/output/logs-directory.tssrc/output/reporter.test.tssrc/output/reporter.tssrc/output/run-state.test.tssrc/output/run-state.tssrc/output/state-renderer.test.tssrc/output/state-renderer.tssrc/output/tree-renderer.test.tssrc/output/tree-renderer.tssrc/output/working-directory.test.tssrc/output/working-directory.tssrc/run-result-writer.test.tssrc/run-result-writer.tssrc/runner/directory-setup.test.tssrc/runner/directory-setup.tssrc/runner/dirty-sha.test.tssrc/runner/dirty-sha.tssrc/runner/git-shim.test.tssrc/runner/git-shim.tssrc/runner/job-result.test.tssrc/runner/job-result.tssrc/runner/local-job-ssh.test.tssrc/runner/local-job.test.tssrc/runner/local-job.tssrc/runner/macos-vm/host-capability.test.tssrc/runner/macos-vm/host-capability.tssrc/runner/macos-vm/image-mapping.test.tssrc/runner/macos-vm/image-mapping.tssrc/runner/macos-vm/macos-vm-job.tssrc/runner/macos-vm/repro-329.test.tssrc/runner/macos-vm/runner-binary.test.tssrc/runner/macos-vm/runner-binary.tssrc/runner/macos-vm/semaphore.test.tssrc/runner/macos-vm/semaphore.tssrc/runner/macos-vm/tart.test.tssrc/runner/macos-vm/tart.tssrc/runner/metadata.test.tssrc/runner/metadata.tssrc/runner/node-modules-cache.test.tssrc/runner/node-modules-cache.tssrc/runner/result-builder.test.tssrc/runner/result-builder.tssrc/runner/runner-credentials.tssrc/runner/runner-image.test.tssrc/runner/runner-image.tssrc/runner/runs-on-compat.test.tssrc/runner/runs-on-compat.tssrc/runner/step-wrapper.test.tssrc/runner/step-wrapper.tssrc/runner/sync.tssrc/runner/workspace.tssrc/types.tssrc/workflow-vars.test.tssrc/workflow-vars.tssrc/workflow/fixture-plan.tssrc/workflow/job-scheduler.test.tssrc/workflow/job-scheduler.tssrc/workflow/matrix-collapse.test.tssrc/workflow/remote-workflow-fetch.test.tssrc/workflow/remote-workflow-fetch.tssrc/workflow/resource-classifier.test.tssrc/workflow/resource-classifier.tssrc/workflow/reusable-workflow.test.tssrc/workflow/reusable-workflow.tssrc/workflow/workflow-parser.test.tssrc/workflow/workflow-parser.tsvitest.config.ts
Files
CHANGELOG.mddoc52,964 bytesREADME.mddoc31,526 bytesSKILL.mdcore1,957 bytescompatibility.jsonasset31,783 bytescompatibility.mddoc58,217 bytesdocs/docker-socket.mddoc4,828 bytespackage.jsonruns1,480 bytesrunner-image.mddoc6,394 bytesshim.shruns223 bytessrc/cli.tsruns5,127 bytessrc/commands/clean.tsruns455 bytessrc/commands/retry-abort.tsruns4,173 bytessrc/commands/run-prewarm.test.tsruns4,072 bytessrc/commands/run.tsruns76,953 bytessrc/commit-status.tsruns1,642 bytessrc/config.test.tsruns13,611 bytessrc/config.tsruns5,435 bytessrc/docker/container-config.test.tsruns18,466 bytessrc/docker/container-config.tsruns16,487 bytessrc/docker/docker-socket.test.tsruns8,346 bytessrc/docker/docker-socket.tsruns7,819 bytessrc/docker/image-pull.test.tsruns5,382 bytessrc/docker/image-pull.tsruns4,050 bytessrc/docker/repro-126.test.tsruns3,035 bytessrc/docker/repro-197.test.tsruns3,806 bytessrc/docker/service-containers.test.tsruns13,362 bytessrc/docker/service-containers.tsruns8,583 bytessrc/docker/shutdown.test.tsruns15,922 bytessrc/docker/shutdown.tsruns8,181 bytessrc/hooks/json-loader.tsruns689 bytessrc/launcher.test.tsruns8,731 bytessrc/launcher.tsruns14,080 bytessrc/log-prune.test.tsruns8,036 bytessrc/log-prune.tsruns8,015 bytessrc/native-launcher.test.tsruns3,078 bytessrc/native-launcher.tsruns4,689 bytessrc/output/agent-mode.test.tsruns1,117 bytessrc/output/agent-mode.tsruns629 bytessrc/output/cleanup.test.tsruns10,963 bytessrc/output/cleanup.tsruns6,545 bytessrc/output/concurrency.test.tsruns3,264 bytessrc/output/concurrency.tsruns3,402 bytessrc/output/debug.tsruns1,326 bytessrc/output/diff-renderer.tsruns3,261 bytessrc/output/logger.test.tsruns9,372 bytessrc/output/logger.tsruns4,516 bytessrc/output/logs-directory.tsruns436 bytessrc/output/reporter.test.tsruns5,291 bytessrc/output/reporter.tsruns5,323 bytessrc/output/run-state.test.tsruns8,213 bytessrc/output/run-state.tsruns8,501 bytessrc/output/state-renderer.test.tsruns33,538 bytessrc/output/state-renderer.tsruns14,427 bytessrc/output/tree-renderer.test.tsruns3,277 bytessrc/output/tree-renderer.tsruns1,949 bytessrc/output/working-directory.test.tsruns3,765 bytessrc/output/working-directory.tsruns1,734 bytessrc/run-result-writer.test.tsruns9,148 bytessrc/run-result-writer.tsruns5,872 bytessrc/runner/directory-setup.test.tsruns10,098 bytessrc/runner/directory-setup.tsruns5,186 bytessrc/runner/dirty-sha.test.tsruns4,535 bytessrc/runner/dirty-sha.tsruns2,017 bytessrc/runner/git-shim.test.tsruns4,059 bytessrc/runner/git-shim.tsruns3,765 bytessrc/runner/job-result.test.tsruns4,290 bytessrc/runner/job-result.tsruns1,248 bytessrc/runner/local-job-ssh.test.tsruns1,212 bytessrc/runner/local-job.test.tsruns3,518 bytessrc/runner/local-job.tsruns40,395 bytessrc/runner/macos-vm/host-capability.test.tsruns1,531 bytessrc/runner/macos-vm/host-capability.tsruns1,825 bytessrc/runner/macos-vm/image-mapping.test.tsruns1,947 bytessrc/runner/macos-vm/image-mapping.tsruns1,961 bytessrc/runner/macos-vm/macos-vm-job.tsruns12,806 bytessrc/runner/macos-vm/repro-329.test.tsruns3,082 bytessrc/runner/macos-vm/runner-binary.test.tsruns1,635 bytessrc/runner/macos-vm/runner-binary.tsruns3,013 bytessrc/runner/macos-vm/semaphore.test.tsruns1,186 bytessrc/runner/macos-vm/semaphore.tsruns930 bytessrc/runner/macos-vm/tart.test.tsruns3,536 bytessrc/runner/macos-vm/tart.tsruns12,383 bytessrc/runner/metadata.test.tsruns5,566 bytessrc/runner/metadata.tsruns4,270 bytessrc/runner/node-modules-cache.test.tsruns7,685 bytessrc/runner/node-modules-cache.tsruns9,080 bytessrc/runner/result-builder.test.tsruns17,427 bytessrc/runner/result-builder.tsruns12,659 bytessrc/runner/runner-credentials.tsruns3,832 bytessrc/runner/runner-image.test.tsruns9,958 bytessrc/runner/runner-image.tsruns10,152 bytessrc/runner/runs-on-compat.test.tsruns4,303 bytessrc/runner/runs-on-compat.tsruns3,266 bytessrc/runner/step-wrapper.test.tsruns4,024 bytessrc/runner/step-wrapper.tsruns5,987 bytessrc/runner/sync.tsruns2,759 bytessrc/runner/workspace.tsruns3,326 bytessrc/types.tsruns767 bytessrc/workflow-vars.test.tsruns2,439 bytessrc/workflow-vars.tsruns3,095 bytessrc/workflow/fixture-plan.tsruns4,368 bytessrc/workflow/job-scheduler.test.tsruns3,970 bytessrc/workflow/job-scheduler.tsruns1,882 bytessrc/workflow/matrix-collapse.test.tsruns4,889 bytessrc/workflow/remote-workflow-fetch.test.tsruns12,496 bytessrc/workflow/remote-workflow-fetch.tsruns5,735 bytessrc/workflow/resource-classifier.test.tsruns6,196 bytessrc/workflow/resource-classifier.tsruns5,148 bytessrc/workflow/reusable-workflow.test.tsruns19,092 bytessrc/workflow/reusable-workflow.tsruns6,969 bytessrc/workflow/workflow-parser.test.tsruns83,982 bytessrc/workflow/workflow-parser.tsruns58,497 bytestsconfig.jsonasset482 bytesvitest.config.tsruns512 bytes
No excerpt is shown for this license. Read the source on GitHub.
View the complete source on GitHublocal-ci
When your agent uses it
Run GitHub Actions CI locally with Local CI to validate changes before pushing. Use when testing, running checks, or validating code changes.
What it loads into context
Frontmatter
69 tokensAlways available to the agent
SKILL.md
482 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Run
- Retry
- Machine-readable output (`--json`)
Files
SKILL.mdcore1,880 bytesSKILL.mdcore1,880 bytesSKILL.mdcore1,880 bytesSKILL.mdcore1,880 bytes
No excerpt is shown for this license. Read the source on GitHub.
View the complete source on GitHubSkills 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
- #825 on Oct 13
- #841 on Oct 19
- #855 on Oct 20
- #843 on Oct 22
- #854 on Oct 23
- #992 since Oct 25
25 earlier periods
- #766 on Aug 1
- #661 on Aug 8
- #656 on Aug 9
- #678 on Aug 10
- #678 on Aug 12
- #652 on Aug 15
- #685 on Aug 17
- #699 on Aug 18
- #685 on Aug 21
- #698 on Aug 26
- #707 on Aug 27
- #675 on Aug 29
- #735 on Sep 1
- #721 on Sep 2
- #719 on Sep 6
- #753 on Sep 10
- #734 on Sep 20
- #782 on Sep 28
- #810 on Sep 29
- #796 on Sep 30
- #739 on Oct 1
- #758 on Oct 2
- #787 on Oct 6
- #795 on Oct 10
- #820 on Oct 12
Before you install
Network or broad shellAutomated 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:1Analysis incomplete: Referenced executable target unavailable; not analyzed.pi/skills/local-ci-dev/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzed.pi/skills/local-ci-dev/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/local-ci/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/local-ci/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/local-ci/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzed
- No broad tool permissions
- 52 dangerous shell commandsin 14 files: cli/runner-image.md:15 cli/src/docker/shutdown.test.ts:169 cli/src/docker/shutdown.ts:16 and 11 more
- 210 network referencesin 34 files: cli/src/config.test.ts:15 cli/src/docker/container-config.test.ts:14 cli/README.md:5 and 31 more
- 8 obfuscation signalsin 2 files: cli/src/runner/runner-credentials.ts:48 cli/src/docker/container-config.ts:182
- No instruction overrides
- 106 executable scriptsin 106 files: cli/package.json:1 cli/shim.sh:1 cli/src/cli.ts:1 and 103 more
- 23 references to secretsin 10 files: cli/src/config.test.ts:242 cli/src/commands/run.ts:297 cli/src/workflow/workflow-parser.test.ts:741 and 7 more
- No requests to vote in Hot
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
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
packages/cli/src/docker/repro-197.test.ts
packages/cli/src/docker/service-containers.test.ts
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
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
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
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
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
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 | Status | Evidence | Install to |
|---|---|---|---|
| Claude Code | Native | Path .claude/commands/local-ci-dev.md | .claude/skills/<skill-name>/ |
| Codex | Native | Manifest AGENTS.md | .agents/skills/<skill-name>/ |
| Cursor | Compatible | Standard SKILL.md .pi/skills/local-ci-dev/SKILL.md | .cursor/skills/<skill-name>/ |
| Gemini CLI | Compatible | Standard SKILL.md .pi/skills/local-ci-dev/SKILL.md | .gemini/skills/<skill-name>/ |
| GitHub Copilot | Compatible | Standard SKILL.md .pi/skills/local-ci-dev/SKILL.md | .github/skills/<skill-name>/ |
| OpenCode | Compatible | Standard 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.