Fast CLI tool to validate development environments. Define checks in YAML, get clear diagnostics.
Pulse validates whether a development environment is correctly configured. It checks for required tools, files, services, and environment variables — then reports what's missing and optionally suggests fixes.
Pulse environment check
✓ Go go version go1.26.2 darwin/arm64
✓ Go module found go.mod
✓ Docker running
✗ PostgreSQL
localhost:5432 refused connection
Suggested fix:
docker compose up db -d
Summary: 3 passed • 1 failed • 142ms
Every team has onboarding friction. New developers clone the repo, run the project, and hit cryptic errors because they're missing a tool, a service isn't running, or an env var isn't set. The fix is usually buried in a wiki nobody maintains.
Pulse replaces that wiki with a declarative YAML file that lives in the repo. Run pulse and you know in under 200ms exactly what's missing — no guessing, no Slack messages, no "works on my machine."
- Validate, don't provision — checks your environment, never installs software
- Declarative — one YAML file, version-controlled with the code
- Fast — concurrent execution, typically <200ms for 10+ checks
- CI-native — JSON output, GitHub annotations, proper exit codes
curl -sSL https://raw.githubusercontent.com/HugoAlvarezAjenjo/pulse/main/install.sh | shgo install github.com/HugoAlvarezAjenjo/pulse/cmd/pulse@latestPre-built binaries for Linux, macOS, and Windows are available on the Releases page.
git clone https://github.com/HugoAlvarezAjenjo/pulse.git
cd pulse
make build# Auto-detect your stack and generate config
pulse init
# Or use a preset
pulse init --preset node
# Run checks
pulse| Command | Description |
|---|---|
pulse |
Run all checks (same as pulse check) |
pulse check |
Run environment checks |
pulse ci |
Run checks in CI mode (no colors, no prompts) |
pulse init |
Generate a .pulse.yaml (auto-detect or preset) |
pulse list |
List configured checks without running them |
pulse validate |
Validate config syntax without running checks |
pulse report |
Run checks and generate a markdown report |
pulse doctor |
Show diagnostic info about pulse and config |
pulse completion |
Generate shell completion scripts (bash/zsh/fish) |
Create a .pulse.yaml in your project root:
checks:
- name: Node.js
type: command
command: node --version
expected: ">= 18.0"
- name: Environment file
type: file
path: .env
fix:
run: "cp .env.example .env"
- name: PostgreSQL
type: port
host: localhost
port: 5432
timeout: 5s
groups: [backend]
fix:
run: "docker compose up db -d"
- name: API Key
type: env
variable: API_KEY
expected: "sk-*"
groups: [backend]
- name: Frontend deps
type: command
command: pnpm --version
groups: [frontend]Validates a command exists and optionally checks its version.
- name: Go
type: command
command: go version
expected: ">= 1.21"Version constraints use semver syntax — supports >=, <=, >, <, !=, ~> (pessimistic), and ranges (>= 1.21, < 2.0).
Version extraction is automatic — works with any output format (go version go1.26.2 darwin/arm64, node v22.3.0, Python 3.12.1, etc.)
Validates a file exists.
- name: Config
type: file
path: .envValidates a TCP port is accepting connections.
- name: Database
type: port
host: localhost
port: 5432Validates an environment variable exists (optionally matches a pattern).
- name: API Key
type: env
variable: API_KEY
expected: "sk-*" # wildcards: "sk-*", "*-production"Validates an HTTP endpoint responds with expected status.
- name: API Health
type: http
url: http://localhost:3000/health
status: 200Validates a Docker container is running.
- name: Redis
type: docker
container: redisAssign checks to groups for selective execution:
checks:
- name: Node.js
type: command
command: node --version
groups: [frontend]
- name: PostgreSQL
type: port
port: 5432
groups: [backend, test]
- name: .env file # no group = always runs
type: file
path: .envpulse check -g frontend # only frontend + global checks
pulse check -g backend # only backend + global checks
pulse check -g backend -g test # union of groupschecks:
- name: Slow build
type: command
command: make build
timeout: 2m # per-check timeout
- name: Quick port
type: port
port: 5432
timeout: 3spulse --timeout 10s # global override for all checksPriority: per-check > global flag > default (30s)
Any check can include a suggested fix:
- name: Database
type: port
port: 5432
fix:
run: "docker compose up db -d"pulse --fix # prompts before executing each fixCreate .pulse.local.yaml for personal overrides (add to .gitignore):
# .pulse.local.yaml — not committed
checks:
- name: PostgreSQL # overrides by name
type: port
host: localhost
port: 5433 # my postgres is on a different port
- name: Debug mode # new check, only for me
type: env
variable: DEBUGMerge rules:
- Same name → local overrides base completely
- New name → appended
- No groups removed from base
pulse # pretty (auto-detects terminal)
pulse --plain # no colors (auto when piped)
pulse -o json # structured JSON
pulse -o github # GitHub Actions annotations
pulse -q # quiet: only show failuresAuto-TTY detection: colors are disabled automatically when output is piped or redirected.
pulse ci # plain, quiet, no prompts
pulse ci --fail-fast # stop at first failure
pulse ci -o github # GitHub Actions annotations
pulse ci -g backend # only backend checks- name: Validate environment
run: pulse ci --output github| Code | Meaning |
|---|---|
| 0 | All checks passed |
| 1 | One or more checks failed |
| 2 | Config/runtime error |
| Flag | Short | Description |
|---|---|---|
--output |
-o |
Output format: pretty, plain, json, github |
--quiet |
-q |
Only show failures and errors |
--plain |
Disable colors (shorthand for -o plain) |
|
--group |
-g |
Run only specified groups (repeatable) |
--timeout |
-t |
Timeout per check (e.g., 10s, 1m) |
--config |
Path to config file | |
--fix |
Prompt to run suggested fixes | |
--fail-fast |
Stop at first failure (ci command) | |
--version |
Show version info | |
--preset |
Use preset template (init command) | |
--empty |
Generate blank template (init command) | |
--force |
Overwrite existing config (init command) |
Share a base config across multiple projects:
# base.pulse.yaml (shared across org)
checks:
- name: Git
type: command
command: git --version
- name: Docker
type: command
command: docker --version# .pulse.yaml (project-specific)
extends: base.pulse.yaml
checks:
- name: Node.js
type: command
command: node --version
expected: ">=20"Rules:
- Child checks with same
nameoverride the parent - New checks are appended
- Supports chains (parent can also
extends) - Max 5 levels deep (circular detection included)
- Path is relative to the config file
Pulse searches in the current directory:
.pulse.yaml(preferred)pulse.yaml- Resolves
extendschain if present .pulse.local.yaml(merged on top, if exists)
make build # Build binary
make test # Run all tests
make lint # Run golangci-lint
make fmt # Format code
make run # Build and run
make install # Install to $GOPATH/binSee docs/architecture.md for design details.
MIT