Skip to content

Commit 6b0664e

Browse files
committed
feat: add cursor pagination and time windows to query command
Replace the old 'last N results' approach with forward pagination: - Add --after and --before for absolute ISO timestamp bounds - Default limit reduced from 100 to 50 for manageable pages - Output includes 'Next page: --after <timestamp>' when more results exist - Results returned oldest-first for natural forward pagination Update skill to guide agents toward broad queries with pagination instead of aggressive namespace/match filtering.
1 parent b1a6a42 commit 6b0664e

File tree

4 files changed

+90
-19
lines changed

4 files changed

+90
-19
lines changed

docs/content/docs/cli/query.mdx

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: "Search historical crumbs"
55

66
## `agentcrumbs query`
77

8-
Query historical crumbs with time ranges and filters.
8+
Query historical crumbs with time windows and cursor-based pagination.
99

1010
```bash
1111
agentcrumbs query --since 5m
@@ -15,38 +15,50 @@ agentcrumbs query --since 5m
1515

1616
| Flag | Description |
1717
| --- | --- |
18-
| `--since <duration>` | Time range (e.g., `5m`, `1h`, `24h`, `7d`) |
18+
| `--since <duration>` | Relative time window (e.g., `5m`, `1h`, `24h`, `7d`) |
19+
| `--after <timestamp>` | Crumbs after this ISO timestamp (cursor for pagination) |
20+
| `--before <timestamp>` | Crumbs before this ISO timestamp |
21+
| `--limit <n>` | Results per page (default: 50) |
1922
| `--ns <pattern>` | Filter by namespace |
2023
| `--tag <tag>` | Filter by tag |
2124
| `--session <id>` | Filter by session ID |
2225
| `--match <text>` | Text search |
2326
| `--app <name>` | Scope to a specific app (default: auto-detect from package.json) |
2427
| `--all-apps` | Query crumbs from all apps |
2528
| `--json` | JSON output |
26-
| `--limit <n>` | Maximum number of results |
2729

2830
Time units: `s` (seconds), `m` (minutes), `h` (hours), `d` (days).
2931

32+
### Pagination
33+
34+
Results are returned oldest-first, capped at `--limit` (default 50). When there are more results, the output includes a `Next page:` line with an `--after` timestamp you can use to fetch the next page.
35+
36+
```bash
37+
# First page
38+
agentcrumbs query --since 5m
39+
# Output: 50 of 128 crumbs. Next page: --after 2026-03-11T14:20:00.123Z
40+
41+
# Next page
42+
agentcrumbs query --since 5m --after 2026-03-11T14:20:00.123Z
43+
```
44+
3045
### Examples
3146

3247
```bash
33-
# Last 5 minutes
48+
# Last 5 minutes (all namespaces)
3449
agentcrumbs query --since 5m
3550

36-
# Last hour, filtered by namespace
37-
agentcrumbs query --since 1h --ns auth-service
51+
# Time window with absolute timestamps
52+
agentcrumbs query --after 2026-03-11T14:00:00Z --before 2026-03-11T14:05:00Z
3853

39-
# Filter by tag
40-
agentcrumbs query --tag root-cause
54+
# Paginate through results
55+
agentcrumbs query --since 1h --limit 25
4156

4257
# Filter by session
4358
agentcrumbs query --session a1b2c3
4459

45-
# JSON output with limit
46-
agentcrumbs query --since 1h --json --limit 50
47-
48-
# Text search
49-
agentcrumbs query --since 24h --match "connection refused"
60+
# Filter by tag
61+
agentcrumbs query --tag root-cause
5062

5163
# Query a specific app
5264
agentcrumbs query --since 1h --app my-project

packages/agentcrumbs/skills/agentcrumbs/SKILL.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ agentcrumbs collect # Start HTTP collector (required for query/tail)
8282
agentcrumbs tail # Live tail (auto-scoped to current app)
8383
agentcrumbs tail --app foo # Tail a specific app
8484
agentcrumbs tail --all-apps # Tail all apps
85-
agentcrumbs query --since 5m # Query history (--ns, --tag, --session, --json)
85+
agentcrumbs query --since 5m # Query last 5 minutes (all namespaces, 50 per page)
86+
agentcrumbs query --since 5m --after <timestamp> # Next page
8687
agentcrumbs clear # Clear crumbs for current app
8788
agentcrumbs clear --all-apps # Clear crumbs for all apps
8889
agentcrumbs strip # Remove all crumb markers from source
@@ -92,6 +93,28 @@ agentcrumbs --help # Full command reference
9293

9394
Most commands accept `--app <name>` and `--all-apps`. Default is auto-detect from `package.json`.
9495

