Skip to content

Instantly share code, notes, and snippets.

@cablehead
Last active January 19, 2026 17:16
Show Gist options
  • Select an option

  • Save cablehead/44eedb8d7d83af47f7efd7619d704ccd to your computer and use it in GitHub Desktop.

Select an option

Save cablehead/44eedb8d7d83af47f7efd7619d704ccd to your computer and use it in GitHub Desktop.
xs stream naming conventions RFC

xs Naming Conventions RFC

Proposing consistent naming for stream position concepts in xs.

The Problem

Current naming mixes metaphors:

  • .head returns the newest frame (like Git HEAD)
  • --tail skips to the end (like Unix tail)
  • But resume_from: "head" means start from the beginning

Proposed Vocabulary

Commands (topic-specific)

Current Proposed Meaning
.head <topic> .last <topic> Most recent frame for topic
- .last <topic> 5 Most recent 5 frames for topic
- .first <topic> Oldest frame for topic
- .first <topic> 5 Oldest 5 frames for topic

CLI Flags (stream-wide via .cat)

Concept Current Proposed
Skip existing, only new --tail --new
Resume after ID (exclusive) --last-id <id> --after <id>
Start from ID (inclusive) - --from <id>
Last N items from stream - --last <n>
First N items from stream - --first <n>

API Endpoints

Current Proposed Meaning
GET /head/{topic} GET /last/{topic} Most recent frame for topic
- GET /first/{topic} Oldest frame for topic
?tail ?new Skip existing
?last-id=<id> ?after=<id> After ID (exclusive)
- ?from=<id> From ID (inclusive)
- ?last=<n> Last N items
- ?first=<n> First N items

Handler start

Current Proposed Meaning
resume_from: "head" start: "first" Process from oldest
resume_from: "tail" start: "new" Only new items
resume_from: "<id>" start: { from: "<id>" } From this ID (inclusive)
- start: { after: "<id>" } After this ID (exclusive)

TTL

Current Proposed Meaning
ttl: "head:5" ttl: "last:5" Keep 5 most recent

Examples

# Topic-specific
.last my.topic           # most recent frame for topic
.last my.topic 5         # most recent 5 frames for topic
.first my.topic          # oldest frame for topic
.first my.topic 5        # oldest 5 frames for topic

# Stream-wide
.cat --last 5            # last 5 from entire stream
.cat --first 5           # first 5 from entire stream
.cat --new --follow      # only new items, keep watching
.cat --last 5 --follow   # last 5, then follow for new
xs cat --new --follow
xs cat --last 5 --follow
xs cat --after 01HQ... --follow
xs cat --from 01HQ...
# Handler start
start: "first"              # all history from oldest
start: "new"                # only new items
start: { from: "01HQ..." }  # from this ID (inclusive)
start: { after: "01HQ..." } # after this ID (exclusive)

Rationale

  • first/last: symmetric peers, both accept optional counts
  • --new: unambiguous "only new items" (NATS uses this)
  • --from/--after: explicit inclusive/exclusive (like AWS Kinesis)
  • start: cleaner than resume_from, works for both initial and resume cases

Feedback?

Does this vocabulary make sense? Any confusing terms?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment