diff --git a/README.md b/README.md
index 782beab..d5b692c 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
-
+
**`hotspot` is an eBPF sampling CPU profiler for Linux: pick a process out of a live table, click it, and watch a flat self-time profile build in real time with user and kernel frames side by side.**
@@ -27,7 +27,7 @@ The thing you would otherwise reach for is `perf record` followed by `perf repor
## Questions this tool answers
**One process is pinning a core and I need to know which function, right now.**
-`yeet run gh:yeet-src/hotspot --tty`, click the process, and read the top of the table. Rows are self-time only, sorted hottest first, so the top row is where the CPU actually is rather than a caller that merely contains it. The first rows land in about a second at the default 499 Hz. See [What you're looking at](#what-youre-looking-at).
+`yeet run gh:yeet-src/hotspot`, click the process, and read the top of the table. Rows are self-time only, sorted hottest first, so the top row is where the CPU actually is rather than a caller that merely contains it. The first rows land in about a second at the default 499 Hz. See [What you're looking at](#what-youre-looking-at).
**I'm SSHed into a box where I can't install `perf` and there's no matching `linux-tools` package. Can I still profile?**
Yes, and this is the case the shape is for. `perf` needs a `linux-tools` build matched to the running kernel, which is exactly what a minimal or slightly-behind image doesn't have. `hotspot` needs the yeet daemon and this script; the sampler is a CO-RE BPF program, so there's no per-kernel recompile and nothing to match. It draws in the terminal you're already in, so there's also no port to forward.
@@ -72,8 +72,8 @@ Not directly. `hotspot` is a mouse-driven TUI with no headless mode and no `--js
## Quick start
```sh
-curl -fsSL https://yeet.cx | sh # install yeet, once
-yeet run gh:yeet-src/hotspot --tty # clone, build and run in one step
+curl -fsSL https://yeet.cx | sh # install yeet, once
+yeet run gh:yeet-src/hotspot # clone, build and run in one step
```
[Manual install guide](https://yeet.cx/docs/install/manual-installation?utm_source=github&utm_medium=readme&utm_campaign=hotspot) | Linux only
@@ -86,13 +86,13 @@ Working on the script itself instead of just running it? Clone it and build in p
```sh
git clone https://github.com/yeet-src/hotspot && cd hotspot
-make # compile bin/probe.bpf.o + bundle the JS (toolchain auto-fetched)
-yeet run . --tty # the live process table; click a process to profile it
+make # compile bin/probe.bpf.o + bundle the JS (toolchain auto-fetched)
+yeet run . # the live process table; click a process to profile it
```
With no flags you land on the process table: every process with an executable, sorted by name. Kernel threads are filtered out because they have no `exe` and no user stacks. Click a row to select it, click the selected row (or `⏎`) to start profiling, and the pane becomes a live profile. No sampling happens until you open a process.
-Script flags go **after `--`** so the runtime routes them to the script rather than consuming them itself, which is the most common first-run mistake. Note that `--tty` is a flag to `yeet run` itself and therefore goes *before* the `--`.
+Script flags go **after `--`** so the runtime routes them to the script rather than consuming them itself, which is the most common first-run mistake. Flags belonging to `yeet run` itself (`--quiet`, `--watch`, and so on) go *before* the `--`.
| flag | default | meaning |
| --- | --- | --- |
@@ -103,9 +103,9 @@ Script flags go **after `--`** so the runtime routes them to the script rather t
```sh
R=gh:yeet-src/hotspot
-yeet run $R --tty -- --freq 997 # sample harder
-yeet run $R --tty -- --repo torvalds/linux --rev v6.12 # link kernel rows to a tag
-yeet run $R --tty -- --repo me/svc --strip /build/src/ # bridge a container build path
+yeet run $R -- --freq 997 # sample harder
+yeet run $R -- --repo torvalds/linux --rev v6.12 # link kernel rows to a tag
+yeet run $R -- --repo me/svc --strip /build/src/ # bridge a container build path
```
(From a clone, `.` replaces `gh:yeet-src/hotspot` in any of these.)
@@ -126,7 +126,7 @@ Read AGENTS.md first, then:
something to show on an idle box:
make demo
./demo/cafe &
-4. Run: yeet run . --tty
+4. Run: yeet run .
5. Navigate to the `cafe` process with the arrow keys and press Enter.
Confirm that within a few seconds you see rows with real function names
(toil, grind_beans, steam_milk, tamp_layer) and non-zero sample counts.
@@ -163,29 +163,15 @@ The mental model for what `hotspot` measures, and what that does and doesn't tel
Two screens. The process table:
-```
- hotspot · 214 processes click/⏎ profile · r refresh · q quit
- 1041 cafe /home/dev/hotspot/demo/cafe
- 892 containerd /usr/bin/containerd
- 1518 node /usr/lib/node_modules/.bin/node
- 734 postgres /usr/lib/postgresql/16/bin/postgres
- 1 systemd /usr/lib/systemd/systemd
-```
+
+
+
Then the flat profile, once you open one:
-```
- cafe (1041) · sampling 499 Hz (cgroup) ←/esc back · f flame · t stream · q quit
- % samples ● function · 4,812 samples · 63 pcs symbolized
- 31.4% ██████████████ 1511 ● toil
- 18.2% ████████ 876 ● steam_milk
- 12.7% █████▌ 611 ● knead_dough
- 9.1% ████ 438 ● grind_beans
- 6.3% ██▊ 303 ● tamp_layer
- 4.8% ██▏ 231 ● __arch_clear_user kernel
- 2.1% ▉ 101 ● ??
- ● cafe ● libc.so.6 ● kernel
-```
+
+
+
The **header** carries the target, the sampler's state (`arming sampler…`, `sampling 499 Hz (cgroup)`, or a probe error), and the keys for this view. The **status line** repeats the column layout and the running totals: cumulative samples and how many distinct PCs have been named so far. The **table** is one row per function, self-time only, hottest first. The **legend row** at the bottom keys the colored dots to the object each function lives in.
@@ -243,7 +229,7 @@ The **stream view** (`t`) is a live flame chart where x is time: one column per
When the target binary carries DWARF, each row knows the `file:line` of its **hottest** PC, meaning the hottest line inside the function rather than its declaration. Pass `--repo` and those become clickable links:
```sh
-yeet run . --tty -- --repo me/service --rev deploy-2026-08-01
+yeet run . -- --repo me/service --rev deploy-2026-08-01
```
Function names then paint as OSC 8 hyperlinks (ctrl or cmd-click in most terminals), and `o` copies the selected row's URL to your clipboard via OSC 52.
@@ -348,7 +334,7 @@ An idle box makes a boring profiler. `demo/` holds two synthetic CPU burners who
```sh
make demo
./demo/cafe & # or ./demo/patterns
-yeet run . --tty # click `cafe` in the process list
+yeet run . # click `cafe` in the process list
```
`cafe` simulates a café rotating through three shifts every four seconds, each burning CPU in its own call subtree, with a twelve-frame recursive tower in the espresso machine. It's the better single take: three distinct subtrees in flame mode and four-second bands sliding past in stream mode.
@@ -392,7 +378,7 @@ There's no capture script; [`demo/README.md`](demo/README.md) has the recording
That is a clone-authentication failure, not a script problem. `gh:` shorthand tries SSH first
(`git@github.com:yeet-src/hotspot`) so private repos work with your own keys, then retries over
HTTPS. If neither has a usable credential you get this. Check `ssh -T git@github.com` succeeds,
-or clone it yourself and run `yeet run . --tty` from the directory.
+or clone it yourself and run `yeet run .` from the directory.
**Why is the top row `??` with a spinner that never resolves?**
A spinner means queued, and a spinner that persists means the batch failed rather than that it's slow. The status line shows `sym: ` when symbolization errored; the most common cause is the process exiting while being profiled, since the resolver reads its live maps. Reopen the process.
diff --git a/assets/hotspot-flat-profile.gif b/assets/hotspot-flat-profile.gif
new file mode 100644
index 0000000..0f31854
Binary files /dev/null and b/assets/hotspot-flat-profile.gif differ
diff --git a/assets/hotspot-process.gif b/assets/hotspot-process.gif
new file mode 100644
index 0000000..1b2eae8
Binary files /dev/null and b/assets/hotspot-process.gif differ
diff --git a/assets/hotspot.gif b/assets/hotspot.gif
index df4d47b..bf01e38 100644
Binary files a/assets/hotspot.gif and b/assets/hotspot.gif differ
diff --git a/demo/README.md b/demo/README.md
index 846999a..484fb48 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -5,9 +5,9 @@ idle box. Both are built for recording: their call graphs are designed so the
flame view has structure and the stream view has motion.
```sh
-make demo # builds demo/cafe and demo/patterns
-./demo/cafe # in one shell
-yeet run . --tty # in another: click `cafe` in the process list
+make demo # builds demo/cafe and demo/patterns
+./demo/cafe # in one shell
+yeet run . # in another: click `cafe` in the process list
```
Both are built `-O0 -g`: the stack walk needs frame pointers, and the whole
@@ -54,7 +54,7 @@ that produces a readable GIF:
make demo
./demo/cafe & # or ./demo/patterns
# resize the terminal to ~100x30, then record:
-yeet run . --tty
+yeet run .
```
A tour that fits in ~20 seconds, in the order that reads best: