GitHub - preloopdev/loopt: GitHub Actions workflows in any language

GitHub

3 min read Original article ↗

Write GitHub Actions workflows in any language. TypeScript, Python, Go, and Rust ship as first-party languages, and custom languages plug in through the plugin protocol. Loopt generates standard .github/workflows/*.yml from that source, and can import existing workflow YAML into editable code.

Generated workflow files start with:

# Generated by loopt. Edit the source under .loopt/workflows and run loopt gen.

Edit .loopt/workflows/*, not the generated YAML.

Install

Prebuilt binaries, no Cargo required:

curl -fsSL https://raw.githubusercontent.com/preloopdev/loopt/main/install.sh | sh

The script installs to ~/.local/bin and verifies the release checksum when one is published. Set LOOPT_INSTALL_DIR to change the destination, or LOOPT_VERSION=v0.1.1 to pin a release. Prebuilt binaries are published for macOS arm64 and Linux x86_64.

The language you author in must be installed when generating: Node.js 26+, Python 3, Go, or Cargo/Rust.

Start a project

Writes a starter workflow as TypeScript source in .loopt/workflows/ci.ts, generates .github/workflows/ci.yml from it, and prints what to do next. The starter follows your project files:

Found Steps
package.json npm ci (or npm install without a lockfile), npm test
Cargo.toml cargo test
go.mod go test ./...
pyproject.toml, requirements.txt, setup.py pip install, python -m pytest
none of these a placeholder step to replace

Every starter uses a read-only token (contents: read), pins actions/checkout to a commit without persisting credentials, cancels superseded runs, and lints clean. Edit it freely; it is only a starting point.

loopt init --language python --name build --template node

--language is typescript (default), python, go, or rust. --name sets the file name (default ci). --template is auto (default), generic, node, rust, go, or python. init never overwrites an existing workflow; use loopt import for those.

Use

# Import existing workflows into .loopt/workflows
loopt import --language typescript

# Generate .github/workflows from the source
loopt gen

# Fail if the committed YAML no longer matches the committed source
loopt gen --check

loopt import leaves the original YAML untouched. loopt gen refuses to overwrite a workflow edited outside Loopt unless you pass --force. Composite actions (action.yml/action.yaml outside .github/workflows/) import as action metadata the same way.

See Authoring workflows for composite-action details, safe run templates, and the full source↔YAML sync semantics.

Review

Runs native correctness and security checks on generated workflows — optionally with shellcheck on run: scripts. loopt gen runs the same review automatically.

See Lint and security review for the --persona/--context/--shellcheck flags and severity mapping.

Everything else

Topic Doc
Typed, commit-pinned action imports (loopt actions …) Action bindings
Names-only secret inventory (loopt secrets sync) Secrets
uses: pin enforcement (loopt lock) Workflow lockfile
Out-of-tree plugin protocol and built-in languages Languages and plugins
@preloopdev/sdk (npm) and loopt-sdk (crates.io) Authoring SDKs
SDK call reference (all four languages) SDK API
Releases, registry credentials, version bumps Publishing
.loopt/ layout Layout

Test

The full external-fixture corpus test is opt-in:

PRELOOP_FIXTURES=/path/to/fixtures cargo test --test corpus -- --ignored

License

MIT.