Skill: justinburdett/flyio-cli (version 1.0.3)

--- name: flyio-cli description: "Use the Fly.io flyctl CLI for deploying and operating apps on Fly.io. Default to read-only diagnostics (status/logs/config/releases). Only perform state-changing operations (deploys, SSH exec, secrets, scaling, machines, volumes, Postgres changes) with explicit user approval. Use when asked to deploy to Fly.io, debug fly deploy/build/runtime failures, set up GitHub Actions deploys/previews, or safely manage Fly apps and Postgres." --- # Fly.io (flyctl) CLI Operate Fly.io apps safely and repeatably with `flyctl`. ## Defaults / safety - Prefer **read-only** commands first: `fly status`, `fly logs`, `fly config show`, `fly releases`, `fly secrets list`. - **Do not edit/modify Fly.io apps, machines, secrets, volumes, or databases without your human’s explicit approval.** - Read-only actions are OK without approval. - Destructive actions (destroy/drop) always require explicit approval. - When debugging builds, capture the exact error output and determine whether it’s a: - build/packaging issue (Dockerfile, Gemfile.lock platforms, assets precompile) - runtime issue (secrets, DB, migrations) - platform issue (regions, machines, health checks) ## Quick start (typical deploy) From the app repo directory: 1) Confirm which app you’re targeting - `fly app list` - `fly status -a <app>` - Check `fly.toml` for `app = "..."` 2) Validate / inspect (read-only) - `fly status -a <app>` - `fly logs -a <app>` - `fly config show -a <app>` (Deploys are in **High-risk operations** below and require explicit user approval.) ## Debugging deploy/build failures ### Common checks - `fly deploy --verbose` (more build logs) - If using Dockerfile builds: verify Dockerfile Ruby/version and Gemfile.lock platforms match your builder OS/arch. ### Rails + Docker + native gems (nokogiri, pg, etc.) Symptoms: Bundler can’t find a platform gem like `nokogiri-…-x86_64-linux` during build. Fix pattern: - Ensure `Gemfile.lock` includes the Linux platform used by Fly’s builder (usually `x86_64-linux`). - Example: `bundle lock --add-platform x86_64-linux` - Ensure Dockerfile’s Ruby version matches `.ruby-version`. (See `references/rails-docker-builds.md`.) ## Logs & config (read-only) - Stream logs: - `fly logs -a <app>` - Show config: - `fly config show -a <app>` - List secrets (names only): - `fly secrets list -a <app>` ## High-risk operations (ask first) These commands can execute arbitrary code on servers or mutate production state. Only run them when the user explicitly asks you to. - Deploy: - `fly deploy` / `fly deploy --remote-only` - SSH exec / console: - `fly ssh console -a <app> -C "<command>"` - Secrets changes: - `fly secrets set -a <app> KEY=value` See `references/safety.md`. ## Fly Postgres basics ### Identify the Postgres app - `fly postgres list` ### Attach Postgres to an app - `fly postgres attach <pg-app> -a <app>` ### Create a database inside the cluster - `fly postgres db create <db_name> -a <pg-app>` - `fly postgres db list -a <pg-app>` ### Connect (psql) - `fly postgres connect -a <pg-app>` ## GitHub Actions deploys / previews - For production CD: use Fly’s GitHub Action (`superfly/flyctl-actions/setup-flyctl`) and run `flyctl deploy`. - For PR previews: - Prefer one **preview app per PR** and one **database per PR** inside a shared Fly Postgres cluster. - Automate create/deploy/comment on PR; destroy on close. (See `references/github-actions.md`.) ## Bundled resources - `references/safety.md`: safety rules (read-only by default; ask before mutating state). - `references/rails-docker-builds.md`: Rails/Docker/Fly build failure patterns + fixes. - `references/github-actions.md`: Fly deploy + preview workflows. - `scripts/fly_app_from_toml.sh`: tiny helper to print the Fly app name from fly.toml (shell-only; no ruby).

path: references/safety.md
content: # Safety policy

- Read-only Fly.io actions are allowed without asking.
- Any action that edits/modifies Fly.io state requires your human’s explicit approval.
  - Examples: deploys, scaling, secrets set/unset, volume/db create/drop, app destroy.


path: references/github-actions.md
content: # Fly + GitHub Actions

## Production deploy (simple)

Workflow outline:
- checkout
- setup flyctl
- `flyctl deploy --remote-only`

Secrets:
- `FLY_API_TOKEN`

## PR previews (recommended architecture)

Goal: per-PR URL + per-PR DB.

Pattern:
- preview app per PR: `myapp-pr-<n>`
- database per PR inside shared Fly Postgres cluster: `myapp_pr_<n>`

Per PR update:
1) create app if missing
2) create db if missing
3) attach postgres to preview app
4) set env/secrets (DATABASE_URL points at per-PR db)
5) deploy
6) comment URL on PR

On PR close:
- destroy preview app
- drop PR database

Notes:
- Be conservative with secrets (use dummy/test where possible).
- Avoid destructive actions without explicit confirmation when running manually.


path: references/rails-docker-builds.md
content: # Rails + Docker builds on Fly (common failure patterns)

## Symptom: Bundler can't find platform gem (e.g., nokogiri)

Example:
- `Could not find nokogiri-...-x86_64-linux in locally installed gems`

Cause:
- `Gemfile.lock` was generated on macOS only (darwin platforms), but Fly builds on Linux.

Fix:
- Add the target platform(s) to the lockfile and commit:
  - `bundle lock --add-platform x86_64-linux`
  - (optional) `bundle lock --add-platform aarch64-linux`

## Symptom: build uses wrong Ruby version

Clue:
- stacktrace paths like `/ruby/3.1.0/...` when app expects Ruby 3.2.x

Fix:
- Ensure Dockerfile `ARG RUBY_VERSION=...` matches `.ruby-version`.

## Symptom: bootsnap precompile fails in Docker build

Clue:
- failure during `bundle exec bootsnap precompile ...`

Fix checklist:
- confirm gems are installed for the platform
- confirm lockfile platforms include Linux
- run `bundle install` in the builder stage after any lockfile surgery

## Tip: prefer remote builder when local env differs

- `fly deploy --remote-only`


path: scripts/fly_app_from_toml.sh
content: #!/usr/bin/env bash
set -euo pipefail

# Print the Fly app name from fly.toml (if present)
# Usage: scripts/fly_app_from_toml.sh [path]

path="${1:-fly.toml}"

if [ ! -f "$path" ]; then
  echo "fly.toml not found: $path" >&2
  exit 1
fi

# naive parse: app = "name" OR app = 'name'
# Avoid using an interpreter (ruby/python) here; keep it as a simple shell parser.
# This assumes a single-line definition like: app = "my-app"
app=$(awk -F= '/^[[:space:]]*app[[:space:]]*=/{v=$2; gsub(/^[[:space:]]*/,"",v); gsub(/[[:space:]]*$/,"",v); gsub(/^"|"$/,"",v); gsub(/^\x27|\x27$/,"",v); print v; exit}' "$path")

if [ -z "$app" ]; then
  echo "Could not find app = \"...\" in $path" >&2
  exit 1
fi

echo "$app"


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)