Skill: matt-dean-git/satgate (version 0.1.2)

--- name: satgate description: Manage your API's economic firewall from the terminal. Mint tokens, track spend, revoke agents, enforce budgets. The server-side counterpart to lnget. homepage: https://satgate.io --- # SatGate CLI SatGate CLI manages API access, budgets, and monetization for the agent economy. Use it when you need to control what agents can access and how much they can spend. **They're the wallet. We're the register.** If the agent needs to *pay* for L402 APIs, install `lnget` from Lightning Labs. SatGate is for the *server side* — enforcement, attribution, and governance. ## Setup Run `scripts/configure.sh` if no `~/.satgate/config.yaml` exists. Or set environment variables: ```bash # For self-hosted gateway export SATGATE_GATEWAY=http://localhost:9090 export SATGATE_ADMIN_TOKEN=sgk_your_token # For SatGate Cloud export SATGATE_SURFACE=cloud export SATGATE_GATEWAY=https://satgate-gateway.fly.dev export SATGATE_BEARER_TOKEN=sg_your_api_key export SATGATE_TENANT=your-tenant-slug ``` Always run `satgate status` first to confirm you're targeting the right gateway. ## Safety Rules 1. **Check target first** — run `satgate status` before any operation to verify gateway URL and surface. 2. **Use `--dry-run`** on destructive operations (`revoke`, `mint` with large budgets). 3. **Never use `--yes`** without explicit user approval. 4. **Revocation is irreversible** — always confirm token name before revoking. ## Commands ### Check gateway health ```bash satgate status # Full status (version, surface, uptime) satgate ping # Quick liveness check (exit 0/1) ``` ### Mint a token for a new agent ```bash # Interactive (prompts for all fields) satgate mint # Non-interactive satgate mint --agent "my-bot" --budget 500 --expiry 30d --routes "/api/openai/*" # With parent (delegation under existing token) satgate mint --agent "child-bot" --budget 100 --parent "parent-token-id" # Preview without executing satgate mint --agent "my-bot" --budget 500 --dry-run ``` ### Check agent spend ```bash satgate spend # Org-wide cost center rollups satgate spend --agent "cs-bot" # Per-agent breakdown satgate spend --period 7d # Time-scoped ``` ### List and inspect tokens ```bash satgate tokens # All tokens with status, spend, budget satgate token <id> # Detail: scope, delegation chain, spend ``` ### Revoke a compromised agent ```bash satgate revoke <token-id> # Interactive confirmation satgate revoke <token-id> --dry-run # Preview only ``` ### View security threats ```bash satgate report threats # Blocked requests, anomalies ``` ### Check policy modes ```bash satgate mode # Current mode per route (read-only) ``` ## Common Workflows **"New agent needs API access"** → `satgate mint --agent "agent-name" --budget 500 --routes "/api/openai/*"` **"How much are agents spending?"** → `satgate spend` **"Agent is misbehaving"** → `satgate revoke <token-id>` **"Board wants AI spend report"** → `satgate spend --json > report.json` **"Is the gateway healthy?"** → `satgate ping` ## Output Formats All commands support `--json` for machine-readable output: ```bash satgate tokens --json | jq '.[] | select(.status == "active")' satgate spend --json > monthly-report.json ``` ## Pairing with lnget SatGate (server-side) + lnget (client-side) = complete agent commerce stack. - **lnget**: Agents pay for L402-gated APIs automatically - **SatGate CLI**: Operators mint tokens, set budgets, revoke access, view spend An agent using `lnget` hits your SatGate-protected endpoint → SatGate enforces the budget and attributes the cost → you see it in `satgate spend`. Install lnget: `claude plugin marketplace add lightninglabs/lightning-agent-tools`

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

# SatGate CLI Configuration
# Interactive setup for ~/.satgate/config.yaml

CONFIG_DIR="${HOME}/.satgate"
CONFIG_FILE="${CONFIG_DIR}/config.yaml"

echo "⚡ SatGate CLI Configuration"
echo "───────────────────────────"
echo ""

# Check if config already exists
if [ -f "$CONFIG_FILE" ]; then
  echo "  Existing config found at ${CONFIG_FILE}"
  read -p "  Overwrite? [y/N]: " OVERWRITE
  if [ "${OVERWRITE,,}" != "y" ]; then
    echo "  Keeping existing config."
    exit 0
  fi
fi

# Choose surface
echo ""
echo "  Where is your SatGate gateway?"
echo "    1) Self-hosted (local or remote gateway)"
echo "    2) SatGate Cloud (cloud.satgate.io)"
echo ""
read -p "  Choice [1/2]: " SURFACE_CHOICE

if [ "$SURFACE_CHOICE" = "2" ]; then
  SURFACE="cloud"
  GATEWAY="https://cloud.satgate.io"

  echo ""
  echo "  SatGate Cloud requires a session token."
  echo "  Get one by signing in at https://cloud.satgate.io"
  echo "  or via magic link: satgate auth login (coming soon)"
  echo ""
  read -p "  Session token: " SESSION_TOKEN

  read -p "  Tenant slug (press Enter for default): " TENANT
  TENANT="${TENANT:-default}"

  # Write config
  mkdir -p "$CONFIG_DIR"
  cat > "$CONFIG_FILE" <<EOF
# SatGate CLI Configuration
# Generated by configure.sh

surface: cloud
gateway: ${GATEWAY}
session_token: ${SESSION_TOKEN}
tenant: ${TENANT}
format: table
EOF

else
  SURFACE="gateway"

  echo ""
  read -p "  Gateway URL [http://localhost:9090]: " GATEWAY
  GATEWAY="${GATEWAY:-http://localhost:9090}"

  read -p "  Admin token: " ADMIN_TOKEN

  # Write config
  mkdir -p "$CONFIG_DIR"
  cat > "$CONFIG_FILE" <<EOF