96+
## Querying crumbs
97+
98+
Start broad — query a time window across all namespaces, then paginate if there are too many results. Do NOT filter by namespace or match text unless you are looking for something very specific. The whole point of crumbs is seeing the full picture across services.
99+
100+
```bash
101+
# Start here: get recent crumbs across all services
102+
agentcrumbs query --since 5m
103+
104+
# Paginate forward (timestamp from "Next page:" in output)
105+
agentcrumbs query --since 5m --after 2026-03-11T14:20:00.123Z
106+
107+
# Time window with absolute bounds
108+
agentcrumbs query --after 2026-03-11T14:00:00Z --before 2026-03-11T14:05:00Z
109+
110+
# Smaller pages if context is tight
111+
agentcrumbs query --since 5m --limit 25
112+
113+
# Only filter by namespace/match when you have a specific reason
114+
agentcrumbs query --since 5m --tag error
115+
agentcrumbs query --session a1b2c3
116+
```
117+
95118
Run `agentcrumbs <command> --help` for detailed options on any command.
96119

97120
## Enable tracing

packages/agentcrumbs/src/cli/commands/query.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,44 @@ export async function query(args: string[]): Promise<void> {
77
const ns = getFlag(args, "--ns");
88
const tag = getFlag(args, "--tag");
99
const since = getFlag(args, "--since");
10+
const after = getFlag(args, "--after");
11+
const before = getFlag(args, "--before");
1012
const session = getFlag(args, "--session");
1113
const match = getFlag(args, "--match");
1214
const json = hasFlag(args, "--json");
13-
const limit = parseInt(getFlag(args, "--limit") ?? "100", 10);
15+
const limit = parseInt(getFlag(args, "--limit") ?? "50", 10);
1416
const appCtx = parseAppFlags(args);
1517
const showApp = appCtx.allApps;
1618

1719
const allCrumbs = readAllCrumbs(appCtx);
1820

1921
let filtered = allCrumbs;
2022

23+
// Time window filters
2124
if (since) {
2225
const cutoff = parseSince(since);
2326
filtered = filtered.filter((c) => new Date(c.ts).getTime() >= cutoff);
2427
}
2528

29+
if (after) {
30+
const afterMs = new Date(after).getTime();
31+
if (isNaN(afterMs)) {
32+
process.stderr.write(`Invalid --after timestamp: "${after}". Use ISO 8601 format.\n`);
33+
process.exit(1);
34+
}
35+
filtered = filtered.filter((c) => new Date(c.ts).getTime() > afterMs);
36+
}
37+
38+
if (before) {
39+
const beforeMs = new Date(before).getTime();
40+
if (isNaN(beforeMs)) {
41+
process.stderr.write(`Invalid --before timestamp: "${before}". Use ISO 8601 format.\n`);
42+
process.exit(1);
43+
}
44+
filtered = filtered.filter((c) => new Date(c.ts).getTime() < beforeMs);
45+
}
46+
47+
// Content filters
2648
if (ns) {
2749
const pattern = new RegExp(`^${ns.replace(/\*/g, ".*")}$`);
2850
filtered = filtered.filter((c) => pattern.test(c.ns));
@@ -40,7 +62,10 @@ export async function query(args: string[]): Promise<void> {
4062
filtered = filtered.filter((c) => JSON.stringify(c).includes(match));
4163
}
4264

43-
const results = filtered.slice(-limit);
65+
const total = filtered.length;
66+
67+
// Take first `limit` crumbs (oldest first) for forward pagination
68+
const results = filtered.slice(0, limit);
4469

4570
if (results.length === 0) {
4671
process.stderr.write("No crumbs found matching filters.\n");
@@ -55,7 +80,16 @@ export async function query(args: string[]): Promise<void> {
5580
}
5681
}
5782

58-
process.stderr.write(`\n${results.length} crumbs found.\n`);
83+
// Pagination footer
84+
const hasMore = total > results.length;
85+
if (hasMore) {
86+
const lastTs = results[results.length - 1]!.ts;
87+
process.stderr.write(
88+
`\n${results.length} of ${total} crumbs. Next page: --after ${lastTs}\n`
89+
);
90+
} else {
91+
process.stderr.write(`\n${results.length} crumbs.\n`);
92+
}
5993
}
6094

6195
function parseSince(since: string): number {

packages/agentcrumbs/src/cli/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ Tail options:
3535
--json Output as JSON
3636
3737
Query options:
38-
--since <duration> Time filter (e.g., 5m, 1h, 24h)
38+
--since <duration> Relative time window (e.g., 5m, 1h, 24h)
39+
--after <timestamp> Crumbs after this ISO timestamp (for pagination)
40+
--before <timestamp> Crumbs before this ISO timestamp
41+
--limit <n> Max results per page (default: 50)
3942
--ns <pattern> Filter by namespace
4043
--tag <tag> Filter by tag
4144
--session <id> Filter by session ID
4245
--match <text> Filter by text content
43-
--limit <n> Max results (default: 100)
4446
--json Output as JSON
4547
4648
Collect options:

0 commit comments

Comments
 (0)