Skip to content

StatPan/gira

Repository files navigation

Gira

Gira is a GitHub-native control plane for AI-assisted software work.

It turns the GitHub issue-to-PR loop into a predictable workflow that humans and coding agents can both follow:

issue -> branch -> PR -> checks -> evidence -> finish

AI coding agents can generate code and open pull requests, but real engineering work is not finished until the repository state converges: the PR is linked, checks are green, review blockers are clear, the issue is closed, active status labels are normalized, and the next command is obvious. Gira makes that finish step explicit.

Use Gira when you want GitHub to remain the source of truth, while still having a Jira-like lifecycle that coding agents can operate safely:

  • Issues are executable task packets.
  • Branches prove work has started.
  • PRs are change units.
  • Checks and reviews are validation evidence.
  • Milestones group sprint/release boundaries.
  • ticket finish merges only when policy allows, then converges issue state.
  • doctor detects repo, workflow, label, and closed-issue status drift.

The core safety model is Terraform-like:

  • --dry-run previews GitHub or repository mutations.
  • --apply executes only after the plan is understood.

Documentation: https://gira.statpan.com

Docs source lives in docs-site/ and is built with VitePress. The docs toolchain is separate from the product runtime; the shipped product remains the Go-built gira binary.

The target branch policy contract is documented in docs/branch-policy.md. It defines the planned direction for resolving a ticket base branch once, recording it as lifecycle state, preserving it through PR creation and review, and avoiding hidden local checkout mutation during finish.

Gira is not a Jira clone or a separate planning database. It is a workflow control layer over GitHub Issues, branches, PRs, checks, labels, and milestones. Repo-linked Projects are visibility surfaces; Project-only items stay intake or planning until routed to a repository issue.

Jira-primary provider mode is optional. In that mode Jira owns planning and status while GitHub still owns execution evidence. See docs/jira-primary-provider.md.

The core flow is:

install -> auth -> init/readiness -> ticket -> PR -> checks -> finish

3-Minute Quick Start

Install Gira:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | sh

Or install through a currently published package manager channel:

npm install -g @statpan/gira
bun install -g @statpan/gira
uv tool install gira-cli
pipx install gira-cli
python -m pip install --user gira-cli
brew tap StatPan/tap
brew install gira

Release binary installs do not require Go. Use Go only when building or testing Gira from source.

Authenticate GitHub first. Gira uses GitHub as the execution backend and shells through gh for GitHub API access:

gira version
gh auth status
gira guide

gira guide is built into the installed binary. Use gira guide quickstart, gira guide ticket, gira guide agent, or gira guide concepts when you need the workflow without opening this README. gira docs is an alias.

Read before writing. For repository setup, run init from a clean checkout so Gira can fail closed before apply steps:

gira init --repo OWNER/REPO --path . --dry-run
gira adopt repo --repo OWNER/REPO --path . --dry-run
gira status --repo OWNER/REPO

Start and finish development from a ticket:

gira status
gira ticket new "Add login retry" \
  --goal "Retry transient auth failures" \
  --acceptance "retries 3 times;does not retry 401;has tests" \
  --dry-run
gira ticket new "Add login retry" \
  --goal "Retry transient auth failures" \
  --acceptance "retries 3 times;does not retry 401;has tests" \
  --apply --start
gira ticket list --state open --label status:ready --limit 20

# implement the bounded issue scope, then verify locally
go test ./...

gira ticket pr --dry-run
gira ticket pr --apply --draft
gira ticket view
gira ticket prompt --role implementer --profile python
gira ticket note "Parser path is implemented; local tests are next." --dry-run
gira ticket checks
gira ticket wait --timeout 5m
gira ticket finish --dry-run
gira ticket finish --apply
gira ticket status

