Skip to content

0.2.0 - 2026-10-13

Choose a tag to compare

@marcel marcel released this 13 Oct 22:41
· 3 commits to main since this release

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

File Platform Checksum
particle-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
particle-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
particle-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
particle-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
particle-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum
particle-cli-x86_64-unknown-linux-musl.tar.xz x64 MUSL Linux checksum