{
  "markdown": "# Local CI\n\nLocal CI is a tool that allows you to run CI/CD pipelines locally using Docker containers. It helps developers test and debug their CI pipelines without pushing to remote repositories.\n\n## Features\n\n- Run CI pipeline jobs locally using Docker\n- Stages-based execution similar to GitLab CI\n- Configuration using YAML format\n- Global and job-specific environment variables\n- Working directory customization\n- Cache support for dependencies and build artifacts\n- Automatic file copying with .gitignore support\n- Real-time log streaming from containers\n- Automatic container cleanup\n- Stage-based pipeline execution\n- Job-based pipeline execution\n- Parallel job execution (all jobs at once, or per-stage) with a live status board\n- Per-job `parallel: true` keyword for detaching individual jobs from the sequential chain\n- Matrix builds: parametrize a job with `matrix:` to fan it out across variable combinations\n- Services: sidecar containers (databases, caches) on a private per-job network with readiness gates — `services: [postgres:16]`\n- Artifacts: pass build outputs from one job to the next with `artifacts: paths: [...]`\n- DAG scheduling: `needs: [job]` starts a job the moment its dependencies pass instead of waiting for the stage barrier\n- Per-job `timeout:` and `retry:` for slow or flaky jobs\n- Templates and includes: factor common config into `.dot-prefixed` templates and pull shared files with `include:`\n- Stage placeholders: splice an included file's stages into the main pipeline at a chosen position\n- GitLab utils\n- Bootstrap scripts\n- Cleanup scripts (companion to bootstrap)\n- Per-job bootstrap and cleanup scripts\n- Web UI: live pipeline graph, ANSI-colored searchable logs, run control (env vars, per-stage/per-job runs, failed-job re-run), desktop notifications, and a built-in YAML editor with live lint — served from a single binary with `local-ci ui`\n- Run history with git context (branch + commit per run), plus per-job duration trends and flaky-job detection; inspect from the UI or `local-ci runs` / `local-ci log`\n- Debug shell: `local-ci shell <job>` drops you into the job's exact container environment — image, variables, workspace, cache mounts, and running services\n- Watch mode: `local-ci run --watch` re-runs the pipeline on every file change\n- Config linting (`local-ci validate`) and a `.gitlab-ci.yml` importer (`local-ci import gitlab`)\n- Claude Code agent plugin\n\n## Installation\n\n### Prerequisites\n\n- Docker must be installed and running\n- Your user must have permissions to access the Docker daemon\n- Verify installation with `docker --version`\n\n### Homebrew (macOS / Linux)\n```bash\nbrew install --cask MrPuls/local-ci/local-ci\n```\nShell completions for bash, zsh, and fish are installed automatically.\n\n### Go Install\n\nRequires Go 1.26 or later ([download](https://golang.org/dl/)). The web UI build is\ncommitted, so the installed binary includes `local-ci ui` with no extra tooling.\n```bash\ngo install github.com/MrPuls/local-ci/cmd/local-ci@latest\n```\n\n### Manual\n\nDownload the latest binary for your platform (Linux, macOS, or Windows) from the\n[releases page](https://github.com/MrPuls/local-ci/releases). The archives also\ncarry completion scripts (`completions/`) for bash, zsh, fish, and PowerShell;\nor generate them on the fly with `local-ci completion <shell>`.\n\n### Shell completions\n\nCompletions are context-aware: `local-ci shell <TAB>` lists the jobs defined in\nyour config, `-j`/`-s` complete job and stage names, `local-ci log <TAB>`\ncompletes recent run ids (with their status), and `-c` offers the discovered\nconfig files. Homebrew installs them for you; otherwise see\n`local-ci completion --help`.\n\n### Build from source\n\nA `Makefile` wraps the common tasks (run `make help` for the full list). Building\nthe UI needs [Bun](https://bun.sh); the Go binary needs Go 1.26+.\n```bash\nmake build      # build the web UI + the local-ci binary into ./bin\nmake install    # build the UI and `go install` the binary\n```\nAfter changing anything under `web/`, run `make web` and commit the regenerated\n`internal/web/dist` so the embedded UI stays in sync.\n\n\n## Usage\n\n### Check Installation\n\n```bash\nlocal-ci --version\n```\n\n### Run a Pipeline\n\n```bash\n# Run using default .local-ci.yaml in current directory\nlocal-ci run\n\n# Run with a specific config file using --config/-c flag\nlocal-ci run --config my-pipeline.yaml\n\n# Run a specific job using --job/-j\nlocal-ci run --job JobName\n\n# Or to run multiple jobs\nlocal-ci run --job jobName1,JobName2\n\n# Run jobs from a specific stage using --stage/-s\nlocal-ci run --stage stageName\n\n# Or use multiple stages\nlocal-ci run --stage stageName1,stageName2\n\n# Run all jobs in parallel with --parallel/-p\nlocal-ci run --parallel\n\n# Or run stages in order, with jobs inside each stage in parallel\nlocal-ci run --parallel-stages\n\n# Clone/update the repository and run it's local-ci.yaml with --remote/-r\nlocal-ci run --remote <repository_url>\n\n# Pass additional environment variables with --env/-e\nlocal-ci run --env NEW_VAR=var_value,SECOND_VAR=new_value\n```\n\nWhen you don't pass `-c/--config`, `run` scans the working directory for config\nfiles — the canonical `.local-ci.yaml`/`.local-ci.yml` plus any\n`<name>.local-ci.yaml` / `<name>-local-ci.yaml` / `<name>_local-ci.yaml`\nvariant — and asks which one to load (Enter picks the first). Non-interactive\nsessions never block: a single discovered file is used as-is, anything else\nfalls back to `.local-ci.yaml`.\n\n### Developer loop\n\n```bash\n# Re-run the pipeline on every file change (Ctrl-C to stop)\nlocal-ci run --watch\n\n# Drop into a job's exact container environment to debug it from the inside:\n# same image, variables, workdir, cache mounts, copied workspace — and its\n# services running on the job network\nlocal-ci shell Test\n\n# Lint the config without running anything (exit 1 when invalid — git-hook friendly)\nlocal-ci validate\n\n# Convert an existing GitLab CI config (prints notes for anything that can't carry over)\nlocal-ci import gitlab\n```\n\n### Web UI\n\n`local-ci ui` serves the whole web app — its UI **and** API — from this single\nbinary, then opens it in your browser. No separate dev server or token to manage.\n\n```bash\n# Serve the UI for the project in the current directory and open a browser\nlocal-ci ui\n\n# Bind a specific port and don't auto-open a browser\nlocal-ci ui --port 8080 --no-open\n\n# Use a non-default config file\nlocal-ci ui --config my-pipeline.yaml\n```\n\nIt binds loopback only (`127.0.0.1`) and shows the configured pipeline as a live\ngraph: trigger and cancel runs, watch job status update in real time, stream\nlogs, and browse run history — all backed by the same engine as `local-ci run`.\n\nOn load the UI scans the project directory for config files (same patterns as\n`run`) and asks which one to drive the session; switch any time via the `FILE:`\nchip in the top bar. The **EDITOR** tab is a built-in YAML editor with syntax\nhighlighting, live lint (undefined stages, unknown `needs` targets, missing\nfields — flagged before you save), validation feedback, a diff preview before\ndiscarding edits, and a live pipeline graph — `Ctrl+S` writes to disk.\n\nThe pipeline view exposes the full trigger surface: pick a run mode, set env\nvars, run a single stage from its column header, or a single job from the\ninspector (failed jobs get a one-click re-run). Logs render ANSI colors and\nare searchable. History shows each run's git context (`branch@sha`) and a\nJOB_TRENDS panel: per-job duration sparklines, pass rates, and an\nINTERMITTENT flag for jobs that flip between pass and fail. The bell in the\ntop bar enables desktop notifications when a run finishes in a hidden tab.\n\n> For **frontend development** against a hot-reloading dev server, use\n> `local-ci serve` (the API-only backend) together with the Vite dev server —\n> see [web/README.md](web/README.md).\n\n### Inspecting past runs\n\nEvery run (CLI or UI) is recorded to a local history store.\n\n```bash\n# List recent runs for the current project (newest first)\nlocal-ci runs\n\n# List runs across all projects, capping the count\nlocal-ci runs --all --limit 50\n\n# Show one run's per-job breakdown\nlocal-ci runs <run-id>\n\n# Print a recorded run's logs — all jobs, or one job\nlocal-ci log <run-id>\nlocal-ci log <run-id> --job Build\nlocal-ci log <run-id> --job pipeline   # run-level diagnostics\n```\n\n### Command reference\n\n| Command | Description | Flags |\n|---|---|---|\n| `run` | Run the pipeline | `-c/--config`, `-j/--job`, `-s/--stage`, `-r/--remote`, `-e/--env`, `-p/--parallel`, `--parallel-stages`, `-w/--watch`, `--no-record` |\n| `shell <job>` | Open an interactive shell in the job's container environment (services included) | `-c/--config`, `-v/--verbose` |\n| `validate [file]` | Lint a config without running it (exit 1 when invalid) | `-c/--config` |\n| `import gitlab [file]` | Convert a `.gitlab-ci.yml` into a local-ci config | `-o/--output` (default `.local-ci.yaml`, `-` for stdout), `--force` |\n| `runs [run-id]` | List recorded runs, or show one run's details | `-a/--all`, `-n/--limit` (default 20) |\n| `log <run-id>` | Print a recorded run's logs | `-j/--job` (use `pipeline` for diagnostics) |\n| `ui` | Serve the embedded web UI **and** API from one binary, then open a browser | `--host` (default `127.0.0.1`), `--port` (default `4123`), `-c/--config`, `--no-open` |\n| `serve` | Run the API-only backend (for the web dev server or a future desktop shell) | `--host` (default `127.0.0.1`), `--port` (default ephemeral), `--token` (default random), `-c/--config` |\n\nGlobal: `local-ci --version`, `local-ci --help`, `local-ci <command> --help`.\n\n## Quick Start\n\n1. Start Docker\n\n2. Create a `.local-ci.yaml` file in your project root:\n\n```yaml\nstages:\n  - build\n  - test\n\nvariables:\n  GLOBAL_VAR: global_value\n\nBuild:\n  stage: build\n  image: golang:1.21\n  variables:\n    GO_FLAGS: \"-v\"\n  script:\n    - echo \"Building application...\"\n    - go build $GO_FLAGS\n  cache:\n    key: go-build-cache\n    paths:\n      - .go/\n      - build/\n\nTest:\n  stage: test\n  image: golang:1.21\n  script:\n    - echo \"Testing with global var: $GLOBAL_VAR\"\n    - go test ./...\n  cache:\n    key: go-build-cache\n    paths:\n      - .go/\n```\n\n3. Run the pipeline:\n\n```bash\nlocal-ci run\n```\n\n## YAML Configuration\n\n### Basic Structure\n\n```yaml\n# Define stages and their order\nstages:\n  - build\n  - test\n  - deploy\n\n# Global variables (available to all jobs)\nvariables:\n  GLOBAL_KEY: global_value\n\n# Job definitions\njob_name:\n  stage: build    # Must match one of the defined stages\n  image: image_name\n  workdir: /path   # Optional\n  variables:       # Job-specific variables (override globals)\n    KEY: value\n  script:\n    - command1\n    - command2\n  cache:           # Optional cache configuration\n    key: cache-key\n    paths:\n      - path/to/cache\n      - another/path\n```\n\n## Claude Code Agent\n\nLocal CI ships as a [Claude Code](https://claude.ai/code) plugin. Once installed, Claude Code can autonomously write pipeline configs, run them, and validate your code in real Docker environments.\n\nInstall the plugin\n\n```bash\n/plugin marketplace add MrPuls/local-ci\n\n/plugin install local-ci@MrPuls-local-ci\n```\n\nSee the [Technical Reference](docs/tech-reference.md#claude-code-agent) for details.\n\n## Documentation\n\n- [YAML Configuration Reference](docs/yaml-reference.md)\n- [Technical Reference](docs/tech-reference.md)\n- [Claude Code Agent](docs/agent.md)\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\n[MIT License](LICENSE)\n",
  "bytes": 11510,
  "sha": "1747349fe48a97f83c885ded773620360f0d90cca3c2b7c3942e95f2550eb54c",
  "repo_slug": "mrpuls/local-ci",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_mrpuls_local_ci_local_ci_cd49b9ef/readme"
}