Universal dev harness for AI agents and humans.
Declare your repo's observe/test/ship/verify capabilities once in tidal.yaml, then run them with a single CLI — whether you're Claude Code, Codex, a human, or CI/CD.
tidal init → generate tidal.yaml template
tidal test → run all tests
tidal observe → view logs, errors
tidal ship → create PR, deploy
tidal verify → health checks, smoke tests
tidal status → show what's configured
go install github.com/oSEAItic/tidal/cmd/tidal@latest# In any repo:
tidal init # creates tidal.yaml
vim tidal.yaml # configure your commands
tidal test # run tests
tidal test unit # run specific test
tidal ship pr # create a PR (auto-runs tests first if configured)
tidal verify # health + smoke checkstidal.yaml is a declarative config that maps capabilities to shell commands:
harness: v1
name: my-project
test:
unit:
cmd: "go test ./... -short"
lint:
cmd: "golangci-lint run"
ship:
pr:
base: main
auto_test: true
verify:
health:
cmd: "curl -sf https://my-app.com/health"
vars:
service: my-appTidal doesn't care about your language or framework — it just executes the cmd you declare.
Use {{var}} in commands. Switch environments with --env:
vars:
base_url: "https://staging.example.com"
envs:
production:
vars:
base_url: "https://example.com"tidal verify # uses staging URL
tidal verify --env production # uses production URLtidal test --json
# {"name":"unit","status":"pass","time_ms":3200}
# {"name":"lint","status":"fail","time_ms":1800,"detail":"..."}This repo uses itself. Here's our own tidal.yaml:
harness: v1
name: tidal
lang: go
test:
build:
cmd: "go build ./cmd/tidal"
vet:
cmd: "go vet ./..."
unit:
cmd: "go test ./... -short"
observe:
errors:
cmd: "gh issue list --label bug --state open --repo oSEAItic/tidal"
ship:
pr:
base: main
prefix: "tidal/"
auto_test: true
template: |
## Summary
{{summary}}
## Test
{{test_output}}
verify:
health:
cmd: "go build ./cmd/tidal && echo 'binary builds OK'"
vars:
summary: ""
test_output: ""After cloning this repo:
# Build and test tidal using tidal
go build -o tidal ./cmd/tidal
./tidal test # runs build + vet + unit
./tidal test build # just build
./tidal status # show configured capabilities
./tidal observe errors # check open bugs
./tidal ship pr # open a PR| Command | Description | Flags |
|---|---|---|
tidal init |
Generate tidal.yaml template |
|
tidal test [name...] |
Run test tasks (all or by name) | --json |
tidal observe logs [name] |
View logs | --json |
tidal observe errors |
View errors | --json |
tidal ship pr |
Create a pull request | --json |
tidal ship deploy [env] |
Deploy to environment | --json |
tidal verify |
Run health + smoke checks | --json |
tidal status |
Show configured capabilities |
Global flags:
| Flag | Description |
|---|---|
-c, --config |
Config file path (default: tidal.yaml) |
-e, --env |
Environment override (e.g. production) |
--json |
Structured JSON output |
Tidal is a tool, not an agent.
Agent (Claude Code / Codex / Devin) ← has a brain, makes decisions
│
├── tidal test --json ← no brain, runs commands, returns data
├── tidal observe --json
├── tidal ship
└── tidal verify --json
Tidal doesn't decide what to do next. It executes what's declared in tidal.yaml and returns structured results. The agent decides whether to loop, escalate, or move on.
Like kubectl is to Kubernetes operators. Like gh is to GitHub bots.
| User | How they use Tidal |
|---|---|
| AI Agents (Claude Code, Codex, Devin) | tidal test --json → parse → fix → tidal ship pr |
| Human devs | tidal deploy staging instead of remembering kubectl commands |
| CI/CD | tidal test && tidal ship deploy in GitHub Actions |
- Phase 0: CLI scaffold + tidal.yaml schema
- Phase 1:
test/observe/ship/verify+--json+run-loop - Phase 2:
tidal worktree create/destroy— isolated parallel execution - Phase 3:
tidal lint— declarative rule engine (file size, imports, naming) - Phase 4:
tidal grade— quality scoring (coverage, lint, docs) - Phase 5:
tidal observemetrics/traces — PromQL/TraceQL support - Phase 6:
tidal drive— app launch, screenshot, video recording
MIT — oSEAItic