gira ticket new creates a repo-bound executable ticket. It writes a structured issue body from --goal, --scope, --acceptance, and --notes, or accepts a complete issue packet through --body, --body-file PATH, or --body-file -. It applies type:* and status:ready, previews the exact payload with --dry-run, and can immediately start the branch with --start. Requested labels must already exist in the repo; ticket new preflights labels during dry-run/apply and reports missing taxonomy instead of creating labels implicitly. gira ticket list lists GitHub issue-backed tickets with compact filters: --state open|closed|all, repeatable or comma-separated --label, --assignee, --milestone, --limit, and --json. gira ticket view shows the ticket operating card: issue state, Gira status, linked PR, blockers, next action, and next command. gira ticket prompt renders stateless planner, implementer, or reviewer prompts from the ticket, with default and python profiles. gira ticket note renders a structured context note and posts it to the issue, linked PR, or both after --dry-run review. gira ticket supersede creates a linked replacement issue, writes decision notes on both tickets, removes active status labels from the old ticket, adds resolution:superseded, and closes it after dry-run review. gira ticket resolves --repo from .gira/config.yaml or git origin. After ticket start checks out an issue-N-* branch, ticket view, ticket prompt, ticket note, ticket pr, ticket checks, ticket wait, ticket finish, and ticket status can infer the ticket from the current branch or linked PR. Pass --repo OWNER/REPO and --ticket N when running outside that context.

For an existing repository, run gira adopt repo --dry-run before full bootstrap. Gira detects existing issues, labels, milestones, Projects, AGENTS.md, and GitHub templates, then recommends an adoption strategy. The default merge strategy preserves user-owned files and metadata while adding only the minimal Gira contract, such as .gira/config.yaml and an AGENTS.md managed block. Bootstrap sample issues are never required for normal adoption.

You can still call gh directly for low-level GitHub operations, but lifecycle work should use Gira ticket controls when available: ticket view, ticket status, ticket start, ticket pr, ticket note, ticket supersede, ticket checks, ticket wait, and ticket finish. Use raw gh only when Gira has no lifecycle command or when you intentionally need an unopinionated GitHub operation. The ticket commands keep the lifecycle consistent: they create or reuse the linked PR, require a closing body such as Closes #TICKET, compute blockers, render context notes, supersede stale work with linked replacement evidence, wait for pending checks, merge only when review and checks allow it, clean up the branch when safe, and give the next Gira command to run.

gira epic list, gira epic status, and gira epic finish close the larger planning loop without requiring raw gh issue list or gh issue close. epic list is a type:epic view over GitHub issues with the same compact list filters as ticket list. Gira can resolve an epic from the current issue-N-* branch, --title, --slug, --milestone, or a sole open type:epic; --ticket N remains the explicit fallback. epic finish --apply refuses to close while child issues are still open, then normalizes active status labels and closes the epic through GitHub.

gira stats repo --repo OWNER/REPO --since 90d renders the first Closure Funnel report. It is GitHub read-only, defaults to human text output, and uses --json only for automation. The report counts opened/closed issues, superseded issues, opened/merged PRs, closing-link hygiene, check friction, stale open work, and closure rate. gira stats workspace --since 90d is the planned multi-repo rollup; see docs/closure-funnel-stats.md.

Jira-Primary Provider Mode

GitHub-native mode remains the default. Jira-primary mode is explicit and keeps a split source of truth: Jira owns planning and status, while GitHub owns branch, PR, review, checks, merge, and close evidence.

gira jira init --repo OWNER/REPO --api-base https://example.atlassian.net --project ABC --dry-run
gira jira init --repo OWNER/REPO --api-base https://example.atlassian.net --project ABC --apply
gira jira doctor --repo OWNER/REPO --sample-key ABC-123
gira jira mirror ABC-123 --repo OWNER/REPO --dry-run
gira jira mirror ABC-123 --repo OWNER/REPO --apply
gira ticket start ABC-123 --repo OWNER/REPO --apply
gira ticket finish --repo OWNER/REPO --dry-run
gira ticket finish --repo OWNER/REPO --apply

Provider config is non-secret and lives in the user-global repo registry. Jira credentials come from JIRA_EMAIL and JIRA_API_TOKEN. gira jira doctor is read-only and reports whether a Jira-primary repo is supported, partially_supported, or blocked before heavier operation. ticket finish refuses Jira Done while GitHub evidence is incomplete, including missing mirror issue, missing linked PR, draft PR, review blocker, failing or pending checks, or unmerged PR. Jira workflow mutation, background sync, full bidirectional sync, hosted dashboards, and Jira-only completion are outside the OSS CLI slices. See docs/jira-primary-provider.md and gira guide jira.

Ticket Flow Cases

Most first-time work starts by creating a repo-bound ticket and immediately starting it:

