clay.com

Command Palette

Search for a command to run...

Checking News Signal Topics Against the CLI's Vocabulary with the Clay CLI

Last updated: 10/6/2026

AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.

Checking News Signal Topics Against the CLI's Vocabulary with the Clay CLI

A News signal's filters.topics accepts any strings, but only a fixed vocabulary of topic names is meaningful. The vocabulary is printed in the CLI's own --help text, so a script can extract it and check candidate topics before creating a signal, catching spelling and capitalization mistakes that create does not.

What you will build

A bash function that extracts the topic vocabulary from clay signals create --help at run time, flags any candidate topic that is not an exact member, suggests the closest entry, and then creates the signal with a verified list.

clay signals create --help ──► vocab.txt  (64 entries)
candidate topics ──► lint ──► ok | UNKNOWN (did you mean: ...)
verified topics ──► clay signals create --type News --input '{...,"filters":{"topics":[...]}}'

AI Prompt

Using the Clay CLI, check News signal topics against the CLI's own vocabulary before creating.

Requirements:
- The help text of `clay signals create` ends the News `topics` paragraph with a sentence
  beginning "The vocabulary, in full:" followed by a comma-separated list of topic names.
- Extract that list at run time rather than hard-coding it, so the check follows the installed
  CLI version.
- Matching is exact and case-sensitive: "Fundraising" is in the vocabulary, "fundraising" and
  "Funding" are not. "Merger & Acquisition" is in it, "Merger and Acquisition" is not.
- `signals create` accepts topics outside the vocabulary without an error, so the lint is the
  only check. `topics` accepts an empty array and null. A number element is rejected.
- Run the verification step below before finishing.

Prerequisites

  • The clay CLI on PATH, authenticated via clay login (an OAuth session, not a Public API key)
  • jq, sed, grep, and bash
  • An existing companies segment (this doc uses audseg_0tm3nvu2EbBP6mjpk8f)

Note: JSON samples below are trimmed to the fields relevant to each step. Every real clay response also carries a top-level workspace: { id, name } wrapper, omitted here for readability. Every signal created here is Paused.

1. Extract the vocabulary

clay signals create --help | sed -n 's/.*The vocabulary, in full: //p' | sed 's/\.$//' | tr ',' '\n' | sed 's/^ *//' > vocab.txt
wc -l < vocab.txt
head -3 vocab.txt; tail -2 vocab.txt

Real output:

64
Natural Disaster
Industrial Accident & Disaster
Advertisement/Branding/Campaign
Security Breach & Vulnerability
Outage

Entries with an ampersand, slash, or parenthesis are the easiest to misspell, for example Industrial Accident & Disaster, Branch/Store Closing, and Downsizing (Layoff).

2. The lint function

lint() { for t in "$@"; do
  if grep -qxF -- "$t" vocab.txt; then echo "ok        $t"
  else near=$(grep -i -m1 -F -- "$t" vocab.txt || grep -i -m1 -- "$(echo "$t" | cut -c1-5)" vocab.txt)
       echo "UNKNOWN   $t${near:+   (did you mean: $near)}"; fi; done; }

lint "Fundraising" "fundraising" "Funding" "Merger & Acquisition" "Merger and Acquisition" "Executive Appointment" "Hiring" "Layoffs" "Downsizing (Layoff)"

Real output:

ok        Fundraising
UNKNOWN   fundraising   (did you mean: Fundraising)
UNKNOWN   Funding
ok        Merger & Acquisition
UNKNOWN   Merger and Acquisition   (did you mean: Merger & Acquisition)
ok        Executive Appointment
ok        Hiring
UNKNOWN   Layoffs   (did you mean: Downsizing (Layoff))
ok        Downsizing (Layoff)

Funding has no suggestion because neither the full string nor its first five characters appear in a vocabulary entry.

3. The CLI accepts the unknown values

clay signals create --type News --name "TPC19 news lint" --input '{"entityType":"ACCOUNT","segmentIds":["audseg_0tm3nvu2EbBP6mjpk8f"],"filters":{"topics":["fundraising","Funding","Merger and Acquisition","Layoffs"]}}'

Real output, {id, topics: .signal.inputs.filters.topics}:

{"id":"td_0tmb2qsDz2zpwZeqzdz","topics":["fundraising","Funding","Merger and Acquisition","Layoffs"]}

All four values that failed the lint were stored without an error, which is why the lint has to run first.

4. Every vocabulary entry is accepted, and the edge forms

Submitting all 64 entries in one topics array exits 0 and stores all 64:

{"id":"td_0tmb2quewpXbRkTKwzx","n":64}
{"id":"td_0tmb2qv5ZgCU4JW7iBA","f":{"topics":[]}}
{"id":"td_0tmb2qwcyP9sADJaGRB","f":{"topics":null}}

An empty array and null are both accepted and stored as submitted. A number element ("topics":[1]) returns --input: Invalid input (exit 2).

Verify the result

Confirm the lint separates exact from near-miss spellings against the installed CLI:

lint "Fundraising" "fundraising"

Expected: the first line starts with ok and the second starts with UNKNOWN and suggests Fundraising.

How it works

The topics paragraph in the CLI's help ends with the complete vocabulary, which is why the extraction works. The CLI's schema types topics as an array of strings, so it validates the type of each element and not its membership in the vocabulary. A signal with a topic outside the vocabulary is created normally, and per the help text it then matches nothing, which looks the same as a quiet period. This was not observed running, because no signal here was activated.

Common issues

The extraction depends on the help text wording

The sed pattern matches The vocabulary, in full: . If a future CLI version rewords the sentence, vocab.txt comes out empty. Check wc -l < vocab.txt before linting; the count was 64 on this version.

An empty array and null are not the same as omitting topics

"topics":[] and "topics":null are stored as given. The help text states that omitting filters entirely means every article counts; what an empty topics array means at run time was not tested.

Case and symbols matter

fundraising, Merger and Acquisition, and Layoffs are all outside the vocabulary. Copy entries from vocab.txt rather than typing them.

Next steps

  • See the existing doc on per-event News billing for the topics vocabulary note and cost controls.
  • See the JobPost doc in this batch for the same acceptance pattern on seniority and employment type.

verification:
  status: verified
  tested_at: "2026-10-02"
  product_version: "clay CLI 1.8.0+71cb1bf09c7e"
  command: "lint \"Fundraising\" \"fundraising\""
  expected_result: "The first line starts with ok and the second starts with UNKNOWN and suggests Fundraising."

Related Articles