* docs: promote packages/cli/README as the main README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: symlink root README to packages/cli/README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: reframe Why section — remote CI is the gatekeeper, agent-ci is the pre-flight check
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: note Docker Desktop is also supported on Linux
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: skip orphan cleanup when running inside a Docker container
When agent-ci runs nested inside a container (e.g. smoke-bun-setup step 8),
it shares the host's Docker socket. killOrphanedContainers() checks
agent-ci.pid labels using process.kill(pid, 0), but host PIDs don't
exist in the container's PID namespace — so every container looks like
an orphan. This caused the nested agent-ci to force-remove its own
parent container (exit 137).
Both pruneOrphanedDockerResources() and killOrphanedContainers() now
bail out when /.dockerenv exists.
Fixes#228
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: ignore inherited AGENT_CI_DTU_HOST inside containers
When agent-ci runs nested inside a container (e.g. smoke-bun-setup),
the outer container's AGENT_CI_DTU_HOST=host.docker.internal is
inherited. The nested agent-ci used this to tell the inner container
where the DTU is, but the nested DTU is inside the outer container,
not on the host. The inner container got "Connection refused" trying
to reach host.docker.internal:PORT.
Now when /.dockerenv exists, AGENT_CI_DTU_HOST is ignored and the
container's own IP (via hostname -I) is used instead, so sibling
containers can reach the DTU.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move /.dockerenv guard to call site so tests still work
The /.dockerenv check inside killOrphanedContainers() broke the
shutdown integration tests — they run inside a Docker container (the
test runner) and need the function to work. Moved the guard to the
session bootstrap in cli.ts where the nested agent-ci problem occurs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add global concurrency limiter across all workflows
In --all mode, each workflow created its own per-wave limiter, allowing
20+ containers to run simultaneously and exhaust available memory (OOM
kills with exit 137). Now a single global limiter (CPU/2) is created in
the orchestrator and shared by all handleWorkflow calls, including
single-job workflows and cold-cache first jobs.
Closes#225
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: factor Docker VM memory into concurrency limit
CPU-based limit alone (cpuCount/2 = 7) still causes OOM kills. Now
reads MemAvailable from /proc/meminfo inside the Docker VM and caps
at floor(available / 3GB per container). Falls back to docker info
with a 4GB reserve if busybox isn't available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: guard orphan cleanup in the function, not just the call site
The /.dockerenv guard was only in cli.ts, but killOrphanedContainers
is also called directly by the Docker integration tests (via a spawned
tsx subprocess). Inside a container, the test's subprocess would see
the parent container's PID label, misidentify it as an orphan, and
kill the container running the tests.
Put the guard back in both functions AND keep the cli.ts guard.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase per-container memory estimate to 4 GB
3 GB per container wasn't enough — tests.yml (vitest + Docker
integration tests) and smoke-binary.yml (full build) both got killed
at 3 concurrent containers. 4 GB gives 2 concurrent containers on a
12 GB Docker VM, with ~5.4 GB each.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: mock fs.existsSync in shutdown unit tests for /.dockerenv guard
The unit tests mock execSync but not fs. Inside a runner container,
the real fs.existsSync("/.dockerenv") returns true, causing
killOrphanedContainers to bail before reaching the mocked execSync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: skip Docker integration tests for orphan cleanup inside containers
The integration tests spawn a real killOrphanedContainers() subprocess.
Inside a container, the function bails due to /.dockerenv (PID namespace
mismatch), so the tests can't exercise it. Skip them with insideDocker().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add --jobs flag and document concurrency
Adds -j/--jobs <n> to override the auto-detected concurrency limit.
Adds a Concurrency section to the README explaining how the limit is
calculated and how to override it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: catch any missing tool in runner image hint, add Nix recipe and docs
Closes#229
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Revert "feat: catch any missing tool in runner image hint, add Nix recipe and docs"
This reverts commit ca261639e9.
* feat: generic missing-tool detection with Nix/xz recipe
Replace the hardcoded per-tool pattern list with a single generic
"command not found" regex that catches any missing tool. Add detection
for the Nix installer's "you do not have 'xz' installed" message.
Update hint to point to runner-image.md docs instead of inlining a
Dockerfile snippet. Add Nix recipe to runner-image.md and a runner
image section to the README.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: unify agent instructions across repo, README, and website
Remove the .agents/ hook system and Machinen-specific CLAUDE.md instructions.
Public-facing docs (README, website) now show generic commands that work with
any agent harness. CLAUDE.md uses the /validate skill directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: mention /validate skill on website
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Agent Skills spec skill and update docs with `npx skills add`
Ship an agentskills.io-compatible skill at skills/agent-ci/SKILL.md so
users can install with `npx skills add redwoodjs/agent-ci --skill agent-ci`.
Works with Claude Code, Cursor, Codex, and 40+ other agents.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add penberg testimonial, update bebraw quote
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: simplify agent instructions to reference the skill
Instead of repeating raw commands, tell agents to run the `agent-ci` skill
that was installed via `npx skills add`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add AI disclosure to blog posts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: move AI disclosure to top of blog posts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: clarify runner image vs VM image in blog post
Explain that agent-ci uses the ~400 MB official runner binary, not
GitHub's ~30 GB VM image.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: show nav links on mobile across all pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: wrap nav links to second row on mobile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: show Star us button on mobile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: resolve workflow secrets from shell environment variables
Shell env vars now act as a fallback for .env.agent-ci when resolving
${{ secrets.FOO }} references. Also auto-populates secrets.GITHUB_TOKEN
from --github-token.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add loadMachineSecrets env fallback tests, update README
Add 7 tests covering process.env fallback behavior in loadMachineSecrets:
file precedence, env-only resolution, key scoping, and merge behavior.
Add a Secrets section to the README documenting resolution order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make GitHub auth opt-in for remote reusable workflow fetching
Remove implicit credential resolution (gh auth token / GITHUB_TOKEN fallback)
that could silently send user credentials. Auth is now opt-in via
--github-token CLI flag or AGENT_CI_GITHUB_TOKEN env var.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: add changeset for opt-in GitHub auth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add --github-token flag and AGENT_CI_GITHUB_TOKEN to docs
Update CLI reference tables, environment variables section, and
compatibility matrix to reflect opt-in GitHub auth for remote
reusable workflows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make commit status posting opt-in via --github-token
Gate postCommitStatus() on the githubToken parameter. When no token
is provided, print a warning instead of silently using implicit
gh CLI credentials.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add --commit-status flag to opt in to posting GitHub commit statuses
Commit status posting now requires both --commit-status and
--github-token. Without --commit-status, no warning is printed
and no status is posted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add tests for 403 error hint and public repo fetch without auth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Move website from website/ to apps/website/ (update pnpm workspace)
- Remove logo icon from navbar, keep AGENT-CI text
- Configure domain routes for agent-ci.dev in wrangler.jsonc
- Replace tabs with stacked tables in compatibility matrix
- Expand all ⚠️ and ❌ notes with reasons and details
- Update compatibility.md to match website content
- Fix useContext SSR error by removing motion/react, using CSS animations
- Add img-src CSP header for pbs.twimg.com (Twitter profile images)
- Remove npx run --all command from hero, rename button to Quick start
- Remove decorative border elements from hero section
- Update footer "Built by" link to rwsdk.com
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Limit Docker API URL rewrites to loopback hosts, keep alias-based defaults unless an explicit bridge gateway override is configured, and update docs/tests to match behavior.
Add a VHS-based terminal recording that demonstrates the core agent-ci
workflow: pause on failure, fix the bug, retry the failed step.
The demo uses tmux split panes to show fixing code in one pane while
agent-ci is paused in the other. The tape auto-resets state on each
recording for easy re-recording.
No changeset needed — no packages/ code changed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures the commands work even when the package isn't installed as a
local devDependency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "(in Docker)" clarification to SKILL.md
- Explain --all flag matches on triggers like GitHub
- Add --no-matrix tip for collapsing matrix jobs locally
- Use --quiet flag in CLAUDE.md snippet
- Add "CI was green before you started" instruction for agents
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Improve npm and AI agent discoverability by filling in package.json
keywords/description, creating a SKILL.md for node_modules scanning,
and adding a ready-to-paste CLAUDE.md snippet to the README.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename package from 'machinen' to 'agent-ci' across all source, tests, scripts, configs, and docs
- Rename CLI binary from 'machinen' to 'agent-ci'
- Rename .machinen → .agent-ci, .env.machinen → .env.agent-ci, MACHINEN_* → AGENT_CI_*
- Rename --runner flag to --name/-n (--runner still accepted for compat)
- agent-ci-dev script now builds DTU before running CLI
- Extract YAML compatibility tables to cli/compatibility.md
- Expand CLI usage docs with per-command flag tables
- Document DOCKER_HOST support for remote Docker
- Document workflow relevance criteria for --all in README
- Add machinen-dev script alias to root package.json
- Make --pause-on-failure the default, add --exit-on-failure/-x to opt out
- Remove unused dev script, concurrently, and wait-on deps
- Move tagline from root README to cli/README
README.md:
- Recommend OrbStack as the preferred Docker provider on macOS
- Rename dtu/github-actions → dtu-github-actions throughout
- Add 'Headless Mode (This Repository Only)' section with oa run examples
- Add 'Full Services Stack' heading before existing pnpm dev content
.env.example: fix GITHUB_REPO example value to use machinen repo name