Release Notes
Added
particle docs reads the Particle documentation as markdown, with no key:
particle docs lists every page, particle docs quickstart prints one, and
particle docs errors/<error_code> explains an API error.
particle doctor checks that everything is ready (version, API, key,
project, config, PATH, tab completion) and says how to fix what isn't.
--json gives agents the same report.
particle guide prints a quick start for agents: how output, errors, names,
and paging behave, and what to run first. particle with no terminal prints
it too.
particle schema <command> shows what a command returns, from the live API
spec and with no key: on a terminal, every field as a --jq path with its
type; in a pipe or with --json, the JSON Schema.
particle completion install sets up tab completion for zsh, bash, or fish
in one step (uninstall reverses it). Completions load on the first Tab, so
shells start as fast as before, and they always match the installed version.
The Homebrew formula now installs completions too, and particle doctor
says when they aren't set up.
particle alert create takes --role (which speaker roles to watch),
--language en,de, and --slack <connection>/<channel> (a channel id or
#name). Every flag has help.
particle alert preview "Sam Altman" --speaker takes the same flags as
alert create, waits for the result (--no-wait to skip), and shows the
match count, a day-by-day bar, and the latest matches as a table
(alert preview-result too). --days sets the window.
particle alert update takes create's flags too: WHO, --email,
--webhook, --slack, --cadence, --role, --language,
--relevant/--no-relevant, and --popular/--no-popular. The filter
flags change the alert's current filters one at a time instead of
replacing them all. An update with nothing to change is an error.
particle alert pause <id> and particle alert resume <id>.
-o tsv: rows with no header or quoting, for cut and while read.
--columns in a pipe prints TSV instead of ignoring the flag, so
particle podcast sponsors lennys --columns sponsor.name,ad_count | sort -t$'\t' -k2n
works.
particle commands --json is complete enough to drive the CLI: it is built
from the same command tree as --help, so it includes short flags, aliases,
--no- forms, porcelain flags (--about, --speaker, --latest, …), which
arguments take names (resolves), where each argument goes (in), usage
lines that match --help, examples, and the shortcuts and built-ins
(operation_id: null). Body fields are listed in args with in: "body".
particle feedback: report a bug (--bug), suggest an idea (--idea), or flag wrong data (--data <name|id|link>) straight to the Particle team.
--last attaches the previous command: its arguments, exit code, error code, and trace ids. Keys and your home directory are scrubbed.
- On a terminal you see exactly what will be sent before it goes. Agents send right away, and
particle guide invites them to.
- Until the feedback service is live, you get a pre-filled GitHub issue to submit instead.
- Unexpected errors now end with
Report it: particle feedback --bug --last.
particle auth login signs you in through the browser: it shows a code,
opens platform.particle.pro, and saves the key Particle issues for this CLI
once you approve (signing up works too). Without a browser (SSH, an agent)
it prints the link and code to open on any device, and waits.
particle auth logout revokes that key. Use --paste or --with-token
for a key you already have.
- On a terminal,
particle transcript <episode> starts by naming the episode
(title · podcast · date).
particle episode feed --follow keeps polling (every 60 s, or --interval)
and prints new episodes as they arrive.
Changed
- Help speaks CLI instead of HTTP: descriptions name commands and flags
(particle podcast search, --include via, --keyword-match,
--no-current-only) where they used to say GET /v1/podcasts/search,
include=via, and keyword_match. particle commands --json gets the same
text.
particle mentions --help (and every noun with a default command) shows
that command's flags and examples, not just the list of subcommands.
- Built-ins (
auth, config, completion, docs, …) no longer repeat ~40
lines of output, paging, and global flags in their help; one line points to
particle --help. resolve and api keep the flags they use.
particle --help groups the 25 resources by topic (podcasts, people and
companies, mentions and charts, advertising, alerts), and wrapped
descriptions stay in their column.
- Flag help: date flags mention
30d, 6mo, and today; booleans that
default to on say how to turn them off (--no-current-only), including
request-body booleans; placeholders are words (<STANDING>, <ID>) instead
of <GUEST_STANDING> and <VALUE>; --help shows defaults that only -h
showed, and neither repeats one the text already states; --format is under
Output and --project under Global options; and an argument that resolves
names says so.
- Relative dates of a day or more (
--since 7d, 30d, 6mo, 1y) are sent
as a UTC date instead of a timestamp to the second, so they hit the API's
daily snapshots and caches: particle ads leaderboard --since 7d went from
about 10 s to 0.2 s.
- A server error that took 20 s or more is no longer retried, and no retry
starts after 30 s in total, so a failing endpoint costs one slow attempt
instead of three in a row.
-v no longer shows a price on failed calls; they aren't billed.
- The same filter has the same flags on every command:
-p/--podcast wherever
there's --podcast-id, --since/--until wherever there's
--published-after/--published-before (and on guest list for
--appeared-since), -e/--episode, -k/--keyword, --entity, --company,
--person, --publisher, --sponsor, --clip, --topic, --category for
--category-slug, --lang, --occupation and --field. So particle episode list -p lennys --since 30d and particle mention timeseries -p lennys --entity sam-altman work like search and mentions always did.
particle webhooks works like particle webhook, and occupation search and
field search like their list commands, as company search does.
- The argument a command is about can be given without its flag:
particle mention timeseries "Sam Altman", particle podcast mentions all-in "Sam Altman", particle sponsor list shopify, particle publisher list iheart, particle guest list altman, particle occupation list cardio,
particle topic list technology, particle webhook create https://…,
particle transcription create <episode>, particle episode archive-download 2026-09-01. The flags still work.
podcast lookup, episode lookup and entity lookup take identifiers and
links as arguments, several at once or - for stdin. All-digit podcast
identifiers are looked up as Apple ids, so particle podcast lookup 1627920305 finds Lenny's Podcast instead of nothing.
podcast mentions, mention timeseries and mention share-of-voice say
"who should mentions be found for?" before calling the API when no one is
named, instead of returning its 422.
- Decimals in tables and cards are rounded to two places (three below 1), so a
score reads 0.984 instead of 0.9843888878822328. Curated views can now
show percentages (43.2%), clock positions (41:12, 0:03.250), sizes
(1.2 MB), and signed changes (+3).
- Tables for commands without a curated view now say what each row is about:
particle ads leaderboard shows the sponsor, podcast related the
podcast, and company competitors the company, instead of bare numbers or
{…}. Columns that are the same on every row are left out, timestamps show
as dates, and -o csv uses the same columns. When a table doesn't fit,
numbers and the title stay readable and the rightmost columns are left out.
- Cards never print
{…}: lists of objects are small tables (particle stats, top sponsors, external links), and time series show their latest
periods with a bar. A card is headed by the publisher, person, or company
it's about, and long text such as bias reasoning is shown in full.
- Podcast and episode lists name what each row is about:
podcast related,
recommended-guests, recommended-sponsors, sponsors, mentions,
external-links, ratings, guests, rankings, rankings-history,
podcast list, podcast topics, transcription list, and episode entities, related, expertise, ads, clips, segments, speakers,
topics, feed, clip list and segment list. Before, many showed only
scores and counts (SCORE BAND / 0.98 strong). Offsets read 44:54,
ratings show stars and dates, and -o csv gets the same columns plus the
wide ones. -o wide episode lists no longer squeeze titles for the slug.
- Names resolve more carefully. A literal name match beats an alias hit, a
match is never auto-accepted over one with far more coverage (Sam no
longer means Samoa, Jensen no longer means a person no episode mentions),
and a clear leader is accepted when every word matches (joe rogan, nvid).
Candidates are listed by coverage, with literal matches first, and --first
takes the top of that list.
- A name with only lookalike matches now exits 4 (
no company named "…",
with suggestions) instead of 5. A single candidate reads "did you mean".
Error JSON lists each candidate as {id, name, kind, episodes, match} with a
short description, instead of the full record.
- The resolution note on stderr is skipped when the input was already the
slug, and keeps the episode count when the answer came from the cache.
- Deleting on a terminal names what was removed:
✓ Deleted webhook connection "ci" (2XzwAEM…) instead of a deleted yes card, and the confirmation asks
about it by name. Pipes still get the API's response.
particle webhook create and rotate-secret warn on stderr that the
signing secret won't be shown again.
particle slack initiate is hidden: connecting Slack is an OAuth install
done in the dashboard, and running it now says where to go instead of
failing at the API.
particle commands lists shortcuts and built-ins too, aligns prices, says
"free" for free calls, marks hidden commands with --hidden, and says so
when nothing matches.
particle guide promises only what's true today. particle schema gives --jq paths on a terminal and the JSON Schema in a pipe. particle commands --json lists API commands, while built-ins and shortcut flags are in --help. CLI-only error codes have no docs page. Exit codes 1 and 130 are listed.
- Search and mentions headers show the short episode id,
§ lines carry the
segment id (so particle segment transcript <id> is reachable), ⋯ marks a
jump between lines that aren't next to each other, and on a terminal the
results end with where to read on: → particle transcript <id> --from 0:38.
search --about and --speaker with a person send the knowledge-graph
entity their profile links to (--about "David Sacks" went from 0 results
to 3), and transcript --speaker takes a person's slug or id as well as a
name.
-n N works on every list: on commands whose endpoint returns its whole list
at once (chart list, webhook list, …) it keeps the first N items instead
of failing with "does not take --limit".
- "Showing N. More available" is shown only when you didn't pass
-n.
search and mentions tables (-o table, --columns) and CSV have one
row per matching line: date, podcast, episode, time, speaker, the line, and
the episode id. --format compact on a terminal shows just the matching
lines under each episode.
alert create, preview, and update list their everyday flags
(--email, --speaker, --role, …) before the raw request-body fields.
Fixed
- A page whose
data is null prints "No results." instead of a card
reading has more no (particle podcast rankings joe-bogan).
- Episode links work wherever an episode goes:
particle episode,
particle transcript, and every episode subcommand take a YouTube,
Spotify or Apple Podcasts episode link. They used to 404.
- Apple Podcasts and Spotify show links resolve as podcasts whatever
resolve -t says (particle resolve <apple link> found nothing), and an episode link
in a podcast slot stands for its show. A show link where an episode goes
says to use particle podcast episodes.
segment transcript, clip transcript, embed clip-transcript, and
episode transcript-preview read like particle transcript: the dialogue
view on a terminal (segment and clip times are labeled as relative), and
-f text|srt prints the text itself, even into a pipe. They used to show a
card that cut every line short, and -f srt printed JSON.
episode transcript-mentions <episode> [entity] takes the entity as an
argument (a name works) and shows the lines around each mention, like
search; without an entity it lists what the episode names and how often.
It used to print a column of counts.
episode transcript-preview --at and episode transcript-words --start/--end take mm:ss and h:mm:ss, like transcript --from.
transcript --from/--to keeps every line that overlaps the range. The API
returns only lines wholly inside it, so --from 10:00 --to 10:30 used to
print nothing when two long lines crossed those edges. An empty range now
says so ("No lines between 10:00 and 10:30"), for --format text too, and
--from after --to is a usage error.
particle completion --help no longer says the shell installer sets up
completions (Homebrew does; elsewhere, run particle completion install),
and particle doctor --help lists every check and exit status.
particle alert create --speaker (and --kind PODCAST_SPEAKER) watches
guest, panelist, correspondent, and audience appearances only. It used to
fire on every clip of the person played on someone else's show: a week of
Sam Altman was 14 matches, all soundbites.
- Usage errors (an unknown flag, a bad value, a missing argument) are JSON on
stderr in a pipe or with --json, like every other error: usage_error,
exit 2, with the command's usage and valid_values or a suggestion when
there is one. On a terminal they stay readable text, without echoing the
flags you passed in the usage line, and a short flag the command lacks
(guest appearances -p) names the flag to use instead of suggesting -- -p.
- Every JSON error carries its next step as
resolve: {message, command?, url?}, including a missing API key (particle auth login), so agents read
one field.
- Typo suggestions name only commands you can see, and only close ones
(particle podcst → podcast, not the hidden podcasts).
- Every filter that takes a podcast, person, company, or entity now accepts a
name, as --podcast-id on search always did. Before, a name was sent as-is
and usually returned nothing with exit 0: particle episode list --person-id "Sam Altman", particle ranking list --podcast-id "Lenny's Podcast",
particle guest list --employer "Nvidia Corporation", particle mention timeseries --entity-id "Sam Altman", and about 25 more. List filters resolve
each item (particle episode feed --podcast-ids "Lenny's Podcast,All In"),
and particle person external-links "Sam Altman" works like the other
person commands.
particle mentions nvidia --company-id apple dropped apple silently. A
name that resolves to a company together with --company-id is now an error.
- Values that the API spells one way are now checked and sent in its spelling
wherever it lists them: particle segment list --type ad sent ad and took
39 s to return nothing (or a 500); it now sends AD and returns in 0.3 s.
The same goes for clip list --type, publisher bias-podcasts --bias,
chart get Movies, and positional values such as particle bias publishers left and particle suitability category-publishers Misinformation. A typo
lists the valid values instead of reaching the server.
--has-video and --has-ads work as switches (--no-has-video for
false); --has-video true still works.
- A profile that doesn't exist is an error instead of silently running with
no key and default settings: --profile, PARTICLE_PROFILE, and config use all check. auth login and config set still create one.
--since 1m is an error saying to write 1min or 1mo, since people mean
both; 90min and 6mo (or 6M) are unchanged.
config get output says auto when it's unset (and config list shows
it), config set output JSON stores json, config edit without a
terminal says where the file is instead of starting an editor into a pipe,
and config list -o csv is one row per setting.
--dry-run JSON shows placeholders as written (<resolve:"Hard Fork">,
<project of your API key>), not percent-encoded, and the paging warning
says "1 request".
- Not-found errors say where that kind of id comes from, instead of always
suggesting particle resolve, which only finds podcasts, people,
companies, and entities: particle episode segments <episode> for a
segment, particle sponsor list --query … for a sponsor, particle chart list, particle alert list, and so on. A podcast slug where an episode
goes suggests particle transcript lennys --latest.
- The API's next steps are CLI commands: an untranscribed episode suggests
particle transcription create --episode-id … instead of POST /v1/podcasts/transcription/requests, and endpoints the API names in an
error read as the commands that call them. JSON errors add the command as
resolve.command.
- A refused
PARTICLE_API_KEY says to fix or unset it, since particle auth login can't override it. The landing screen says "API key set" rather than
"Signed in", because it doesn't check the key; auth login --no-input says
why it won't prompt; and auth logout forgets the project that login
saved.
--columns takes the grammar of cli.toml columns, path[:format][|Header]
('podcast.title|Podcast,score:pct'), and [0] indexing. Headers that
would repeat (entity.name, entity.type.name) use two path segments, a
path that matches nothing gets a warning listing the response's fields, and
an unknown format fails before any request. With --columns, search,
mentions, and other commands with their own view print a table, and a
single object prints one row.
- Tables use
$COLUMNS when the terminal reports no width (macOS script,
some CI and IDE terminals), instead of 80.
- A 404 that isn't about the item itself no longer sets off a name search.
podcast bias joe-bogan ("bias analysis not available") and podcast mentions all-in --entity-id … ("entity not found") used to pay for a
podcast search, print a misleading resolution, and evict the cached name.
--first picks are no longer cached, so a later command without --first
isn't quietly given the same guess.
- A typo'd command says what was meant instead of failing oddly or looking
the word up as a name: particle episode transcrpt E and particle podcast epsiodes say "unknown command …; did you mean 'transcript'/'episodes'?",
and particle person list says the noun has no list. A name in several
unquoted words (particle podcast Lenny's Podcast) says to quote it.
particle help <command> works, particle transcript with no episode asks
"which episode?", and a noun with flags but no command or id (particle podcast --no-pager) shows the noun's help instead of missing <id>.
--jq supports @csv and @tsv (as well as jaq's @json, @text, @sh,
@base64, @html, @uri), and a bad expression says what's wrong and
where (`[` at column 6 is never closed) instead of printing a Rust
debug dump. It's checked before any request, so a typo no longer costs a
billed call (or a whole --all run) first.
-o jsonl --jq .slug runs the filter on each item, as you'd expect, instead
of on the envelope (which printed null); -o csv|tsv|table|wide with
--jq warns that -o is ignored.
- Responses that wrap their list (
transcript lines, lookup results, chart
entries, series buckets) give one jsonl line and one csv row per entry
instead of the whole object on one line or a field,value dump.
- When a search comes back empty, a terminal shows why, from the API's
diagnostics, and what to try next, with params named as flags: "No
results. The search text matches content, but --since excluded all of it."
particle feedback keeps private values out of reports.
- When the feedback service can't be reached, the public GitHub issue shows only the outline of the previous command (
particle api … -f …). There are no argument values or error messages, and on a terminal you're asked before your browser opens.
- The saved last command masks emails, tokens, URLs, query strings,
-f fields, and header values, and replaces the API key wherever it appears, including percent-encoded URLs.
- The saved file is readable only by you, and
PARTICLE_NO_HISTORY=1 turns it off.
- Config, credentials, and caches are written atomically and, where several
processes update them, under a lock: parallel config set or auth login
runs no longer corrupt config.toml or lose keys, and a full disk can no
longer empty the name cache. Parallel runs keep each other's cached names.
- A
config.toml that isn't valid TOML no longer stops every command,
--help and doctor included: defaults apply with a warning, and doctor
says how to fix it.
- Paging stops, with a warning, when the API repeats a cursor or returns an
empty page that still says there's more, instead of looping forever.
- A
PARTICLE_API_KEY with a trailing newline or spaces (a .env file, a
secret mount) works instead of failing as "could not reach the Particle API".
- The API key is never sent along a redirect to another site.
particle schema never cuts a --jq path: the column grows to half the
terminal, and a longer path gets its own line.
particle schema resolve describes resolve's JSON (.[].match.id, …);
other built-ins say they have no API schema instead of "no command".
- YouTube channel links (
youtube.com/@handle) resolve to the person again
where a person or company goes; in a podcast slot they still mean the show.
- An Apple Podcasts episode link (
…?i=…) where a podcast goes finds the show,
even when Particle doesn't have that episode.
particle mentions <podcast link> says it's a podcast and suggests
--podcast, instead of sending the show as the person to search for.
--dry-run with --columns prints the request instead of a blank line.
- A page that fails partway through
-n/--all no longer throws away the
pages before it: they're printed, with the --cursor to resume from, and
the command exits with the error's code.
- A few empty pages in a row (a filtered feed) no longer end a walk early;
five in a row still stop a walk that isn't moving.
- An error body that isn't JSON is cut to its start (a 20 MB error page no
longer lands on stderr), and a success that isn't JSON (a captive portal, a
proxy) says what came back and exits 8.
particle doctor reports a stalled API after 15 seconds instead of 120.
- A
credentials.toml that can't be read or parsed is reported ("couldn't
read the saved API key …") instead of looking like no key at all, and
particle auth login moves it aside (credentials.toml.unreadable) and
saves the new key.
episode stream and episode archive-stream show one line per episode on
a terminal instead of multi-KB JSON; -n N stops after N events. Pipes
still get every event's JSON, one per line.
episode feed ends, on a terminal, with the cursor to poll from next, and
says when nothing new arrived or when the feed needs a filter.
episode archive-download and podcast archive-download show progress,
resume an interrupted download, skip a file that's already current, and on
a terminal without -O save under the archive's published name.
particle schema transcript (and the segment, clip, and preview
transcripts, and alert delivery-payload) lists the response's fields; the
spec declares them as {}.
- A name nothing matches is a no-match error (exit 4) with a next step, the
same JSON shape as a name with only lookalikes.
- Help examples use values that work when pasted (full Spotify and Apple
links, no made-up project id, a date that returns results).
Install particle-cli 0.2.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/particlepro/particle-cli/releases/download/v0.2.0/particle-cli-installer.sh | sh
Install prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/particlepro/particle-cli/releases/download/v0.2.0/particle-cli-installer.ps1 | iex"
Install prebuilt binaries via Homebrew
brew install particlepro/tap/particle
Download particle-cli 0.2.0