diff --git a/.claude/commands/gx-act.md b/.claude/commands/gx-act.md new file mode 100644 index 0000000..cdca950 --- /dev/null +++ b/.claude/commands/gx-act.md @@ -0,0 +1,68 @@ +# /gx-act + +Run GitHub Actions workflows locally with [nektos/act](https://github.com/nektos/act) before pushing, so CI failures are caught on the laptop and the PR can be squash-merged on the first remote run. + +## Pre-conditions + +- Docker (or Podman) is running. +- `act` is installed: + + ```sh + command -v act || curl -fsSL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -s -- -b "$HOME/.local/bin" + ``` + +## Default flow + +1. Inspect what would run: + + ```sh + act -l + ``` + +2. Execute the push workflows locally: + + ```sh + act push + ``` + + Or a single job / event: + + ```sh + act -j + act pull_request + act workflow_dispatch -W .github/workflows/release.yml + ``` + +3. Only after `act` is green, hand off to the finish flow: + + ```sh + gx branch finish \ + --branch "$(git branch --show-current)" \ + --base main \ + --via-pr \ + --wait-for-merge \ + --cleanup + ``` + +4. Squash-merge the PR on GitHub once the remote run mirrors the local one. + +## When to use vs the remote run + +- `act` is a **fast pre-flight**: catches syntax errors, missing tools, broken matrix configs, obvious test failures. +- It does **not** replace the remote run. GitHub-hosted services, real secrets, and concurrency groups only exist remotely. Treat green `act` as a strong signal, full proof comes from the PR's checks. + +## Secrets and env + +Never commit secrets. Pass them at invocation time: + +```sh +act -s GITHUB_TOKEN="$GITHUB_TOKEN" --env-file .env.act +``` + +Add `.env.act` to `.gitignore` if you create one. + +## Notes + +- Pin a runner image close to GitHub's: `act -P ubuntu-latest=catthehacker/ubuntu:act-latest`. +- `act --reuse` keeps containers between runs for faster iteration. +- Store shared flags in `.actrc` at the repo root so every agent uses the same setup. diff --git a/.claude/skills/gx-act/SKILL.md b/.claude/skills/gx-act/SKILL.md new file mode 100644 index 0000000..40c753f --- /dev/null +++ b/.claude/skills/gx-act/SKILL.md @@ -0,0 +1,82 @@ +--- +name: gx-act +description: "Run GitHub Actions workflows locally with nektos/act before pushing, so CI failures are caught on the laptop and the PR can be squash-merged on the first remote run." +--- + +# gx-act — local GitHub Actions + +Use whenever a change touches code that would trigger CI on GitHub. Run the workflows locally with `act` first; only push the branch when the local run is green, then squash-merge the PR on GitHub. + +## When to invoke + +- Before `gx pr open` / `gx pr sync` / `gx branch finish --via-pr`. +- Before re-pushing after a CI failure. +- When iterating on `.github/workflows/*.yml` itself. + +## Install `act` + +`act` requires Docker (or Podman). Check the binary: + +```sh +command -v act || echo "act not installed" +``` + +Install one way: + +```sh +# Linux/macOS via the upstream installer +curl -fsSL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -s -- -b "$HOME/.local/bin" + +# macOS via Homebrew +brew install act + +# Arch +sudo pacman -S act + +# Or use the GitHub CLI extension +gh extension install https://github.com/nektos/gh-act +``` + +Upstream: https://github.com/nektos/act + +## Quick commands + +```sh +# List jobs the local runner would execute for the push event +act -l + +# Run the default push workflows (what GitHub runs on a normal push) +act push + +# Run a specific event +act pull_request +act workflow_dispatch -W .github/workflows/release.yml + +# Run a single job +act -j test + +# Pin a runner image (medium is the act default; large matches real GH closer) +act -P ubuntu-latest=catthehacker/ubuntu:act-latest + +# Pass secrets / env without committing them +act -s GITHUB_TOKEN="$GITHUB_TOKEN" --env-file .env.act + +# Reuse containers between runs (faster iteration) +act --reuse +``` + +## Workflow (local CI → squash-merge on GitHub) + +1. Implement the change in the agent worktree. +2. `act -l` to confirm which jobs will fire for the event you care about. +3. `act push` (or the specific event/job) until it is green locally. +4. `gx branch finish --branch "" --base main --via-pr --wait-for-merge --cleanup`. + - Or `gx pr open` then `gx pr sync --auto-merge --merge-strategy squash` for explicit PR control. +5. On GitHub: squash-merge once the remote run mirrors the local one. + +## Notes + +- `act` does not reproduce GitHub-hosted services exactly (no real secrets, different runner image, no concurrency groups). Treat a green `act` run as a strong signal, not a proof — the remote run is still authoritative. +- Keep `act` config in `.actrc` at the repo root so every agent uses the same runner image. +- If a workflow uses `GITHUB_TOKEN` for API calls, pass a PAT via `-s GITHUB_TOKEN=...`; do not commit it. +- Add `.actrc`, `.cache/act`, and any `act`-specific event payloads to `.gitignore` if they appear. diff --git a/AGENTS.md b/AGENTS.md index a49d92a..5303ec0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,8 +18,11 @@ If you are a Claude Code session arriving in this repo for the first time: namespaces, set `GUARDEX_AGENT_BRANCH_PREFIXES_ONLY=1` plus an explicit list. 2. **Slash commands** — `/gx-status`, `/gx-doctor`, `/gx-pivot`, - `/gx-pr`, `/gx-finish`, `/gx-setup` are available out of the box. See - `.claude/commands/`. + `/gx-pr`, `/gx-finish`, `/gx-setup`, `/gx-act` are available out of the + box. See `.claude/commands/`. `/gx-act` wraps + [nektos/act](https://github.com/nektos/act) so CI workflows run locally + before the remote PR run, letting you squash-merge on the first green + round-trip. 3. **PR flow** — when you need explicit PR control, use `gx pr open`, `gx pr status`, `gx pr sync`, or `gx pr watch`. For end-of-task commit + push + PR + merge + cleanup, still use the non-negotiable diff --git a/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/.openspec.yaml b/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/.openspec.yaml new file mode 100644 index 0000000..231e3ab --- /dev/null +++ b/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-05-18 diff --git a/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/notes.md b/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/notes.md new file mode 100644 index 0000000..0491a0e --- /dev/null +++ b/openspec/changes/agent-claude-add-nektos-act-skill-2026-05-18-10-00/notes.md @@ -0,0 +1,37 @@ +# agent-claude-add-nektos-act-skill-2026-05-18-10-00 (minimal / T1) + +Branch: `agent/claude/add-nektos-act-skill-2026-05-18-10-00` + +## Change + +Add `gx-act` skill + `/gx-act` slash command for running GitHub Actions +locally with [nektos/act](https://github.com/nektos/act) before pushing, +so PR remote runs land green on the first round-trip and can be +squash-merged immediately. + +Files added: + +- `skills/gx-act/SKILL.md` — top-level skill (Codex auto-loadable). +- `.claude/skills/gx-act/SKILL.md` — Claude Code skill mirror. +- `templates/codex/skills/gx-act/SKILL.md` — codex install template. +- `.claude/commands/gx-act.md` — `/gx-act` slash command source. + +Files modified: + +- `src/cli/commands/claude.js` — `MANAGED_SLASH_COMMANDS` now includes + `gx-act.md` so `gx claude install` propagates `/gx-act` into target + repos. +- `AGENTS.md` (and via symlink `CLAUDE.md`) — quickstart mentions + `/gx-act` and the local-CI-then-squash-merge flow. + +## Verification + +- `node --test test/claude-install.test.js` — 12 pass, 0 fail. +- Full `npm test` shows 23 unrelated pre-existing failures (same on + bare `main` at b8ec4ff); none touch slash-command or skill installs. + +## Cleanup + +- [ ] Run: `gx branch finish --branch agent/claude/add-nektos-act-skill-2026-05-18-10-00 --base main --via-pr --wait-for-merge --cleanup` +- [ ] Record PR URL + `MERGED` state in the completion handoff. +- [ ] Confirm sandbox worktree is gone (`git worktree list`, `git branch -a`). diff --git a/skills/gx-act/SKILL.md b/skills/gx-act/SKILL.md new file mode 100644 index 0000000..40c753f --- /dev/null +++ b/skills/gx-act/SKILL.md @@ -0,0 +1,82 @@ +--- +name: gx-act +description: "Run GitHub Actions workflows locally with nektos/act before pushing, so CI failures are caught on the laptop and the PR can be squash-merged on the first remote run." +--- + +# gx-act — local GitHub Actions + +Use whenever a change touches code that would trigger CI on GitHub. Run the workflows locally with `act` first; only push the branch when the local run is green, then squash-merge the PR on GitHub. + +## When to invoke + +- Before `gx pr open` / `gx pr sync` / `gx branch finish --via-pr`. +- Before re-pushing after a CI failure. +- When iterating on `.github/workflows/*.yml` itself. + +## Install `act` + +`act` requires Docker (or Podman). Check the binary: + +```sh +command -v act || echo "act not installed" +``` + +Install one way: + +```sh +# Linux/macOS via the upstream installer +curl -fsSL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -s -- -b "$HOME/.local/bin" + +# macOS via Homebrew +brew install act + +# Arch +sudo pacman -S act + +# Or use the GitHub CLI extension +gh extension install https://github.com/nektos/gh-act +``` + +Upstream: https://github.com/nektos/act + +## Quick commands + +```sh +# List jobs the local runner would execute for the push event +act -l + +# Run the default push workflows (what GitHub runs on a normal push) +act push + +# Run a specific event +act pull_request +act workflow_dispatch -W .github/workflows/release.yml + +# Run a single job +act -j test + +# Pin a runner image (medium is the act default; large matches real GH closer) +act -P ubuntu-latest=catthehacker/ubuntu:act-latest + +# Pass secrets / env without committing them +act -s GITHUB_TOKEN="$GITHUB_TOKEN" --env-file .env.act + +# Reuse containers between runs (faster iteration) +act --reuse +``` + +## Workflow (local CI → squash-merge on GitHub) + +1. Implement the change in the agent worktree. +2. `act -l` to confirm which jobs will fire for the event you care about. +3. `act push` (or the specific event/job) until it is green locally. +4. `gx branch finish --branch "" --base main --via-pr --wait-for-merge --cleanup`. + - Or `gx pr open` then `gx pr sync --auto-merge --merge-strategy squash` for explicit PR control. +5. On GitHub: squash-merge once the remote run mirrors the local one. + +## Notes + +- `act` does not reproduce GitHub-hosted services exactly (no real secrets, different runner image, no concurrency groups). Treat a green `act` run as a strong signal, not a proof — the remote run is still authoritative. +- Keep `act` config in `.actrc` at the repo root so every agent uses the same runner image. +- If a workflow uses `GITHUB_TOKEN` for API calls, pass a PAT via `-s GITHUB_TOKEN=...`; do not commit it. +- Add `.actrc`, `.cache/act`, and any `act`-specific event payloads to `.gitignore` if they appear. diff --git a/src/cli/commands/claude.js b/src/cli/commands/claude.js index 343feda..2b10c2c 100644 --- a/src/cli/commands/claude.js +++ b/src/cli/commands/claude.js @@ -29,6 +29,7 @@ const MANAGED_HOOK_FILES = [ ]; const MANAGED_SLASH_COMMANDS = [ + 'gx-act.md', 'gx-doctor.md', 'gx-finish.md', 'gx-pivot.md', diff --git a/templates/codex/skills/gx-act/SKILL.md b/templates/codex/skills/gx-act/SKILL.md new file mode 100644 index 0000000..40c753f --- /dev/null +++ b/templates/codex/skills/gx-act/SKILL.md @@ -0,0 +1,82 @@ +--- +name: gx-act +description: "Run GitHub Actions workflows locally with nektos/act before pushing, so CI failures are caught on the laptop and the PR can be squash-merged on the first remote run." +--- + +# gx-act — local GitHub Actions + +Use whenever a change touches code that would trigger CI on GitHub. Run the workflows locally with `act` first; only push the branch when the local run is green, then squash-merge the PR on GitHub. + +## When to invoke + +- Before `gx pr open` / `gx pr sync` / `gx branch finish --via-pr`. +- Before re-pushing after a CI failure. +- When iterating on `.github/workflows/*.yml` itself. + +## Install `act` + +`act` requires Docker (or Podman). Check the binary: + +```sh +command -v act || echo "act not installed" +``` + +Install one way: + +```sh +# Linux/macOS via the upstream installer +curl -fsSL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -s -- -b "$HOME/.local/bin" + +# macOS via Homebrew +brew install act + +# Arch +sudo pacman -S act + +# Or use the GitHub CLI extension +gh extension install https://github.com/nektos/gh-act +``` + +Upstream: https://github.com/nektos/act + +## Quick commands + +```sh +# List jobs the local runner would execute for the push event +act -l + +# Run the default push workflows (what GitHub runs on a normal push) +act push + +# Run a specific event +act pull_request +act workflow_dispatch -W .github/workflows/release.yml + +# Run a single job +act -j test + +# Pin a runner image (medium is the act default; large matches real GH closer) +act -P ubuntu-latest=catthehacker/ubuntu:act-latest + +# Pass secrets / env without committing them +act -s GITHUB_TOKEN="$GITHUB_TOKEN" --env-file .env.act + +# Reuse containers between runs (faster iteration) +act --reuse +``` + +## Workflow (local CI → squash-merge on GitHub) + +1. Implement the change in the agent worktree. +2. `act -l` to confirm which jobs will fire for the event you care about. +3. `act push` (or the specific event/job) until it is green locally. +4. `gx branch finish --branch "" --base main --via-pr --wait-for-merge --cleanup`. + - Or `gx pr open` then `gx pr sync --auto-merge --merge-strategy squash` for explicit PR control. +5. On GitHub: squash-merge once the remote run mirrors the local one. + +## Notes + +- `act` does not reproduce GitHub-hosted services exactly (no real secrets, different runner image, no concurrency groups). Treat a green `act` run as a strong signal, not a proof — the remote run is still authoritative. +- Keep `act` config in `.actrc` at the repo root so every agent uses the same runner image. +- If a workflow uses `GITHUB_TOKEN` for API calls, pass a PAT via `-s GITHUB_TOKEN=...`; do not commit it. +- Add `.actrc`, `.cache/act`, and any `act`-specific event payloads to `.gitignore` if they appear.