gira ticket new "Fix install retry" \
  --goal "Retry transient install downloads" \
  --acceptance "retries temporary network failures;does not hide checksum errors;has tests" \
  --apply --start

If the GitHub issue already exists, start from that ticket number once. After Gira checks out the issue-N-* branch, the rest of the flow infers the ticket from context:

gira ticket start 42 --apply
gira ticket pr --apply --draft
gira ticket view
gira ticket note "Ready for CI review." --target pr --dry-run
gira ticket checks
gira ticket wait --timeout 5m
gira ticket finish --apply

If someone reports an issue in GitHub without enough structure, normalize it before starting work: add the missing goal, scope, acceptance criteria, and status:ready/type:* labels in GitHub or recreate it through gira ticket new. Start only after the ticket is executable.

Use --json for automation:

gira status --repo OWNER/REPO --json
gira ticket status --repo OWNER/REPO --ticket 12 --json

LLM And Agent Runbook

When an LLM or coding agent operates a Gira-managed repository, follow this order exactly. Do not skip dry-runs, do not use raw gh for product workflow steps when a gira lifecycle command exists, and keep the PR body linked to the source issue with Closes #TICKET. A Project item by itself does not authorize branch, PR, checks, merge, or finish work unless it is backed by a repository issue; route or lower repo-agnostic items first.

# 1. Read current state.
gh auth status
gira init --repo OWNER/REPO --path . --dry-run
gira adopt repo --repo OWNER/REPO --path . --dry-run
gira status --repo OWNER/REPO

# 2. Create and start a repo-bound ticket.
gira ticket new "TITLE" --goal "GOAL" --acceptance "item 1;item 2" --dry-run
gira ticket new "TITLE" --goal "GOAL" --acceptance "item 1;item 2" --apply --start
gira ticket new --title "TITLE" --body-file issue.md --dry-run
gira ticket new --title "TITLE" --body-file issue.md --apply --start

# 3. Implement the bounded issue scope, then verify locally.
go test ./...

# 4. Open or validate the PR through Gira.
gira ticket pr --dry-run
gira ticket pr --apply --draft
gira ticket view
gira ticket note "Ready for review." --target pr --dry-run
gira ticket note "Ready for review." --target pr --apply

# 5. Finish through Gira after review and checks are ready.
gira ticket checks
gira ticket wait --timeout 5m
gira ticket finish --dry-run
gira ticket finish --apply

# 6. Re-check the ticket and Project bridge.
gira ticket status

Use GitHub assignees for accountable humans. Use agent:* labels for the execution actor, for example agent:human, agent:codex, agent:reviewer, or agent:gira. Use lane:* labels for delegation authority and risk, such as lane:agent, lane:human, or lane:hybrid. gira projects sync mirrors the execution actor label into the Project planning field; it does not replace GitHub assignees or make the Project item the source of truth.

Advanced visibility commands such as gira projects sync --config .gira/config.yaml --dry-run, gira epic status, and gira epic finish --dry-run are useful after the first ticket loop is working.

Command Model

The Go-built gira binary is the sole product implementation. The default user experience is Jira-style ticket work backed by GitHub issues, PRs, labels, and milestones.

  • gira ticket ... is the daily issue -> branch -> PR workflow.
  • gira workspace ... is the Jira-like personal workspace and inbox layer for repo-agnostic backlog before work is routed to an execution repo.
  • gira projects ... mirrors canonical repository issue state into visible GitHub Projects board items.
  • gira sprint ..., gira release, and gira status are daily planning and reporting commands.
  • gira audit readiness --repo OWNER/REPO combines doctor checks, audit ledger health, and the next Gira-first action.
  • gira ops ... contains advanced setup, migration, policy, audit, and raw GitHub controls.
  • gira start and gira work ... remain compatibility aliases.

Advanced Setup

Most daily work should use gira ticket, gira workspace, gira projects, gira sprint, gira release, and gira status. Use gira ops for setup, adoption, policy, audit, and lower-level GitHub controls.

Plan setup without changing GitHub or repository files:

gira adopt repo --repo OWNER/REPO --path . --dry-run
gira ops bootstrap --repo OWNER/REPO --template default --dry-run
gira ops sync --repo OWNER/REPO --dry-run

Apply the reviewed setup:

