diff --git a/README.md b/README.md index 8e68a22..fe08351 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,14 @@ Optionally, install it to your PATH: cargo install --path . ``` +### Agent Skill + +This repository includes an agent skill for using the CLI safely: + +```bash +npx skills add jsvana/hamalert-cli +``` + ## Configuration Run the managed login flow: diff --git a/skills/hamalert-cli/SKILL.md b/skills/hamalert-cli/SKILL.md new file mode 100644 index 0000000..990fee9 --- /dev/null +++ b/skills/hamalert-cli/SKILL.md @@ -0,0 +1,59 @@ +--- +name: hamalert-cli +description: Use the hamalert-cli command-line tool to manage HamAlert.org triggers, credentials, backups, restores, imports, bulk deletion, and trigger profiles. Use when a user asks an agent to configure HamAlert credentials, add callsign alerts, import Ham2K PoLo or local callsign files, back up or restore triggers, inspect trigger/profile status, switch profiles, manage permanent triggers, or plan safe hamalert-cli operations. +--- + +# HamAlert CLI + +## Overview + +Use this skill to operate `hamalert-cli` safely on behalf of a user. The CLI talks to the live HamAlert.org account configured on the machine, so treat credential handling and destructive trigger operations carefully. + +## Start Here + +1. Determine whether the user wants a read-only check, a dry-run plan, or a live modification. +2. Run `scripts/local-check.sh` to identify how to invoke the CLI in the current environment. +3. Read `references/safety.md` before any command that can modify HamAlert state. +4. Read the task-specific reference: + - Command syntax: `references/commands.md` + - Common workflows: `references/workflows.md` + - File and JSON formats: `references/data-formats.md` + - Failures and environment issues: `references/troubleshooting.md` + +## Invocation + +Prefer an installed binary: + +```bash +hamalert-cli +``` + +When working from this repository and no binary is installed, use: + +```bash +cargo run -- +``` + +For generated help, run `scripts/help-snapshot.sh`. + +## Operating Rules + +- Never print passwords, ask for passwords in chat, or write secrets into files unless the user explicitly instructs a local config fallback. +- Prefer `auth login --password-stdin` or `auth login --password-env`; avoid `--password` except when the user explicitly accepts process-history exposure. +- Ask for explicit confirmation before live modifications unless the user already gave clear approval. +- Prefer dry-run flows before live changes. Note that many dry-runs still log in and fetch live data. +- Back up triggers before destructive operations when the command does not already create an auto-backup. +- Do not assume README examples are complete. Check `hamalert-cli --help` or `scripts/help-snapshot.sh` when exact syntax matters. + +## Quick Tasks + +Read `references/workflows.md` for full recipes. Common starting points: + +```bash +hamalert-cli auth status +hamalert-cli backup +hamalert-cli add-trigger --callsign W1AW --comment "W1AW spotted" --actions app +hamalert-cli import-file --file callsigns.txt --comment "Local imports" --actions app --dry-run +hamalert-cli profile status +hamalert-cli profile switch portable +``` diff --git a/skills/hamalert-cli/agents/openai.yaml b/skills/hamalert-cli/agents/openai.yaml new file mode 100644 index 0000000..0f538f4 --- /dev/null +++ b/skills/hamalert-cli/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "HamAlert CLI" + short_description: "Operate HamAlert triggers safely" + default_prompt: "Use $hamalert-cli to manage HamAlert triggers safely." diff --git a/skills/hamalert-cli/references/commands.md b/skills/hamalert-cli/references/commands.md new file mode 100644 index 0000000..21f196b --- /dev/null +++ b/skills/hamalert-cli/references/commands.md @@ -0,0 +1,109 @@ +# Command Reference + +Use `hamalert-cli --help` for exact syntax. If no installed binary is available and the current directory is this repository, use `cargo run -- `. + +## Global + +```bash +hamalert-cli [--config-file ] +``` + +`--config-file` points at a TOML config file. Without it, the CLI uses the platform config directory, normally `~/.config/hamalert/config.toml`. + +## auth + +```bash +hamalert-cli auth login [--username ] [--password-stdin | --password-env | --password ] +hamalert-cli auth status +hamalert-cli auth logout +``` + +- `auth login` validates credentials and stores the password in the OS keyring when possible. +- `auth status` is read-only for local files and prints credential source/status without password values, but it does attempt a live HamAlert login when credentials resolve. +- `auth logout` removes the stored local password and keeps the username. + +Prefer `--password-stdin` or `--password-env` for automated use. + +## add-trigger + +```bash +hamalert-cli add-trigger --callsign W1AW --comment "W1AW spotted" --actions app +hamalert-cli add-trigger --callsign W1AW --callsign K3LR --comment "Monitor activity" --actions app telnet +hamalert-cli add-trigger --callsign VP8LP --comment "FT8 only" --actions app --mode ft8 +``` + +`add-trigger` modifies live HamAlert state. Multiple `--callsign` values are sent as one trigger by joining callsigns. The default separator is comma-space. Use `--compact` for comma-only or `--one-per-line` for newline-separated callsigns. + +Actions: `url`, `app`, `threema`, `telnet`. +Modes: `cw`, `ft8`, `ssb`. + +## import-polo-notes + +```bash +hamalert-cli import-polo-notes --url --comment "PoLo imports" --actions app --dry-run +hamalert-cli import-polo-notes --url --comment "PoLo imports" --actions app +``` + +Imports callsigns from a Ham2K PoLo notes URL. Use `--dry-run` first. Dry-run still requires configured credentials because the CLI logs in before running non-auth commands. + +## import-file + +```bash +hamalert-cli import-file --file callsigns.txt --comment "Local imports" --actions app --dry-run +hamalert-cli import-file --file callsigns.txt --comment "Local imports" --actions app +``` + +Imports callsigns from a local text file. Use `--dry-run` first. See `data-formats.md` for file parsing rules. + +## backup + +```bash +hamalert-cli backup +hamalert-cli backup --output my-triggers.json +``` + +Fetches all live triggers and writes JSON. Without `--output`, the CLI writes to the HamAlert backup directory under the platform data directory, normally `~/.local/share/hamalert/backups/`. + +## restore + +```bash +hamalert-cli restore --input hamalert-backup-2026-07-08.json +hamalert-cli restore --input hamalert-backup-2026-07-08.json --no-dry-run +``` + +Dry-run is the default and previews replacing all existing triggers. `--no-dry-run` deletes existing triggers, creates an automatic backup first, and recreates triggers from the backup file. + +## edit + +```bash +hamalert-cli edit +``` + +Fetches triggers, asks the user to choose one, opens editable JSON in `$EDITOR` or `vi`, validates JSON, and updates the live trigger if changed. + +## bulk-delete + +```bash +hamalert-cli bulk-delete --dry-run +hamalert-cli bulk-delete +``` + +Interactive TUI. All triggers start selected, meaning kept. Unchecked triggers are deleted. `--dry-run` still fetches live triggers and asks for a selection before previewing. + +## profile + +```bash +hamalert-cli profile list +hamalert-cli profile show +hamalert-cli profile status +hamalert-cli profile save +hamalert-cli profile save --from-backup +hamalert-cli profile switch +hamalert-cli profile switch --no-dry-run +hamalert-cli profile delete +hamalert-cli profile set-permanent +hamalert-cli profile set-permanent --from-backup +hamalert-cli profile show-permanent +``` + +Profiles manage saved trigger sets for different locations or activities. `profile switch` is dry-run by default; `--no-dry-run` replaces non-permanent live triggers with the target profile and creates an automatic backup first. diff --git a/skills/hamalert-cli/references/data-formats.md b/skills/hamalert-cli/references/data-formats.md new file mode 100644 index 0000000..dafa646 --- /dev/null +++ b/skills/hamalert-cli/references/data-formats.md @@ -0,0 +1,71 @@ +# Data Formats and Locations + +## Config + +Default config path: + +```text +~/.config/hamalert/config.toml +``` + +Preferred config stores only the username: + +```toml +username = "N0CALL" +``` + +When the OS keyring is unavailable, the CLI may use a legacy plaintext fallback: + +```toml +username = "N0CALL" +password = "secret" +``` + +Do not create or print plaintext password config unless the user explicitly asks for that fallback. + +## Callsign Files + +`import-file` reads a text file where the first word on each non-comment line is the callsign. + +```text +W1AW +K3LR friend from contest +N0CALL met at hamfest +``` + +Skipped lines: + +```text +# comment +// comment + +``` + +Notes after the first word are ignored. + +## Backup Files + +`backup` writes a JSON array of HamAlert trigger objects. A backup may include runtime fields such as `_id`, `user_id`, `matchCount`, `disabled`, `conditions`, `actions`, `comment`, and `options`. + +Default backup directory: + +```text +~/.local/share/hamalert/backups/ +``` + +Use the actual path printed by `hamalert-cli backup`; platform data directories can vary. + +## Profiles + +Profile data lives under the platform data directory, normally: + +```text +~/.local/share/hamalert/ + permanent.json + current-profile + profiles/ + home.json + portable.json +``` + +Profile and permanent trigger files store trigger-like JSON without runtime-only IDs. Matching is based on `conditions` and `comment`; actions and options are preserved but are not part of identity matching. diff --git a/skills/hamalert-cli/references/safety.md b/skills/hamalert-cli/references/safety.md new file mode 100644 index 0000000..1425d48 --- /dev/null +++ b/skills/hamalert-cli/references/safety.md @@ -0,0 +1,72 @@ +# Safety Rules + +## Credential Safety + +- Never print passwords or ask the user to paste a password into chat. +- Prefer `auth login --password-stdin` or `auth login --password-env`. +- Avoid `auth login --password` unless the user explicitly accepts shell history and process-list exposure. +- `auth status` does not print passwords, but it may attempt a live login with resolved credentials. + +## Read-Only or Mostly Read-Only Commands + +These do not intentionally modify live HamAlert triggers: + +```bash +hamalert-cli auth status +hamalert-cli backup +hamalert-cli restore --input +hamalert-cli import-file --file ... --dry-run +hamalert-cli import-polo-notes --url ... --dry-run +hamalert-cli bulk-delete --dry-run +hamalert-cli profile list +hamalert-cli profile show +hamalert-cli profile status +hamalert-cli profile show-permanent +hamalert-cli profile switch +``` + +Important caveats: + +- Non-auth commands still log in before they run. +- Dry-runs often fetch live triggers. +- `profile status` may offer to update local profile bookkeeping. +- `profile switch ` dry-run may offer to save unexpected triggers into a local profile before exiting. + +## Commands That Modify Live HamAlert + +Ask for explicit approval before running these unless approval is already clear: + +```bash +hamalert-cli add-trigger ... +hamalert-cli import-file ... # without --dry-run +hamalert-cli import-polo-notes ... # without --dry-run +hamalert-cli restore --input --no-dry-run +hamalert-cli edit +hamalert-cli bulk-delete # without --dry-run +hamalert-cli profile switch --no-dry-run +``` + +## Commands That Modify Local State + +These change local config/profile files: + +```bash +hamalert-cli auth login +hamalert-cli auth logout +hamalert-cli profile save +hamalert-cli profile delete +hamalert-cli profile set-permanent +hamalert-cli profile switch --no-dry-run +``` + +## Backup Expectations + +- Run `hamalert-cli backup` before live destructive changes when practical. +- `restore --no-dry-run`, `bulk-delete`, and `profile switch --no-dry-run` create automatic backups before destructive live changes. +- Report the printed backup path to the user. + +## Interaction Safety + +- For `bulk-delete`, all triggers start checked, meaning kept. Unchecked triggers are deleted. +- For `profile set-permanent`, checked triggers become permanent. +- If the user is not present for an interactive TUI, stop and ask for input rather than guessing. diff --git a/skills/hamalert-cli/references/troubleshooting.md b/skills/hamalert-cli/references/troubleshooting.md new file mode 100644 index 0000000..1a2c613 --- /dev/null +++ b/skills/hamalert-cli/references/troubleshooting.md @@ -0,0 +1,65 @@ +# Troubleshooting + +## `hamalert-cli` Not Found + +If inside this repository, use: + +```bash +cargo run -- +``` + +To install from the repo: + +```bash +cargo install --path . +``` + +## Missing Config + +Run: + +```bash +hamalert-cli auth login +``` + +or use a custom config: + +```bash +hamalert-cli --config-file /path/to/config.toml auth login +``` + +## Keyring Unavailable + +Headless Linux, SSH sessions, or locked desktop keyrings may not provide a usable keyring. The CLI can fall back to a plaintext config password, but only use that path when the user explicitly accepts the security tradeoff. + +## Login Failed + +Check: + +- Username/callsign spelling. +- Password source (`--password-stdin`, `--password-env`, or interactive prompt). +- Whether `HAMALERT_PASSWORD` or the named environment variable is set when using `--password-env`. + +## Empty Import + +For local files, verify the file exists and contains callsigns as the first word on non-comment lines. + +For PoLo notes, verify the URL is reachable and returns the expected text content. + +## Backup Location Confusion + +Default backups are not written to the current directory. Use the path printed by `hamalert-cli backup`, normally under: + +```text +~/.local/share/hamalert/backups/ +``` + +## Profile Mismatch + +Run: + +```bash +hamalert-cli profile status +``` + +Use the status output to decide whether to update the recorded current profile, save current triggers as a profile, or ignore the mismatch. diff --git a/skills/hamalert-cli/references/workflows.md b/skills/hamalert-cli/references/workflows.md new file mode 100644 index 0000000..f388fa6 --- /dev/null +++ b/skills/hamalert-cli/references/workflows.md @@ -0,0 +1,158 @@ +# Workflows + +## Check Local Setup + +```bash +skills/hamalert-cli/scripts/local-check.sh +hamalert-cli auth status +``` + +`auth status` verifies resolved credentials against HamAlert if credentials are available. It does not print password values. + +## First-Time Login + +Interactive: + +```bash +hamalert-cli auth login +``` + +Non-interactive with stdin: + +```bash +printf '%s\n' "$HAMALERT_PASSWORD" | hamalert-cli auth login --username N0CALL --password-stdin +``` + +Non-interactive with environment variable: + +```bash +hamalert-cli auth login --username N0CALL --password-env HAMALERT_PASSWORD +``` + +Avoid `--password` unless the user accepts shell history and process-list exposure. + +## Add a Callsign Alert + +Confirm the requested callsign, comment, actions, and optional modes, then run: + +```bash +hamalert-cli add-trigger --callsign W1AW --comment "W1AW spotted" --actions app +``` + +`add-trigger` changes live HamAlert state and has no dry-run mode. + +## Add Multiple Callsigns as One Trigger + +```bash +hamalert-cli add-trigger \ + --callsign W1AW \ + --callsign K3LR \ + --comment "Monitor activity" \ + --actions app telnet +``` + +The CLI sends one trigger containing the joined callsigns. + +## Import a Local Callsign File + +Preview: + +```bash +hamalert-cli import-file --file callsigns.txt --comment "Local imports" --actions app --dry-run +``` + +Execute after approval: + +```bash +hamalert-cli import-file --file callsigns.txt --comment "Local imports" --actions app +``` + +## Import Ham2K PoLo Notes + +Preview: + +```bash +hamalert-cli import-polo-notes --url https://example.com/callsigns.txt --comment "PoLo imports" --actions app --dry-run +``` + +Execute after approval: + +```bash +hamalert-cli import-polo-notes --url https://example.com/callsigns.txt --comment "PoLo imports" --actions app +``` + +## Back Up Triggers + +```bash +hamalert-cli backup +``` + +Tell the user the output path printed by the command. When no `--output` is given, backups are written under the platform data directory, normally `~/.local/share/hamalert/backups/`. + +## Restore Triggers + +Always preview first: + +```bash +hamalert-cli restore --input +``` + +Execute only with explicit approval: + +```bash +hamalert-cli restore --input --no-dry-run +``` + +Live restore deletes all existing triggers after creating an automatic backup. + +## Clean Up Triggers + +Preview the interactive selection: + +```bash +hamalert-cli bulk-delete --dry-run +``` + +Execute only with explicit approval: + +```bash +hamalert-cli bulk-delete +``` + +All entries begin checked, meaning kept. Unchecked entries are the deletion set. + +## Use Profiles + +Inspect state: + +```bash +hamalert-cli profile list +hamalert-cli profile status +hamalert-cli profile show-permanent +``` + +Save current non-permanent triggers as a profile: + +```bash +hamalert-cli profile save home +``` + +Preview a switch: + +```bash +hamalert-cli profile switch portable +``` + +Execute a switch only with explicit approval: + +```bash +hamalert-cli profile switch portable --no-dry-run +``` + +Select permanent triggers: + +```bash +hamalert-cli profile set-permanent +``` + +Permanent triggers are excluded from profiles and remain active across profile switches. diff --git a/skills/hamalert-cli/scripts/help-snapshot.sh b/skills/hamalert-cli/scripts/help-snapshot.sh new file mode 100755 index 0000000..5e2a4fb --- /dev/null +++ b/skills/hamalert-cli/scripts/help-snapshot.sh @@ -0,0 +1,37 @@ +#!/bin/sh +set -eu + +run_cli() { + if command -v hamalert-cli >/dev/null 2>&1; then + hamalert-cli "$@" + elif [ -f Cargo.toml ]; then + cargo run -- "$@" + else + echo "hamalert-cli binary not found and no Cargo.toml is present" >&2 + exit 1 + fi +} + +run_help() { + printf '\n## hamalert-cli' + if [ "$#" -gt 0 ]; then + printf ' %s' "$@" + fi + printf ' --help\n\n' + run_cli "$@" --help +} + +run_help +run_help auth +run_help auth login +run_help add-trigger +run_help import-polo-notes +run_help import-file +run_help backup +run_help restore +run_help edit +run_help bulk-delete +run_help profile +run_help profile save +run_help profile switch +run_help profile set-permanent diff --git a/skills/hamalert-cli/scripts/local-check.sh b/skills/hamalert-cli/scripts/local-check.sh new file mode 100755 index 0000000..8ad6acf --- /dev/null +++ b/skills/hamalert-cli/scripts/local-check.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -eu + +if command -v hamalert-cli >/dev/null 2>&1; then + echo "hamalert-cli: $(command -v hamalert-cli)" + hamalert-cli --help >/dev/null + echo "invoke: hamalert-cli" + exit 0 +fi + +if [ -f Cargo.toml ]; then + cargo run -- --help >/dev/null + echo "hamalert-cli binary not found" + echo "invoke: cargo run --" + exit 0 +fi + +echo "hamalert-cli binary not found and no Cargo.toml is present" >&2 +exit 1