Skip to content

Commit c8f18f9

Browse files
committed
Allow --head/--tail to customize count with --after/--before cursors
Previously all four direction/cursor flags were mutually exclusive, which locked cursor-based pagination to the hardcoded default of 25. Relax the rule to allow the natural combinations: --after TS --head N next N newer after TS --before TS --tail N previous N older before TS Still forbidden: --head + --tail (two counts), --after + --before (two cursors), --head + --before, --tail + --after (direction conflicts). Error messages name the offending pair. README and skill docs updated with the new idioms and drop the "next/previous 25" phrasing in favor of "default 25, override with --head/--tail".
1 parent 734715c commit c8f18f9

3 files changed

Lines changed: 70 additions & 36 deletions

File tree

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ slack conversations list --refresh
135135
slack messages list '#general'
136136
slack messages list C0123456789
137137

138-
# Direction flags (mutually exclusive)
139-
slack messages list '#general' --tail 5 # last 5 messages
140-
slack messages list '#general' --head 5 # first 5 in window
141-
slack messages list '#general' --after 1234567890.123456 # next 25 after cursor
142-
slack messages list '#general' --before 1234567890.123456 # previous 25 before cursor
138+
# Direction flags
139+
slack messages list '#general' --tail 5 # last 5 messages
140+
slack messages list '#general' --head 5 # first 5 in window
141+
slack messages list '#general' --after 1234567890.123456 # messages after cursor (default 25, override with --head N)
142+
slack messages list '#general' --before 1234567890.123456 # messages before cursor (default 25, override with --tail N)
143+
slack messages list '#general' --after 1234567890.123456 --head 5 # next 5 newer
144+
slack messages list '#general' --before 1234567890.123456 --tail 5 # previous 5 older
143145

144146
# Compose with time windows
145147
slack messages list '#general' --today

coding-agent-plugins/claude-code/skills/slackcli/SKILL.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,26 +72,33 @@ slack conversations list --refresh # Force cache refresh
7272

7373
### List Messages
7474

75-
Four mutually-exclusive direction flags control which slice of history to fetch.
76-
When no direction flag is given, the default is `--tail 25`. Results are always
77-
displayed oldest → newest.
75+
Direction flags control which slice of history to fetch. When no direction flag
76+
is given, the default is `--tail 25`. Results are always displayed
77+
oldest → newest.
7878

7979
| Flag | Meaning |
8080
|------|---------|
8181
| `--tail N` | Last N messages in the window (default direction; default N=25) |
8282
| `--head N` | First N messages in the window, oldest first |
83-
| `--after TS` | Next 25 messages after cursor timestamp TS (forward walk) |
84-
| `--before TS` | Previous 25 messages before cursor timestamp TS (backward walk) |
83+
| `--after TS` | Messages after cursor timestamp TS (default 25, override with `--head N`) |
84+
| `--before TS` | Messages before cursor timestamp TS (default 25, override with `--tail N`) |
85+
86+
Allowed combinations: `--head N` alone, `--tail N` alone, `--after TS` alone,
87+
`--before TS` alone, `--after TS --head N`, `--before TS --tail N`.
88+
`--head + --tail`, `--after + --before`, `--head + --before`, and
89+
`--tail + --after` are rejected.
8590

8691
Direction flags compose with time-window flags (`--since`, `--until`, `--today`,
8792
`--last-7d`, `--last-30d`), which are orthogonal bounds on the window.
8893

