Skip to content

feat(cli): club targeting via --club/--all + current_club (#86)#123

Merged
Sootopolis merged 1 commit into
mainfrom
feat/86-cli-current-club
Jun 25, 2026
Merged

feat(cli): club targeting via --club/--all + current_club (#86)#123
Sootopolis merged 1 commit into
mainfrom
feat/86-cli-current-club

Conversation

@Sootopolis

Copy link
Copy Markdown
Owner

What

Reshapes the ccas CLI's club targeting (issue #86, epic #40). Drops positional club slugs everywhere in favour of a uniform --club option plus a current-club context pointer.

  • Targeting: --club <slug> (comma-separated on membership/history) and --all (every managed club, expanded client-side via GET /api/managed-clubsserver API unchanged). Neither given → falls back to current_club. --all + --club together is rejected (conflicting intent).
  • ccas use-club <slug>: local config write (no server) that sets current_club. Top-level — it's a client-local focus pointer, whereas the club group is server-side managed-set ops. Server-validation was rejected on purpose (a fresh / not-yet-fetched club has nothing to validate against): it warns offline against the completion cache but never blocks.
  • ConfigWriter: surgical single-key HOCON edit (zio-config has no writer), written atomically (temp-file + same-dir rename) so a crash/concurrent writer can't leave a half-written config.
  • Trim CLI club input at the resolver / use-club boundary (ClubSlug.normalize only lowercases).
  • Rename the managed-clubs group clubsclub (singular, idiomatic per gh/docker/git-remote).
  • Completion: club-slug completion moves from positionals to the --club value flag (+ the use-club positional); drift guard now covers hyphenated commands.
ccas use-club team-a     # local: set current club
ccas club add team-a     # server: managed_club marker
ccas membership          # targets current_club
ccas membership --all    # all managed clubs

Fixes

Fixes #86.

Testing

  • sbt test923 passed, 0 failed (pre-push hook green; +new TestClubResolver, TestUseClub, TestConfigWriter, updated parser/config/completion suites).
  • Staged-binary smoke: use-club write + offline warn + trim; --all/--club conflict and no-club → clean exit 2; club group rename; old clubs/use rejected; regenerated completions/ccas.bash byte-matches the emitter.

Note: the standalone ZIOAppDefault apps still hand-roll argv parsing — out of scope here (#70). Future intent to gate job submission to managed clubs only is captured for #66/#60.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ETHm6wCYdzFuB3kNEBayjF

Replace positional club slugs across the CLI with a uniform --club option
and a current-club context pointer, the cleaner way to deliver #86's intent.

Why the redesign over the issue's "optional positional slug": an optional
positional is ambiguous for `blacklist add/remove` (slug precedes the
username positionals). Moving the club to an option dissolves that and gives
one git/kubectl-style targeting model everywhere.

- Targeting: `--club <slug>` (comma-separated on membership/history) and
  `--all` (every managed club, expanded client-side via /api/managed-clubs so
  the server API is unchanged). Neither given -> falls back to current_club.
  `--all` together with `--club` is rejected: conflicting intent, almost
  always a mistake.
- `ccas use-club <slug>`: a local config write (no server) that sets
  current_club. Top-level, not under `club`, because it's a client-local
  focus pointer while the `club` group is server-side managed-set ops.
  Server-validation was rejected on purpose: a fresh user / not-yet-fetched
  club has nothing to validate against, so it warns (offline, vs the
  completion cache) but never blocks.
- ConfigWriter: surgical single-key HOCON edit (zio-config has no writer),
  written atomically via temp-file + same-dir rename so a crash/concurrent
  writer can't leave a half-written config.
- Trim CLI club input at the resolver/use-club boundary, since
  ClubSlug.normalize only lowercases.
- Rename the managed-clubs group `clubs` -> `club` (singular, idiomatic per
  gh/docker/git-remote).
- Completion: club-slug completion moves from positionals to the `--club`
  value flag (plus the `use-club` positional); drift guard now sees
  hyphenated commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETHm6wCYdzFuB3kNEBayjF
@Sootopolis Sootopolis merged commit d18e0f9 into main Jun 25, 2026
1 check passed
@Sootopolis Sootopolis deleted the feat/86-cli-current-club branch June 25, 2026 14:25
Sootopolis added a commit that referenced this pull request Jun 25, 2026
Regression from #123. `club add`/`remove` manage the membership set itself,
so the club is the direct operand (like `git remote add <name>`), not the
`--club` context option the operation commands use. With `--club`, the natural
`ccas club add <slug>` silently dropped the slug as an unparsed operand and
failed with "no club specified". Revert these two to a required positional
slug (no `--club`, no current_club fallback).

Also fix a latent completion bug from the same PR: the `clubs` -> `club` group
rename missed the CompletionSpec *leaves* (still `List("clubs", …)`), so
`leavesOf("club")` was empty — the `club` group's subcommands lost argument
completion and rendered blank summaries. Rename the leaves and add a drift
guard asserting every group's children have a matching leaf, which fails on
exactly this mismatch.


Claude-Session: https://claude.ai/code/session_01ETHm6wCYdzFuB3kNEBayjF

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI club-context: current_club + ccas use <slug>

1 participant