gira ops bootstrap --repo OWNER/REPO --path /path/to/repo
gira ops sync --repo OWNER/REPO
gira ops onboard verify --repo OWNER/REPO --stage steady-state

Jira To GitHub Mapping

Gira keeps the user-facing workflow close to Jira while storing canonical state in GitHub. The v1 model is intentionally small:

Jira concept GitHub object Gira behavior
Workspace GitHub account plus configured inbox and execution repos A workspace groups repo-agnostic intake with one or more execution repos so personal backlog is visible before it is assigned to a repo.
Project Repository plus optional repo-linked GitHub Project board A repo is the default execution space. Repo-linked Projects can show repo issue state even when the Project URL is under users/OWNER/projects/N or orgs/OWNER/projects/N. Multi-repo work starts as a top-level ticket and is lowered into repo issues when ownership is clear.
Backlog Inbox repo issues plus repo issues gira workspace status and gira workspace backlog show unrouted inbox tickets together with routed repo work.
Epic Parent or top-level issue A milestone-sized outcome. gira epic status and gira epic finish inspect and close epics without requiring the issue number when branch, title, slug, milestone, or repo context is enough.
Story / Task / Bug Issue The main work packet. Type, priority, blocked, and status are represented with managed labels and issue metadata.
Sprint Milestone gira sprint plans, starts, closes, and rolls over milestone-scoped work.
Status Labels plus PR evidence Gira reads and updates status labels, then cross-checks branch, PR, review, and check state. In Jira-primary mode, Jira owns planning/status and GitHub status labels are mirrors or execution hints.
Assignee GitHub assignee Ownership stays visible in GitHub and can be supplemented with owner or worker labels.
Branch Issue execution context gira ticket start verifies the ticket, creates or reuses a branch, and moves work to in-progress on apply.
Pull request Change unit gira ticket pr creates or validates a linked PR with a closing keyword such as Closes #12.
Done Merged PR plus closed issue Completion is proven by GitHub merge and close evidence, not by hidden local state. Jira Done transitions are gated on this evidence when Jira-primary mode is enabled.
Release GitHub Release plus readiness report gira release readiness checks whether issue, PR, review, and milestone evidence are ready for delivery.

Full GitHub Projects v2 view automation, Web UI/TUI, chat bots, LLM decomposition, background Jira sync, and full bidirectional Jira sync are not v1 product workflows. Jira import/export commands are explicit migration helpers. Projects sync links and mirrors repository issue state into Projects; it does not make Project items the execution source of truth.

Workspace Backlog

For a single repo, gira status --repo OWNER/REPO is enough. For Jira-style intake that is not yet tied to a repository, configure a personal workspace:

workspace:
  name: personal
  owner: OWNER
  inbox_repo: OWNER/backlog
  repos:
    - OWNER/app
    - OWNER/cli

The inbox repo is where repo-agnostic tickets live. Execution repos are where branch, PR, milestone, and release work happens.

gira workspace status --config .gira/config.yaml
gira workspace backlog --config .gira/config.yaml
gira workspace list --config .gira/config.yaml
gira workspace sync --dry-run --config .gira/config.yaml
gira workspace ticket new "Define billing model" --repo OWNER/app --dry-run --config .gira/config.yaml
gira workspace ticket new "Define billing model" --repo OWNER/app --apply --config .gira/config.yaml
gira workspace ticket route --ticket 12 --repo OWNER/app --dry-run --config .gira/config.yaml
gira workspace ticket route --ticket 12 --repo OWNER/app --apply --config .gira/config.yaml
gira workspace project adopt --owner OWNER --title "Gira" --dry-run --config .gira/config.yaml
gira workspace project adopt --owner OWNER --title "Gira" --apply --config .gira/config.yaml
gira projects sync --dry-run --config .gira/config.yaml
gira projects sync --apply --config .gira/config.yaml

workspace status is safe for larger global workspaces: it reports GitHub API budget when available, bounds concurrent repo reads, caches per-repo status for five minutes by default, and supports --repo, --limit, --active-only, and --refresh for practical CLI and future GUI refresh loops.

workspace ticket new --repo OWNER/REPO --apply creates an inbox ticket, routes it to a repo execution issue, and links the child issue back to the inbox ticket without requiring the user to copy the inbox issue number. workspace ticket route --ticket N remains available for older or externally-created inbox tickets. After routing, the normal loop continues with gira ticket start, gira ticket pr, and gira ticket status on the target repo.

workspace project adopt registers an existing profile or org GitHub Project in workspace.project; it never creates Projects and fails instead of replacing a different configured Project. projects sync then keeps that existing GitHub Projects v2 board visible by linking configured repos, adding missing open issues as project items, mirroring Gira status labels to the board's standard Status field, keeping closed issues as Done, creating supported planning fields, mirroring priority:*, area:*, and agent:* labels into Project planning fields, and copying milestone due dates into Target date. A Project may live under users/OWNER/projects/N or orgs/OWNER/projects/N; when it is linked to the repo and its items are repo issues, it is still a normal repo board surface. Repo issues remain the execution source of truth. Add --archive-closed only when closed issue items should leave the active Project item set. GitHub does not expose supported Project view creation APIs, so Gira reports the manual Board/Schedule view setup step instead of hiding it behind raw Project numbers.

GitHub Workflow Templates

The default bootstrap template includes GitHub issue forms and a pull request template under .github/. These templates are part of the Gira repository contract: they help downstream repos collect the context needed before an issue becomes status:ready, then keep PRs tied to the issue -> branch -> checks -> finish loop.

gira ops bootstrap --repo OWNER/REPO --template default --dry-run
gira ops bootstrap --repo OWNER/REPO --path /path/to/repo

Issue forms collect goal, scope, acceptance criteria, priority, optional source ticket, rollout or migration notes, observability/security impact, and expected verification. They do not ask for a Gira ticket ID before issue creation because the GitHub issue number becomes the ticket ID after submission. The PR template requires a closing issue reference, records the expected gira ticket start and gira ticket finish lifecycle commands, and includes production-readiness checks for tests, migrations, rollout, observability, security, and docs.

Install, Upgrade, and Remove

Gira is implemented as a Go-built CLI. Normal users should install the release binary through install.sh, npm/bun, PyPI via uv/pipx/pip, or Homebrew. These channels do not require Go, do not build from source, and do not mutate any repository.

Release Binary Channels

Use one of the release channels:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | sh
npm install -g @statpan/gira
bun install -g @statpan/gira
uv tool install gira-cli
python -m pip install --user gira-cli
pipx install gira-cli
brew tap StatPan/tap
brew install gira

All channels install the same Go-built gira binary. Package managers are wrappers around the release binary, not alternate runtimes.

Install Script

Install the latest tagged release:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | sh

Pin a version:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | GIRA_VERSION=v1.0.0 sh

Install to a custom directory:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | GIRA_INSTALL_DIR="${HOME}/bin" sh

The install script:

  • Detects os and arch, then selects the matching GitHub release archive.
  • Installs latest by default and accepts an explicit version, for example GIRA_VERSION=v1.0.0.
  • Downloads from GitHub release assets, not from a source checkout or CI artifact.
  • Requires the release checksums.txt asset and verifies the selected archive before unpacking it.
  • Installs to ${GIRA_INSTALL_DIR} when set, otherwise to ${HOME}/.local/bin.
  • Prints PATH guidance when the install directory is not already on PATH.
  • Replaces an existing gira binary in the selected install directory atomically when possible.
  • Never modifies repository files, GitHub labels, milestones, or issues during binary installation.

Verification:

command -v gira
gira --help
gira version
gira upgrade
gira doctor --repo OWNER/REPO
gira audit readiness --repo OWNER/REPO

Developer Source Build

Use go install only for source and development workflows, not as a normal user install path:

go install github.com/StatPan/gira/cmd/gira@latest

The module is github.com/StatPan/gira and the binary package is under cmd/gira, so the install path includes /cmd/gira. If the repository is private in your environment, configure Go private module access first, for example with GOPRIVATE=github.com/StatPan/gira plus normal GitHub authentication.

From this checkout, build and install the current source version:

GOBIN="${HOME}/.local/bin" go install ./cmd/gira

Use a temporary install directory for smoke tests:

GOBIN="$(mktemp -d)" go install ./cmd/gira
"${GOBIN}/gira" --help
"${GOBIN}/gira" version

GitHub Release Archives

Manual release-archive installation uses the same release assets as the install script. Release archive names follow:

