Manage GitHub repos from your terminal.
Quick Start · Features · Install · Commands
────────────────────────────────────────
Ward is a Rust CLI that treats repository management like infrastructure-as-code.
Declare your desired state in ward.toml, diff it against reality, apply the changes, and verify the result. No shell scripts, no cloning, no guessing.
Features
- Security management - Dependabot, secret scanning, push protection across repos in one command
- Template commits - deploy workflow configs via the Git Trees API (no cloning needed)
- Branch protection - declarative rules for PRs, approvals, status checks, force-push policies
- Settings & rulesets - Copilot code review rulesets, review instructions (app vs ops auto-detect)
- Compliance audit - version inventory, alert counts, security posture as JSON or table
- Rollback - reverse applied changes using the audit log
- Custom templates - drop
.terafiles in~/.ward/templates/to extend or override builtins - Interactive TUI - browse repos and security state in a terminal dashboard
- Audit trail - every mutation logged as JSON lines to
~/.ward/audit.log
────────────────────────────────────────
Install
# from crates.io (recommended)
# homebrew (macOS / Linux)
# shell script (macOS / Linux)
|
# powershell (Windows)
# from source
&&
Requires Rust >= 1.85 (source install only) and a GitHub token (GH_TOKEN, GITHUB_TOKEN, or gh auth token).
Token scopes needed: repo, read:org, workflow.
────────────────────────────────────────
Quick Start
Use ward init --non-interactive to scaffold a minimal ward.toml without the wizard.
────────────────────────────────────────
Configuration
[]
= "my-github-org"
[]
= true
= true
= true
= true
[]
= true
= 1
= true
= true
[]
= "chore/ward-setup"
= ["alice", "bob"]
= "chore: "
# custom_dir = "~/.ward/templates"
[[]]
= "backend"
= "Backend Services"
= ["operations?", "workflows"]
# repos = ["standalone-service", "shared-lib"] # explicit repo names (no prefix needed)
Systems group repos by name prefix: id = "backend" matches backend-* repos. The exclude field filters by regex on the suffix. You can also list repos explicitly with repos for repos that don't follow the prefix convention. Security and branch protection settings can be overridden per-system.
────────────────────────────────────────
Commands
Every mutating command follows plan → apply → verify.
ward security
ward protection
ward commit
Deploy config files to repos without cloning. Uses the Git Trees API for atomic commits.
Built-in templates: dependabot, codeql, dependency-submission. Auto-detects Gradle vs npm and extracts Java/Node versions.
ward settings
ward rollback
ward audit
ward repos
ward tui
Interactive terminal dashboard for browsing repos, security state, and applying changes.
Navigation:
1/2/3/? Switch tabs (Repos, Security, Actions, Help)
Tab / Shift+Tab Cycle systems
Enter / l Load repos for current system
j/k or arrows Navigate list
/ Filter repos
Esc Clear filter
q Quit
Repo Actions (on selected repo):
a Apply security settings
p Apply branch protection
t Deploy template (sub-menu: d/c/s for dependabot/codeql/submission)
S Apply settings (copilot ruleset + instructions)
Bulk Actions:
A Apply security to all filtered repos
r / R Reload / force reload (R clears cache)
Filter syntax:
foo Show repos matching "foo"
!ops Hide repos matching "ops"
!ops !system Hide repos matching "ops" OR "system"
foo !ops Show "foo", hide "ops"
Filters work like kanban board labels: stack multiple ! terms to exclude categories. Useful for hiding operations/gitops repos while working on application repos.
────────────────────────────────────────
How it works
Plan (read) → Apply (write) → Verify (read)
Diff current Execute with Re-read from API,
vs desired audit logging confirm match
- No git cloning - file commits use the Git Trees API (blob → tree → commit → update ref). Atomic, no filesystem side effects.
- Idempotent - detects existing state and skips what's already done.
- Audit log - every mutation logged to
~/.ward/audit.logas JSON lines. Query withjq. - Custom templates - place
.terafiles in~/.ward/templates/to add or override built-in templates. Uses Tera (Jinja2-compatible).
────────────────────────────────────────
Recipes
# full security hardening
# drift detection in CI
|
# rollback last batch of changes
────────────────────────────────────────
Global flags
| Flag | Description |
|---|---|
--org <ORG> |
GitHub org (overrides ward.toml) |
--system <ID> |
Filter repos by system prefix |
--repo <REPO> |
Target a single repo |
--json |
JSON output |
--parallelism <N> |
Max concurrent API calls (default: 5) |
-v / -vv / -vvv |
Log verbosity |
────────────────────────────────────────
Contributing
&& &&
- New template - add
.terafile + match arm incli/commit.rs - New security feature - add fields to
SecurityState+SecurityConfig, update planner - New command - add module in
cli/, register incli/mod.rs+main.rs
────────────────────────────────────────
License
MIT. See LICENSE.