Requirements
Heckle requires Python 3.11 or newer. The Python package has no runtime Python dependencies. generate requires either OpenTofu or Terraform 1.8 or newer and below 2.0. inventory, coverage and compatibility do not require either CLI.
Install
Install Heckle from your preferred channel. The Python package requires Python 3.11 or newer. DEB, RPM and AppImage releases are intended to provide the same heckle CLI.
PipX / Pip
pipx is the recommended Python installation method because it keeps Heckle isolated from system Python packages.
pipx install heckle
heckle --versionInside an existing Python virtual environment, you can instead use:
python -m pip install heckle
heckle --versionUbuntu / Debian apt repository
sudo mkdir -p /usr/share/keyrings
curl -fsSL https://mig5.net/static/mig5.asc | sudo gpg --dearmor -o /usr/share/keyrings/mig5.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/mig5.gpg] https://apt.mig5.net $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/mig5.list
sudo apt update
sudo apt install heckle
heckle --versionFedora / RPM-style repository
sudo rpm --import https://mig5.net/static/mig5.asc
sudo tee /etc/yum.repos.d/mig5.repo > /dev/null << 'EOF'
[mig5]
name=mig5 Repository
baseurl=https://rpm.mig5.net/$releasever/rpm/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mig5.net/static/mig5.asc
EOF
sudo dnf upgrade --refresh
sudo dnf install heckle
heckle --versionAppImage
Download the Heckle.AppImage from the release page, rename it to heckle if desired, and make it executable:
chmod +x heckle
./heckle --versionThe AppImage bundles Heckle and Python. It does not bundle Terraform or OpenTofu, so generate still needs one of those CLIs available separately.
Development checkout
Clone the git repository, then run:
poetry install
poetry run heckle --helpChoose Terraform or OpenTofu
OpenTofu is the default. Heckle uses the same selected executable for provider hydration, formatting, validation and adoption rehearsal.
# Default: OpenTofu
heckle generate github --org example
# Terraform
heckle generate github --org example --tf terraform
# Explicit path
heckle generate github --org example --tf /opt/opentofu/bin/tofuThe neutral environment override is HECKLE_TF_BIN.
Credentials and forge hosts
Heckle does not accept tokens on the command line and does not render them into provider configuration.
| Forge | Token environment | Host environment | Default host |
|---|---|---|---|
| GitHub | GITHUB_TOKEN or GH_TOKEN | GITHUB_BASE_URL | https://api.github.com |
| GitLab | GITLAB_TOKEN | GITLAB_BASE_URL | https://gitlab.com |
| Gitea | GITEA_TOKEN | GITEA_BASE_URL | Required |
| Forgejo | FORGEJO_API_TOKEN or FORGEJO_TOKEN | FORGEJO_HOST | Required |
Use --url to override the host. GitHub Enterprise Server expects its API base ending in /api/v3. GitLab, Gitea and Forgejo accept the site root or their usual API root; Heckle normalises it. HTTPS verification remains enabled. Use --ca-file for a private CA. --allow-http is an explicit local-test opt-in.
Quickstart
Organization or group
export GITHUB_TOKEN='...'
heckle generate github --org example --out ./github-iac
export GITLAB_TOKEN='...'
heckle generate gitlab --group example/platform --out ./gitlab-iac
export GITEA_TOKEN='...'
heckle generate gitea --org example --url https://git.example.org
export FORGEJO_API_TOKEN='...'
heckle generate forgejo --org example --url https://code.example.orgPersonal account
heckle generate github --me
heckle generate gitlab --user alice
heckle generate gitea --me --url https://git.example.org
heckle generate forgejo --user alice --url https://code.example.orgPersonal mode includes repositories/projects owned by the selected personal namespace. It does not turn collaborations in other namespaces into owned resources and does not create or manage the login account itself.
Namespace selectors
Choose exactly one selector for generate or inventory:
| Selector | Where | Meaning |
|---|---|---|
| --org NAME | GitHub, Gitea, Forgejo | Organization namespace. |
| --group PATH | GitLab | Group path, including nested subgroups. |
| --user NAME | All four | Named personal account; include only repositories/projects owned by that namespace. |
| --me | All four | Resolve the authenticated account and use its personal namespace. |
Commands
generate
Discovers or replays inventory, hydrates provider import configuration, renders HCL, validates it unless disabled, and rehearses the adoption path. It publishes a standalone project only after its checks pass.
heckle generate FORGE SELECTOR [options]inventory
Saves a private, versioned discovery snapshot and coverage report without generating HCL. Useful for checking token visibility and optional API gaps first.
heckle inventory FORGE SELECTOR --out ./snapshotcoverage
Reads a saved inventory or generated project's coverage report without network access.
heckle coverage ./snapshot
heckle coverage ./snapshot --jsoncompatibility
Shows the exact provider versions audited by this Heckle release and the provider behaviours recorded for them.
heckle compatibility
heckle compatibility forgejo
heckle compatibility --jsonCommon generate / inventory options
| Option | Meaning |
|---|---|
| --url URL | Forge base URL. Required for Gitea/Forgejo unless their host environment variable is set. |
| --out PATH | Output directory. Without it, Heckle chooses a forge/scope-based directory in the current working directory. |
| --force | Replace only an output still marked as a disposable Heckle generation; never overwrite an initialized/adopted project. |
| --workers N | Bounded repository discovery concurrency. Range 1–16; default 4. |
| --timeout SECONDS | HTTP request timeout; default 60. |
| --retries N | HTTP retry count; default 4. |
| --ca-file PATH | Additional trusted CA bundle while keeping TLS verification enabled. |
| --allow-http | Permit plaintext HTTP. Intended only for trusted local test instances. |
| --provider-version X.Y.Z | Override the exact audited provider pin. Experimental unless this Heckle release has audited that version. |
| --allow-untested-provider | Explicitly permit an unaudited provider override; compatibility knowledge may be incomplete. |
Generate-only options
| Option | Meaning |
|---|---|
| --from-inventory PATH | Replay discovery from a saved snapshot. Provider hydration still contacts the forge. |
| --allow-partial | Permit explicitly reported discovery permission/API gaps instead of refusing generation. |
| --keep-inventory | Keep the private discovery snapshot under .generation/inventory/. |
| --keep-workdir | On generation failure, retain the private temporary build workspace and print commands for diagnostics. |
| --no-validate | Skip final validation. Provider hydration and formatting still happen. |
| --allow-destroy | Do not generate Heckle's default prevent_destroy lifecycle guards. |
| --split-teams | GitHub only: emit one data file per team. |
| --state-root PATH | Read an explicitly identified existing Heckle project's state to omit already-adopted addresses and generate state moves when required. |
| --tf PATH | Terraform or OpenTofu executable. Defaults to HECKLE_TF_BIN, then tofu. |
Environment variables
| Variable | Purpose |
|---|---|
| HECKLE_TF_BIN | Neutral Terraform/OpenTofu executable override. |
| TF_VAR_* | Normal Terraform/OpenTofu variable input mechanism for generated projects. |
Forge token and host variables are listed in Credentials and forge hosts.
Generated output
provider.tf
versions.tf
modules.tf
imports.tf # when declarative import is accepted
adopt.sh # otherwise, one-time state-only adoption helper
variables.tf # when private input is required
modules/
.generation/report.json
README.mdProvider-specific data files are split by organization/group/project/repository. After adoption, remove the .heckle-generated marker and maintain the ordinary HCL directly. Do not regenerate over a maintained project.