gira_VERSION_linux_amd64.tar.gz
gira_VERSION_linux_arm64.tar.gz
gira_VERSION_darwin_amd64.tar.gz
gira_VERSION_darwin_arm64.tar.gz
gira_VERSION_windows_amd64.zip

Example:

version=v1.0.0
curl -fLO "https://github.com/StatPan/gira/releases/download/${version}/gira_${version}_linux_amd64.tar.gz"
tar -xzf "gira_${version}_linux_amd64.tar.gz"
install -m 0755 "gira_${version}_linux_amd64/gira" "${HOME}/.local/bin/gira"
gira --help

Verify the archive with the release checksums.txt before installing the binary. Every v1 release should publish checksums.txt; treat a missing checksum asset as a release defect.

Wrapper Distribution Boundaries

Package-manager wrappers such as Homebrew, npm, bun, pip, pipx, or uv are allowed only as distribution channels for the Go-built release binary. They must not reimplement Gira in another runtime, change the command surface, or install unversioned CI artifacts.

The npm/bun wrapper package is maintained under packages/npm, and the PyPI wrapper package is maintained under packages/pypi. Homebrew publishing targets the external StatPan/homebrew-tap repository. These channels install the Go-built release binary and verify release checksums.

Wrapper packages must preserve the same command surface as the native binary:

gira version
gira ticket start --repo OWNER/REPO --ticket 12 --dry-run
gira ops bootstrap --repo OWNER/REPO --template default --dry-run
gira ops sync --repo OWNER/REPO --dry-run
gira status --repo OWNER/REPO --json

Official release install channels:

npm install -g @statpan/gira
bun install -g @statpan/gira
uv tool install gira-cli
python -m pip install --user gira-cli
pipx install gira-cli
brew tap StatPan/tap
brew install gira

The install script downloads GitHub Release assets directly. The npm and bun channels install the @statpan/gira wrapper from the npm registry. The uv, pip, and pipx channels install the gira-cli wrapper from PyPI. The Homebrew channel is published through StatPan/homebrew-tap. All channels install the same Go-built release binary and keep the gira command surface unchanged. Normal release-binary users do not need Go installed.

apt/deb packaging is a future target, not an initial official channel. It should wait until usage justifies signing keys, repository hosting, architecture matrix maintenance, and upgrade policy support.

Unsupported distribution channels are source snapshots, unversioned binaries copied from CI artifacts, package wrappers that do not execute the official Go-built binary, and alternate product runtimes.

Upgrade

Check the latest release and print the right next step for your install channel:

gira upgrade
gira update
gira upgrade --channel uv
gira upgrade --channel pipx
gira upgrade --json

gira upgrade and gira update are aliases. They are advisory by default: the installed Go-built binary checks the latest GitHub release and prints the channel-specific command, but it does not run package managers or mutate repositories. If Gira cannot confidently infer how it was installed, pass --channel install.sh|uv|pipx|pip|homebrew|npm|bun. Use --channel go only for developer source builds.

Use the same channel that installed Gira:

curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | sh
curl -fsSL https://raw.githubusercontent.com/StatPan/gira/main/install.sh | GIRA_VERSION=v1.0.0 sh
uv tool upgrade gira-cli
python -m pip install --user --upgrade gira-cli
pipx upgrade gira-cli
brew update && brew upgrade gira
npm update -g @statpan/gira
bun update -g @statpan/gira

Upgrade with the same release channel used for installation. Developer source builds can be refreshed with go install github.com/StatPan/gira/cmd/gira@latest or GOBIN="${HOME}/.local/bin" go install ./cmd/gira, but those are not normal release-binary upgrade paths.

For uv, pip, and pipx installs, the gira-cli PyPI wrapper caches downloaded native binaries under GIRA_PYPI_CACHE_DIR when set, otherwise under ~/.cache/gira-cli/<version>. After upgrading, preview stale cache cleanup before deleting anything:

gira cache prune --dry-run
gira cache prune --apply

gira cache prune only removes direct child directories with stable semver release names older than the active gira version. It skips the active version, newer versions, malformed entries, files, symlinks, and any directory containing the current executable. Use --root PATH for a custom wrapper cache and --json for automation.

An upgrade replaces only the local gira binary or package wrapper. It must not mutate repository files or GitHub metadata. After upgrading, verify the command still resolves from the expected install location:

command -v gira
gira --help
gira version
gira upgrade
gira doctor --repo OWNER/REPO
gira audit readiness --repo OWNER/REPO

Binary Uninstall

Binary uninstall removes the local CLI from the machine. It does not detach a repository from Gira and does not delete GitHub labels, milestones, issues, or files.

For install-script or manual installs:

gira_path="${GIRA_INSTALL_DIR:+${GIRA_INSTALL_DIR}/gira}"
gira_path="${gira_path:-$(command -v gira)}"
rm "${gira_path}"

If you installed to a custom directory, set GIRA_INSTALL_DIR to that same directory or remove the path printed by command -v gira. For npm, bun, uv, pip, pipx, or Homebrew installs, uninstall with the same package manager used for installation.

Verification:

command -v gira

If command -v gira still prints a path, remove the remaining binary or package from that location.

Repository Detach

Repository detach is separate from binary uninstall. Detach means removing or disabling Gira-managed repository files and GitHub metadata for one repository while leaving the local gira binary installed.

Future command contract:

gira ops detach --repo OWNER/REPO --dry-run
gira ops detach --repo OWNER/REPO --dry-run --json
gira ops detach --repo OWNER/REPO --apply

Default behavior must be dry-run-first:

  • gira ops detach --repo OWNER/REPO --dry-run reports the Gira-managed files, labels, milestones, and bootstrap issues that would be removed, archived, or left in place.
  • gira ops detach --repo OWNER/REPO --dry-run --json emits the same plan in machine-readable form for review and automation.
  • gira ops detach --repo OWNER/REPO --apply performs only the actions shown by the dry-run plan and should require an explicit apply flag.
  • Destructive deletion is never default behavior. File deletion, GitHub issue closure, label deletion, and milestone deletion must be opt-in and visible in the dry-run plan before apply.
  • Detach must not delete user-authored project history by default. Prefer archiving, closing with an explanatory comment, or leaving unmanaged resources in place unless the operator explicitly requests cleanup.

Verification after detach:

gira status --repo OWNER/REPO --json
gira ops sync --repo OWNER/REPO --dry-run

status should make clear that the repository is not fully Gira-managed. sync --dry-run should show what would be recreated if the repository is adopted again.

Daily Happy Path

From a fresh shell, make sure the install directory is on PATH, then run Gira directly (no source checkout):

gira --help
gira ops sync --repo OWNER/REPO --dry-run
gira ops onboard verify --repo OWNER/REPO --stage steady-state
gira status --repo OWNER/REPO
gira ticket start --repo OWNER/REPO --ticket 12 --dry-run
gira ticket pr --repo OWNER/REPO --ticket 12 --dry-run
gira ticket status --repo OWNER/REPO --ticket 12

This is the canonical operator path for daily use.

Use --json for automation only; human output ends with a concise next step: line where Gira can suggest a safe continuation.

gira start and gira work start|pr|status remain compatibility aliases for users and scripts that already adopted the earlier issue-oriented wording. New documentation uses ticket because the intended mental model is Jira-style tickets mapped onto GitHub issues.

Advanced Adoption And Migration

Use the bootstrap and policy-mode commands when introducing Gira to a new or already-configured repository:

gira ops bootstrap --repo OWNER/REPO --template default --dry-run
gira ops bootstrap --repo OWNER/REPO --path /path/to/repo
gira ops sync --repo OWNER/REPO --dry-run --policy-mode adopt
gira ops sync --repo OWNER/REPO --dry-run --policy-mode merge
gira ops sync --repo OWNER/REPO --dry-run --policy-mode enforce
gira ops onboard verify --repo OWNER/REPO --stage init --json
gira status --repo OWNER/REPO --json

Package-manager wrappers such as npm, bun, uv, pip, pipx, or Homebrew may be used as distribution channels when they install or invoke the Go-built gira binary. They are not alternate product implementations.

For local development from this checkout:

GOBIN="$(mktemp -d)" go install ./cmd/gira
"${GOBIN}/gira" --help

To smoke-test the binary from outside the source checkout:

