No description
  • Rust 96.5%
  • Nix 2.1%
  • Just 1.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
natsukium 7c67e7880b
All checks were successful
ci / cargo fmt / clippy / test / deny (push) Successful in 2m19s
ci / cargo fuzz smoke (push) Successful in 2m4s
chore: move project notes to AGENTS.md and skills to .agents/skills
The collaborator notes and project skills were under Claude-specific
paths, so agents that follow the AGENTS.md / .agents/skills convention
could not find them. Moving the source files to those paths makes the
project instructions readable by any agent. .claude/skills is kept as a
symlink to .agents/skills so Claude Code still auto-loads the skills
without a second copy to keep in sync.

The product-shipped skill stays at skills/felis-cast and is linked into
.agents/skills, so its path in the release tooling does not change.

Rejected: keeping CLAUDE.md as the source, because it would leave the
notes readable by Claude Code only. Not yet done: a CLAUDE.md symlink
to AGENTS.md, which Claude Code needs to read the project notes at all.
2026-10-15 10:31:59 +09:00
.agents/skills chore: move project notes to AGENTS.md and skills to .agents/skills 2026-10-15 10:31:59 +09:00
.cargo feat(cast)!: redesign the CLI around felis's own command line 2026-10-14 22:46:59 +09:00
.claude chore: move project notes to AGENTS.md and skills to .agents/skills 2026-10-15 10:31:59 +09:00
.config chore: adopt felis's verification stack 2026-10-14 19:21:16 +09:00
.forgejo/workflows docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
crates docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
docs docs: restructure run-on sentences and eliminate em dashes 2026-10-15 10:08:49 +09:00
fuzz feat(cast)!: redesign the CLI around felis's own command line 2026-10-14 22:46:59 +09:00
skills/felis-cast docs: restructure run-on sentences and eliminate em dashes 2026-10-15 10:08:49 +09:00
.gitignore chore: ignore cargo-mutants output 2026-10-14 20:44:10 +09:00
AGENTS.md chore: move project notes to AGENTS.md and skills to .agents/skills 2026-10-15 10:31:59 +09:00
Cargo.lock feat(cast)!: redesign the CLI around felis's own command line 2026-10-14 22:46:59 +09:00
Cargo.toml docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
clippy.toml chore(fcast): adopt felis core's lint policy and clear it under -D warnings 2026-06-21 10:24:32 +09:00
CONTRIBUTING.md docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
deny.toml chore(fcast): adopt felis core's lint policy and clear it under -D warnings 2026-06-21 10:24:32 +09:00
flake.lock feat: felis-fcast — .fcast format, recorder, and replay design 2026-06-20 18:27:33 +09:00
flake.nix docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
justfile docs: fold the reference/explanation twins into single pages 2026-10-15 08:52:49 +09:00
LICENSE chore(fcast): declare the MSRV and ship the Apache-2.0 LICENSE file 2026-06-21 22:50:11 +09:00
README.md docs: clean up stale references, em dashes and line wrapping 2026-10-15 09:43:56 +09:00
rustfmt.toml chore(fcast): adopt felis core's lint policy and clear it under -D warnings 2026-06-21 10:24:32 +09:00

felis-cast

The .fcast session-cast format for felis, and the tools that record and replay it. Think asciinema's .cast, but the frames are the daemon→client messages of one felis session, in felis's own felis-json form, so a player replays through felis's real grid and renderer rather than re-parsing a terminal byte stream.

felis core stays unchanged: recording is a client attach that tees the frames. play and serve replay by standing in for the daemon, so an unmodified felis client renders the recording. Browser playback lives in felis-web-component, and felis-reel renders a recording to video.

Install

felis runs felis cast … by finding felis-cast beside its own binary or on PATH:

nix profile install git+https://git.natsukium.com/natsukium/felis-fcast

Quick start

# Record yourself: inside felis, this window switches to a new shell,
# and `exit` ends the recording and brings you back. (Outside felis, a
# new window opens instead.)
felis cast record demo.fcast

# Record one program, or a script with no window.
felis cast record demo.fcast -- htop
felis cast record --headless --max-duration 10 build.fcast -- cargo build

# Record a session you already have; Ctrl-C stops the recording, not the
# session.
felis cast record --session 1a2b demo.fcast

# Watch it. Space pauses, q quits, any key leaves the final screen.
felis cast play demo.fcast
felis cast play -s 2 -i 1 demo.fcast   # twice as fast, pauses cut to 1 s

# Serve it to any felis client over a socket.
felis cast serve --socket /tmp/replay.sock demo.fcast
felis --socket /tmp/replay.sock attach 1

A .fcast is NDJSON: a header on line 1, then [t_us, kind, msg] frames, so jq reads it. A Rust program reads one with the parser crate, which brings no felis dependency:

[dependencies]
felis-cast-format = { git = "https://git.natsukium.com/natsukium/felis-fcast", rev = "<commit>" }
let cast = felis_cast_format::parse(&text)?;
for frame in &cast.frames {
    // frame.t_us, frame.kind, and frame.msg (felis-json, opaque here)
}

Documentation

Each spec page ends with design notes: the rationale, the alternatives rejected, and when to revisit.