8994
```bash
90-
slack messages list '#channel' # Last 25 messages
91-
slack messages list '#channel' --tail 5 # Last 5 messages
92-
slack messages list '#channel' --head 5 # First 5 in window
93-
slack messages list '#channel' --after 1234567890.123456 # Next 25 after cursor
94-
slack messages list '#channel' --before 1234567890.123456 # Previous 25 before cursor
95+
slack messages list '#channel' # Last 25 messages
96+
slack messages list '#channel' --tail 5 # Last 5 messages
97+
slack messages list '#channel' --head 5 # First 5 in window
98+
slack messages list '#channel' --after 1234567890.123456 # After cursor (default 25)
99+
slack messages list '#channel' --before 1234567890.123456 # Before cursor (default 25)
100+
slack messages list '#channel' --after 1234567890.123456 --head 5 # Next 5 newer
101+
slack messages list '#channel' --before 1234567890.123456 --tail 5 # Previous 5 older
95102

96103
slack messages list '#channel' --today # Today only
97104
slack messages list '#channel' --last-7d # Last 7 days

src/slackcli/commands/messages.py

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,16 @@ def list_messages(
276276
str | None,
277277
typer.Option(
278278
"--after",
279-
help="Return up to 25 messages strictly after this ts (forward cursor).",
279+
help="Return messages strictly after this ts (forward cursor). "
280+
"Defaults to 25; combine with --head N to override.",
280281
),
281282
] = None,
282283
before: Annotated[
283284
str | None,
284285
typer.Option(
285286
"--before",
286-
help="Return up to 25 messages strictly before this ts (backward cursor).",
287+
help="Return messages strictly before this ts (backward cursor). "
288+
"Defaults to 25; combine with --tail N to override.",
287289
),
288290
] = None,
289291
reactions: Annotated[
@@ -310,15 +312,20 @@ def list_messages(
310312
) -> None:
311313
"""List messages in a channel or thread.
312314
313-
Exactly one of --head / --tail / --after / --before may be set. If none
314-
are specified, --tail 25 is used. Display order is always ascending
315-
(oldest on top, newest on bottom) regardless of the direction flag.
315+
Direction flags compose as follows: --head N or --tail N alone, --after TS
316+
or --before TS alone (defaults to 25), or --after TS --head N /
317+
--before TS --tail N to override the count. Any other combination is
318+
rejected. If none are specified, --tail 25 is used. Display order is
319+
always ascending (oldest on top, newest on bottom) regardless of the
320+
direction flag.
316321
317322
Examples:
318323
slack messages list '#general' # last 25
319324
slack messages list '#general' --tail 5
320325
slack messages list '#general' --after 1234567890.123456
321326
slack messages list '#general' --before 1234567890.123456
327+
slack messages list '#general' --after 1234567890.123456 --head 5
328+
slack messages list '#general' --before 1234567890.123456 --tail 5
322329
slack messages list '#general' --head 100 --since 2024-01-01
323330
slack messages list '#general' 1234567890.123456 # thread replies
324331
"""
@@ -327,17 +334,29 @@ def list_messages(
327334
error_console.print(f"[red]Invalid --reactions value: {reactions}. Use 'off', 'counts', or 'names'.[/red]")
328335
raise typer.Exit(1)
329336

330-
# Validate mutually exclusive direction flags.
331-
direction_flags = {
332-
"--head": head is not None,
333-
"--tail": tail is not None,
334-
"--after": after is not None,
335-
"--before": before is not None,
336-
}
337-
set_flags = [name for name, is_set in direction_flags.items() if is_set]
338-
if len(set_flags) > 1:
337+
# Validate direction flag combinations. Allowed:
338+
# (none), --head N, --tail N, --after TS, --before TS,
339+
# --after TS --head N, --before TS --tail N.
340+
# Everything else is a user error.
341+
has_head = head is not None
342+
has_tail = tail is not None
343+
has_after = after is not None
344+
has_before = before is not None
345+
346+
if has_head and has_tail:
347+
error_console.print("[red]--head and --tail are mutually exclusive.[/red]")
348+
raise typer.Exit(1)
349+
if has_after and has_before:
350+
error_console.print("[red]--after and --before are mutually exclusive.[/red]")
351+
raise typer.Exit(1)
352+
if has_head and has_before:
339353
error_console.print(
340-
f"[red]--head / --tail / --after / --before are mutually exclusive. Got: {', '.join(set_flags)}[/red]"
354+
"[red]--head cannot be combined with --before. Use --tail N with --before, or --head N with --after.[/red]"
355+
)
356+
raise typer.Exit(1)
357+
if has_tail and has_after:
358+
error_console.print(
359+
"[red]--tail cannot be combined with --after. Use --head N with --after, or --tail N with --before.[/red]"
341360
)
342361
raise typer.Exit(1)
343362

@@ -347,14 +366,20 @@ def list_messages(
347366
count: int
348367
after_ts: str | None = None
349368
before_ts: str | None = None
350-
if head is not None:
351-
direction, count = "head", head
352-
elif tail is not None:
353-
direction, count = "tail", tail
354-
elif after is not None:
369+
if has_after and has_head:
370+
direction, count = "head", head # type: ignore[assignment]
371+
after_ts = after
372+
elif has_before and has_tail:
373+
direction, count = "tail", tail # type: ignore[assignment]
374+
before_ts = before
375+
elif has_head:
376+
direction, count = "head", head # type: ignore[assignment]
377+
elif has_tail:
378+
direction, count = "tail", tail # type: ignore[assignment]
379+
elif has_after:
355380
direction, count = "head", DEFAULT_CURSOR_PAGE
356381
after_ts = after
357-
elif before is not None:
382+
elif has_before:
358383
direction, count = "tail", DEFAULT_CURSOR_PAGE
359384
before_ts = before
360385
else:

0 commit comments

Comments
 (0)