GOBIN="$(mktemp -d)" go install ./cmd/gira
(cd /tmp && "${GOBIN}/gira" --help)
(cd /tmp && "${GOBIN}/gira" version)
(cd /tmp && "${GOBIN}/gira" ops bootstrap --repo OWNER/REPO --template default --dry-run)
(cd /tmp && "${GOBIN}/gira" ops bootstrap --repo OWNER/REPO --path /path/to/repo --no-branch)
(cd /tmp && "${GOBIN}/gira" ops sync --repo OWNER/REPO --dry-run)
(cd /tmp && "${GOBIN}/gira" ops sync --repo OWNER/REPO --dry-run --bootstrap-issues)
(cd /tmp && "${GOBIN}/gira" status --repo OWNER/REPO --json)

Release Flow

Tagged Go releases are built by .github/workflows/release.yml. Pull requests and main pushes run validation builds only. Tags that start with v publish stable GitHub Release assets, then publish configured package-manager channels.

The workflow checks install.sh syntax, runs go test ./..., runs npm and PyPI wrapper tests, builds Linux, macOS, and Windows CLI archives with version metadata, generates checksums.txt, verifies the checksum manifest, and publishes those assets to the GitHub release. Published release assets are treated as immutable; rerun with a new patch tag instead of replacing an existing release. If NPM_TOKEN is configured, it publishes @statpan/gira. If PYPI_API_TOKEN is configured, it publishes gira-cli. If HOMEBREW_TAP_TOKEN is configured, it updates StatPan/homebrew-tap.

Maintainer flow:

git checkout main
git pull --ff-only origin main
$EDITOR CHANGELOG.md
git tag -a v1.0.0 -m "gira v1.0.0"
git push origin v1.0.0

Expected release assets:

checksums.txt
gira_VERSION_linux_amd64.tar.gz
gira_VERSION_linux_arm64.tar.gz
gira_VERSION_darwin_amd64.tar.gz
gira_VERSION_darwin_arm64.tar.gz
gira_VERSION_windows_amd64.zip

After publishing, smoke-test the official installer against the tag:

tmpdir="$(mktemp -d)"
GIRA_INSTALL_DIR="${tmpdir}" GIRA_VERSION=v1.0.0 sh install.sh
"${tmpdir}/gira" --help
"${tmpdir}/gira" version

The release policy and package-manager channel details are documented in docs/release-distribution.md. Developer experience conventions for first-run onboarding, dry-run/apply output, JSON, recovery, and the issue-to-PR loop are documented in docs/dx.md.

The GitHub-native Product OS schema for future Projects v2 planning, roadmap date semantics, permission/secret model, and dry-run-first automation is documented in docs/product-os-schema.md. The execution roadmap for that phase is tracked in docs/product-os-roadmap.md. The Jira-vs-Gira operating boundary, work decomposition contract, and assistant/dev-agent split are documented in docs/jira-gira-operating-boundary.md. Goal-level autonomy for long-running agent work is documented in docs/goal-operating-model.md. Jira-primary provider mode and workflow safety are documented in docs/jira-primary-provider.md. Closure Funnel stats are documented in docs/closure-funnel-stats.md. Agent delegation lanes, approval policy, and Delegation Quality metrics are documented in docs/agent-delegation-lanes.md. The workspace backlog layer is documented in docs/workspace.md, business-group multi-repo workflow design is documented in docs/business-group-workflows.md, and the older portfolio intake compatibility layer is documented in docs/portfolio-intake.md. The vendor-neutral dashboard/export boundary for Notion and other consumers is documented in docs/dashboard-consumer-contract.md, and the first concrete export bundle layout is documented in docs/dashboard-export-artifacts.md. The hosted control-plane product boundary and service roadmap are documented in docs/hosted-control-plane-roadmap.md. The MVP CRUD support contract is documented in docs/crud-capability-matrix.md. Adoption on pre-configured repositories is documented in docs/adoption-migration-playbook.md.

This repository dogfoods Gira for its own work. The active operating loop, sprint commands, and maintainer handoff are documented in docs/dogfood.md.

Explicit non-goals for v1: full GitHub Projects v2 view automation, LLM PRD-to-issue decomposition, Web UI/TUI, chat-bot integration, background Jira sync, full bidirectional Jira sync, and Jira workflow mutation. Gira may keep explicit migration helpers, but the v1 source of truth is the GitHub execution loop unless a repo explicitly enables Jira-primary planning/status.

Packages

 
 
 

Contributors

Languages