wiq-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cac3732fa4c286907bce03d6ac62765477d828507719a29074873a9f9b90bde2
4
+ data.tar.gz: c686b4e1fb901e6554727c7030eb63d66cd70f659ca95345db2124b0ec6c9138
5
+ SHA512:
6
+ metadata.gz: 970cfd866b44f27e8be608f8ddb40b147521bc241557637e545b21e23ec490d6e5a6ca8b6252b9f1c5f5a0ece7d1ad4a12f6457b80e1131c0beef691a5e65a3d
7
+ data.tar.gz: 22e94b802d4b4209c32131919733b68937775515a0b089ce764c1496758b281562e5532b708258351bac66c78f2db138eaefa9b55987dcb68671112ef2272ca5
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WrestlingIQ
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # wiq-cli
2
+
3
+ > [!WARNING]
4
+ > **Research preview — v0.1.0.** This is an exploratory tool. The command
5
+ > surface, output shapes, and behavior are subject to change quickly and
6
+ > without backwards compatibility guarantees between releases. Not yet
7
+ > recommended for production-critical automation. Pin your gem version
8
+ > if you build anything load-bearing on top of it.
9
+
10
+ Read-only command-line interface for [WrestlingIQ](https://www.wrestlingiq.com).
11
+ Designed to be driven by both humans and AI agents (Claude Code, Cursor,
12
+ etc.) via per-user personal access tokens (PATs).
13
+
14
+ ## Getting started
15
+
16
+ Four steps. Roughly five minutes end-to-end.
17
+
18
+ ### 1. Install
19
+
20
+ ```bash
21
+ gem install wiq-cli
22
+ ```
23
+
24
+ Requires Ruby 3.1+. On macOS, the system Ruby is too old —
25
+ `brew install ruby` (or use rbenv / asdf) before running the gem install.
26
+
27
+ ### 2. Get a personal access token
28
+
29
+ Sign into WrestlingIQ in your browser, then visit:
30
+
31
+ **https://www.wrestlingiq.com/settings/personal_access_tokens**
32
+
33
+ Click "New token", give it a name (e.g., `wiq-cli on my laptop`),
34
+ and copy the token value. **You'll only see it once** — paste it
35
+ somewhere safe for the next step.
36
+
37
+ The token inherits your WrestlingIQ permissions. If you're an admin
38
+ coach, your CLI will be able to run admin reports; if you're not, it
39
+ won't. Either way, the token can be revoked anytime from the same
40
+ page.
41
+
42
+ ### 3. Log in
43
+
44
+ ```bash
45
+ wiq auth login
46
+ ```
47
+
48
+ The CLI prompts for the host (defaults to production — just press
49
+ Enter) and the token (paste the value from step 2). It verifies
50
+ against the API and stores the token at
51
+ `~/.config/wiq/credentials.json` (mode 0600, never logged).
52
+
53
+ Sanity-check:
54
+
55
+ ```bash
56
+ wiq doctor
57
+ ```
58
+
59
+ All checks should pass and "Bound profile" should show your name + team.
60
+
61
+ ### 4. Install the Claude Code skill (optional but recommended)
62
+
63
+ ```bash
64
+ wiq setup claude
65
+ ```
66
+
67
+ This drops a small `SKILL.md` into `~/.claude/skills/wiq/` that
68
+ teaches Claude how to drive the CLI. Claude Code auto-detects it
69
+ within the current session — no restart needed.
70
+
71
+ Now you can ask Claude things like:
72
+
73
+ - "How is our prospect pipeline doing?"
74
+ - "Show me everyone who hasn't been to practice in 2 weeks"
75
+ - "Which families have failed payments that weren't retried successfully?"
76
+
77
+ …and Claude will translate them into the right CLI commands.
78
+
79
+ ## Try it without Claude
80
+
81
+ ```bash
82
+ wiq rosters list # Browse rosters
83
+ wiq prospects summary # Pipeline dashboard
84
+ wiq events list --start 2026-05-01 --end 2026-05-31 # Calendar
85
+ wiq workflows list # Curated multi-step recipes
86
+ wiq reports types # 36 report types w/ recommendations
87
+ wiq commands # Full JSON command tree (for agents)
88
+ ```
89
+
90
+ Pass `--help` to any command for the full option list. Pass
91
+ `--json` for the structured envelope, `--agent` for bare JSON, or
92
+ just let the default pretty output flow.
93
+
94
+ ## Multiple clubs / multiple roles
95
+
96
+ If you have PATs for different WIQ accounts (different clubs, or
97
+ both a coach + parent role), store each under its own alias:
98
+
99
+ ```bash
100
+ wiq auth login # First login → slot "default"
101
+ wiq auth login --as westside # Second account → slot "westside"
102
+ wiq --as westside rosters list # Run against the second slot
103
+ WIQ_ALIAS=westside wiq events list # Same, via env var
104
+ ```
105
+
106
+ Full mechanic + resolution chain documented in `docs/wiq_api_notes.md`.
107
+
108
+ ## If something doesn't work
109
+
110
+ ```bash
111
+ wiq doctor # Diagnostic checks (host, token, reachability, profile)
112
+ wiq auth status # Shows the resolved credential
113
+ wiq auth list # All stored credentials
114
+ ```
115
+
116
+ If `wiq doctor` reports a failure or you see an unexpected error code,
117
+ the error envelope includes a `hint` field pointing at the next thing
118
+ to try. If you get stuck, email
119
+ [support@wrestlingiq.com](mailto:support@wrestlingiq.com) with the
120
+ output (the CLI never logs your token — paste the full JSON safely).
121
+
122
+ ## Output modes
123
+
124
+ | Flag | Output |
125
+ | --- | --- |
126
+ | (default) | Pretty JSON to a TTY, bare JSON when piped |
127
+ | `--json` | Full envelope: `{ok, data, summary, breadcrumbs, meta}` |
128
+ | `--agent` | Bare `data` as JSON — best for headless agents |
129
+
130
+ ## Where things live
131
+
132
+ - [`docs/wiq_api_notes.md`](docs/wiq_api_notes.md) — auth model, response shapes, gotchas, what the CLI maps to in `/api/v1`
133
+ - [`docs/deferred.md`](docs/deferred.md) — work explicitly out of scope for v1 + the rationale
134
+ - [`share/skills/wiq/SKILL.md`](share/skills/wiq/SKILL.md) — the bundled Claude Code skill content
135
+
136
+ ## Status
137
+
138
+ v0.1.0 — 29 commands across 16 groups, 117 RSpec smoke examples.
139
+ Reads-only except for report submission (the API's canonical async
140
+ pattern). Write commands deferred — see `docs/deferred.md`.
141
+
142
+ ## License
143
+
144
+ MIT.
data/bin/wiq ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
5
+
6
+ require "wiq"
7
+
8
+ begin
9
+ Wiq::CLI.start(ARGV)
10
+ rescue Wiq::Error => e
11
+ Wiq::Output.render_error(e, options: { agent: ARGV.include?("--agent"), json: ARGV.include?("--json") })
12
+ exit(e.exit_code)
13
+ rescue Faraday::Error => e
14
+ Wiq::Output.render_error(
15
+ Wiq::Error.new(e.message, code: "network_error", hint: "Check the host URL and your network."),
16
+ options: { agent: ARGV.include?("--agent"), json: ARGV.include?("--json") }
17
+ )
18
+ exit(1)
19
+ rescue Interrupt
20
+ warn "\nInterrupted"
21
+ exit(130)
22
+ end
data/docs/deferred.md ADDED
@@ -0,0 +1,155 @@
1
+ # Deferred work
2
+
3
+ Everything we've explicitly chosen NOT to ship in v1. Each item carries a
4
+ one-line "why we punted" so future-us doesn't have to re-derive the
5
+ decision. Re-order as priorities shift; the headings are descriptive, not
6
+ priority-ordered.
7
+
8
+ Last updated: 2026-05-12 (after L1 ships).
9
+
10
+ ## Agent-discovery surface
11
+
12
+ - ~~**L2 — `wiq workflows` command.**~~ SHIPPED. 14 curated workflows
13
+ across 7 categories (attendance, leads, roster, finance, memberships,
14
+ fundraising, store) in `lib/wiq/workflows.rb`. Each carries a
15
+ `question`, structured `parameters` (with types + enums + required
16
+ flags), an ordered `recipe` (with `<placeholder>` and `[--flag <name>]`
17
+ syntax), and `admin_only` flag propagated from underlying reports.
18
+ Spec invariants enforce parameter↔placeholder consistency and
19
+ admin_only drift detection across `Workflows::ALL` and
20
+ `Reports::TYPES`.
21
+ - ~~**L3 — SKILL.md + Claude Code installer.**~~ SHIPPED.
22
+ `share/skills/wiq/SKILL.md` (lean — 10.8 KB) bundled in the gem,
23
+ installed via `wiq setup claude` (default `~/.claude/skills/wiq/`,
24
+ `--project` for per-project, `--force` to overwrite, `--print` to
25
+ inspect). Uses Claude Code's canonical skill format (no plugin
26
+ wrapper — confirmed via current docs). Sections cover bootstrap,
27
+ three core surfaces (commands/workflows/reports), auth model,
28
+ multi-club aliases, output modes, error codes table, pagination,
29
+ report decision matrix, common gotchas, what's NOT available.
30
+ - ~~**Per-command `agent_notes` annotations.**~~ SHIPPED via Thor
31
+ `long_desc` blocks on every command across all 11 groups. Surfaces in
32
+ `wiq <group> help <cmd>` today; Phase 2's `wiq <cmd> --help --agent`
33
+ will project it to structured JSON.
34
+ - ~~**Recommendation pass on the other report types.**~~ SHIPPED — 20
35
+ REC, 1 DEP, 15 NEU, 9 admin_only across the 36 entries in
36
+ `Reports::TYPES`. User-curated.
37
+ - ~~**`wiq commands` JSON tree dump.**~~ SHIPPED. Walks Thor's
38
+ registry, emits stable nested JSON: `{name, version, global_options,
39
+ top_level_commands, groups: [{name, description, commands:
40
+ [{name, description, long_description, usage, options}]}]}`. Filters
41
+ Thor internals (`help`, `tree`), surfaces `enum` constraints,
42
+ reverses Thor's `map` so display names match what users type
43
+ (`run` not `run_report`, `check` not `check_all`).
44
+ - **Per-command `--help --agent` JSON mode.** Deferred per the
45
+ Phase 2 scoping discussion — `wiq commands` covers the discovery
46
+ case in one call (~30 KB total). Add later only if a real agent
47
+ flow needs per-command JSON narrowly (filter the same introspection
48
+ output to one entry; very low cost).
49
+ - **`.surface` drift CI.** Snapshot of the command tree at repo root; CI
50
+ fails on drift without an explicit update. Worth it once the command
51
+ surface stabilizes (i.e., after L2 lands).
52
+
53
+ ## Commands not yet exposed
54
+
55
+ - ~~**`wiq events types`**~~ SHIPPED. Six canonical strings from
56
+ `app/models/event.rb` (practice, dual_meet, tournament, scramble,
57
+ private_lesson, other) surfaced via static command.
58
+ - **`wiq events create`** — recurring practice/event creation
59
+ (`POST /api/v1/events` with `repeat:` block). Write surface; deferred
60
+ until v1.1.
61
+ - **`wiq check_ins record`** — mark attendance via CLI
62
+ (`POST/PUT /api/v1/events/:id/check_ins`). Write surface; deferred.
63
+ - **`wiq invoice_payments list`** — receipts/payment-instance granularity
64
+ for tracing money on a specific subscription. Endpoint exists
65
+ (`GET /api/v1/billing_subscriptions/:id/invoice_payments`). Hold
66
+ until a real use case beats `wiq charges list` for clarity.
67
+ - ~~**`wiq wrestlers list`**~~ SHIPPED narrow. Default per_page=20, no
68
+ --all flag, base payload kept tight. Filters translate to Ransack
69
+ (--first-name, --last-name, --weight-class, --academic-class, --age,
70
+ --roster, --profile-type) + legacy free-text --query. --expand opts
71
+ into rosters / registration_answers per row. Multi-roster
72
+ intersection deferred (API supports it; CLI surface didn't justify
73
+ the complexity for v1). `wiq wrestlers show <id>` paired.
74
+ - **`wiq url parse <url>`** — extract team/roster/event IDs from WIQ web
75
+ URLs. Initial-plan item; useful for agents pasted URLs by humans.
76
+ - **`wiq paid_sessions create/update`**, **`wiq rosters create/update`**,
77
+ etc. — every write path on every resource. v1 is reads-only except
78
+ report submission. Cherry-pick as customers ask.
79
+ - **Prospect write commands.** API supports `POST /prospect_families`,
80
+ `PATCH /prospect_families/:id` (incl. assigned_coach), `DELETE`,
81
+ `POST /prospect_families/:id/prospects`, `PATCH /prospects/:id`
82
+ (incl. stage transitions via `advance_to!`), and
83
+ `POST /prospect_families/:id/notes` (with `clear_follow_up_for[]` /
84
+ `add_follow_up_for[]` side-effect params). Reads-only in v1 — most
85
+ pipeline edits happen in the drawer UI today, and exposing
86
+ stage-transition writes without first watching agents use them is
87
+ asking for trouble.
88
+
89
+ ## Packaging / distribution
90
+
91
+ - **macOS Keychain integration.** Currently file-based at
92
+ `~/.config/wiq/credentials.json` mode 0600. Keychain via the `keyring`
93
+ gem was in the original plan; the gem has compilation quirks and the
94
+ file store is fine for v1. Add once we have at least one customer
95
+ using the CLI.
96
+ - **Homebrew tap (`brew install wrestlingiq/tap/wiq-cli`).** Initial-plan
97
+ distribution channel for Mac users. Gem-only install for v1.
98
+ - **`curl …/install-cli | bash` script.** Agent-friendly env-setup
99
+ installer. Gem-only install for v1.
100
+ - ~~**README.md**~~ SHIPPED (lean — install, bootstrap, common
101
+ commands, multi-club, Claude integration, output modes, pointers
102
+ to docs/). **CHANGELOG.md** still deferred — wait for v0.2.
103
+ - **Integration / command-level tests.** Smoke layer landed
104
+ (`spec/{pagination,credentials,errors,config,output,client,season_resolver}_spec.rb`,
105
+ 57 examples covering config resolution, error mapper, pagination,
106
+ output formatters, client wrap-unwrap, season filter). Still missing:
107
+ full Thor-invocation tests that exercise the command modules end-to-end
108
+ (`wiq rosters list --as westside` against a stubbed API). Add once a
109
+ command module starts carrying real logic beyond passing params through.
110
+
111
+ ## Output
112
+
113
+ - **`--md` Markdown output mode.** Three modes (pretty/json/agent) cover
114
+ v1. Add when an agent actually needs Markdown inline in a chat surface.
115
+
116
+ ## Verification gaps (driven by user, not me)
117
+
118
+ - **End-to-end smoke against real staging.** Auth flow + at least one
119
+ paginated index + one report poll. User is driving this.
120
+ - **Confirm `PracticeAttendanceReport.result` / `CheckInSummaryReport.result`
121
+ shapes are agent-friendly.** Both land in `report.result` as opaque
122
+ jsonb; verify the structure is parseable without an HTML-strip step.
123
+ - **OpenAPI regeneration.** `wrestling/doc/openapi.yaml` is ~1 year
124
+ stale. Run `OPENAPI=1 bundle exec rspec` and inspect the diff before
125
+ the CLI / spec is published externally. WIQ-app side, not CLI side.
126
+
127
+ ## Backend asks (push back to WIQ app team)
128
+
129
+ - **`GET /api/v1/prospects?query=<str>` 500s on ambiguous ORDER BY.**
130
+ Found during the Phase 5 agent telemetry pass. The controller does
131
+ `Prospect.joins(:prospect_family).merge(ProspectFamily.search(query))
132
+ .order(created_at: :desc)` — both `prospects` and `prospect_families`
133
+ have `created_at`, so the join makes the order ambiguous. One-line
134
+ fix on the WIQ-app side: change to
135
+ `.order("prospects.created_at DESC")` (or
136
+ `.order(Prospect.arel_table[:created_at].desc)`). The CLI documents
137
+ the workaround (use `wiq prospect_families list --query` — same
138
+ matches, returns families with prospects embedded) until this ships.
139
+
140
+
141
+ - ~~**`days_threshold` permit fix on `Api::V1::ReportsController`**~~ —
142
+ SHIPPED. The CLI's `--days-threshold` flag now lands on the model
143
+ unchanged; no further CLI work needed.
144
+ - **Echo `request_id`** in the response body or `X-Request-ID` header,
145
+ for support correlation. Today the CLI can't give a customer a request
146
+ ID to ship to support.
147
+ - **Real location/site filter on events.** `Event.location` is free-text
148
+ and not in `ransackable_attributes`. WIQ team has flagged a structured
149
+ location concept as roadmap. Until then the CLI deliberately exposes
150
+ no `--site` flag.
151
+ - **Subdomain discovery flow for `wiq auth login`.** PAT settings URL
152
+ lives at `<team-subdomain>.wrestlingiq.com/settings/personal_access_tokens`.
153
+ If a customer doesn't know their subdomain, the CLI can't deep-link
154
+ them. Either document a discovery flow on the marketing site or accept
155
+ the host URL interactively (current plan).