# SatGate CLI Configuration
# Generated by configure.sh

surface: gateway
gateway: ${GATEWAY}
admin_token: ${ADMIN_TOKEN}
format: table
EOF

fi

chmod 600 "$CONFIG_FILE"

echo ""
echo "✓ Config written to ${CONFIG_FILE}"
echo ""

# Test connection
echo "  Testing connection..."
if satgate ping 2>/dev/null; then
  echo ""
  echo "  🎉 You're connected! Try: satgate status"
else
  echo ""
  echo "  ⚠️  Could not reach gateway. Check your config:"
  echo "     ${CONFIG_FILE}"
fi


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

# SatGate CLI Health Check
# Validates that the CLI is installed and can reach the gateway.

echo "⚡ SatGate CLI Health Check"
echo "───────────────────────────"

# Check binary
if ! command -v satgate &>/dev/null; then
  echo "❌ satgate binary not found in PATH"
  echo "   Run: scripts/install.sh"
  exit 1
fi
echo "✓ Binary: $(which satgate)"
satgate version

# Check config
CONFIG="${HOME}/.satgate/config.yaml"
if [ -f "$CONFIG" ]; then
  echo "✓ Config: ${CONFIG}"
else
  echo "⚠️  No config file at ${CONFIG}"
  echo "   Using environment variables or defaults"
fi

# Check connection
echo ""
echo "Testing gateway connection..."
if satgate ping; then
  echo ""
  satgate status
else
  echo ""
  echo "❌ Cannot reach gateway"
  echo "   Run: scripts/configure.sh"
  exit 1
fi


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

# SatGate CLI Installer
# Downloads the correct binary for your platform and verifies SHA256 checksum.

REPO="SatGate-io/satgate-cli"
BINARY="satgate"
INSTALL_DIR="${SATGATE_INSTALL_DIR:-/usr/local/bin}"

# Detect platform
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$ARCH" in
  x86_64|amd64) ARCH="amd64" ;;
  arm64|aarch64) ARCH="arm64" ;;
  *) echo "❌ Unsupported architecture: $ARCH"; exit 1 ;;
esac

case "$OS" in
  linux|darwin) ;;
  *) echo "❌ Unsupported OS: $OS"; exit 1 ;;
esac

PLATFORM="${OS}-${ARCH}"
echo "⚡ Installing SatGate CLI for ${PLATFORM}..."

# Get latest release tag
if command -v gh &>/dev/null; then
  VERSION=$(gh release view --repo "$REPO" --json tagName -q .tagName 2>/dev/null || echo "latest")
else
  VERSION="latest"
fi

if [ "$VERSION" = "latest" ]; then
  BASE_URL="https://github.com/${REPO}/releases/latest/download"
else
  BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
fi

# Create temp directory
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT

# Download binary and checksums
echo "  Downloading ${BINARY}-${PLATFORM}..."
curl -fsSL "${BASE_URL}/${BINARY}-${PLATFORM}" -o "${TMPDIR}/${BINARY}" || {
  echo "❌ Download failed. No release binaries found."
  echo "   Build from source: git clone https://github.com/${REPO} && cd satgate-cli && make build"
  exit 1
}

echo "  Downloading SHA256SUMS..."
curl -fsSL "${BASE_URL}/SHA256SUMS" -o "${TMPDIR}/SHA256SUMS" || {
  echo "⚠️  Checksums not available — skipping verification."
  echo "   Consider building from source for verified integrity."
}

# Verify checksum
if [ -f "${TMPDIR}/SHA256SUMS" ]; then
  echo "  Verifying checksum..."
  cd "$TMPDIR"
  EXPECTED=$(grep "${BINARY}-${PLATFORM}" SHA256SUMS | awk '{print $1}')
  if [ -n "$EXPECTED" ]; then
    if command -v sha256sum &>/dev/null; then
      ACTUAL=$(sha256sum "$BINARY" | awk '{print $1}')
    elif command -v shasum &>/dev/null; then
      ACTUAL=$(shasum -a 256 "$BINARY" | awk '{print $1}')
    else
      echo "⚠️  No sha256sum or shasum found — skipping verification."
      ACTUAL="$EXPECTED"
    fi

    if [ "$EXPECTED" != "$ACTUAL" ]; then
      echo "❌ Checksum verification FAILED!"
      echo "   Expected: $EXPECTED"
      echo "   Actual:   $ACTUAL"
      echo "   The binary may have been tampered with. Aborting."
      exit 1
    fi
    echo "  ✓ Checksum verified."
  else
    echo "⚠️  Binary not found in SHA256SUMS — skipping verification."
  fi
  cd - >/dev/null
fi

# Install
chmod +x "${TMPDIR}/${BINARY}"

mkdir -p "$INSTALL_DIR" 2>/dev/null || true
if [ -w "$INSTALL_DIR" ]; then
  mv "${TMPDIR}/${BINARY}" "${INSTALL_DIR}/${BINARY}"
else
  echo "  Installing to ${INSTALL_DIR} (requires sudo)..."
  sudo mv "${TMPDIR}/${BINARY}" "${INSTALL_DIR}/${BINARY}"
fi

echo ""
echo "✓ SatGate CLI installed to ${INSTALL_DIR}/${BINARY}"
echo ""
echo "  Next steps:"
echo "    satgate status              # Check gateway connection"
echo "    satgate --help              # See all commands"
echo "    scripts/configure.sh        # Interactive setup"
echo ""
$INSTALL_DIR/$BINARY version


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