Bounded graph search
Search people, talks, events, companies, projects, topics, photos, and videos without downloading the corpus.
Search developer-community work, follow topic paths, publish connected records, import talks, and manage your graph with a fast native client.
$ cargo install bay-cli
$ bay graph -k talk -q rust -l 3
{
"entities": [
{ "kind": "talk", "name": "…" }
],
"nextCursor": "…"
}Four steps, then explore
You need a devreal account and Rust 1.88 or newer with Cargo. New to Rust? Install the current stable toolchain from rustup.rs ↗.
bay --versionBay is published as the bay-cli crate and installs one native executable named bay.
cargo install bay-cliSign in to My graph, open Bay CLI access, and create a revocable member key. It is shown once.
Create a key ↗Save the key in Bay’s local named profile. Replace the example with the key you just created.
bay login --token bay_sk_...Start with a bounded search. Bay reports the response and your exact weighted quota usage.
bay graph --kind talk --query rust --limit 10Search the curated ontology, list its newest connected talks, and open an exact graph record. Add --json for formatted output or --with-meta for request and quota metadata.
bay topic search "Rust AI"
bay topic contents rust -k talk -s newest -l 10
bay entity show talk:known-id --json
bay quota statusKey safety: Bay stores the token in your local platform configuration. Revoke it from My graph if a machine or key is no longer trusted. On shared shells, use the BAY_API_KEY environment variable so the token does not appear in command history.
Human workflow, scriptable output
Search people, talks, events, companies, projects, topics, photos, and videos without downloading the corpus.
Browse the published ontology, inspect newest content, save private interests, and suggest genuinely missing topics.
Create records, import YouTube talks idempotently, claim your person node, and preserve provenance.
Preview Luma ingestion, commit exact review hashes, version event edits, and run scoped administrator reviews.
Canonical Bay manual
This is the full canonical manual shipped with Bay—not an excerpt. It is also available in your terminal with bay man, or as a system manual after bay man install.
bay - explore and maintain the devreal developer-community graph
bay [-j|--json] [-M|--with-meta] COMMAND [ARGUMENTS] [OPTIONS]Bay is the Somme-derived command-line client for devreal.ai. It explores people, events, talks, companies, projects, topics, photos, and videos; navigates the curated topic ontology and manages private interests; creates connected records; previews and commits reviewed Luma event ingestion; submits LinkedIn-backed person claims; performs versioned event edits; shows and requests fair-use allowance; and exposes the administrator review workflow.
Create a revocable API key in the devreal account dashboard before logging in. The server accounts for weighted work atomically across every key and browser session belonging to an account. An administrator's ordinary key remains a non-admin member key on the finite signed-in or claimed-person tier. Only an unexpired key with the explicit admin:quota-bypass and admin:write scopes and a total lifetime no longer than 24 hours has no daily denial and may run administrator commands; endpoint, per-minute, concurrency, and operation caps still apply. Bay can import a whole YouTube talk archive while reusing recordings already indexed from Functional.TV.
-j, --json-M, --with-meta{"data": RESPONSE, "meta": {"requestId": ID, "rateLimit": ...}} so scripts can read request and weighted-quota metadata from standard output. Without this opt-in wrapper, Bay writes the server response body unchanged. Quota information is also reported to standard error in both modes.-h, --help-V, --versionbay login -t|--token KEY [-u|--api-base URL] [-a|--account NAME] [-e|--email EMAIL]Validate and save a bay_sk_ key. The API base defaults to https://devreal.ai, the local profile to default, and --email stores optional local metadata. API bases must use HTTPS. HTTP is accepted for local development only when the parsed host is exactly localhost, 127.0.0.1, or ::1, with an optional port; host suffixes, lookalikes, URL user information, queries, and fragments are rejected before Bay sends the bearer key. This validation also applies when loading an older saved profile or BAY_API_BASE. BAY_API_KEY supplies the token when --token is omitted. Login validation calls the authenticated quota-status endpoint. It costs one unit from a small, independent recovery bucket rather than the graph-data allowance, so it remains available after data-quota exhaustion. A temporary validation failure is reported as such rather than being mislabeled as a rejected key.
bay logout [-a|--account NAME]Remove the selected profile's saved token while retaining its local account record.
bay account [ls|use NAME]List profiles and authentication state or select an active profile. The active profile is marked with *.
bay configPrint the active account, configuration path, and saved-account count without exposing keys.
bay quota status [-j|--json] [-M|--with-meta]Fetch the active account's current allowance from GET /api/account/quota. The response reports rolling daily data usage, the independent recovery bucket, minute and concurrency state, third-party discovery allowance, recent temporary grants, and the next rolling expirations supplied by the server. This recovery action costs one recovery unit rather than one graph-data unit, so it remains available when the data allowance is exhausted. Bay prints the response unchanged unless --with-meta is selected and does not cache, retry, or transform it.
bay quota request -u|--units UNITS -d|--duration-hours HOURS -r|--reason TEXT [-j|--json] [-M|--with-meta]Submit a temporary daily-allowance request to POST /api/account/quota/request. --units is required and accepts 100 through 10,000 additional rolling daily units. --duration-hours is required and accepts 1 through 72 hours. --reason is required; after trimming, the server requires at least 20 characters describing the legitimate research or maintenance task and stores at most 2,000 characters. The request costs one recovery unit.
An administrator must approve the request before it changes the allowance. Only one request may be pending or submitted per rolling 24 hours; the API returns 409 when that rule prevents another submission. A grant raises only the rolling daily data allowance for its approved window. It does not change minute, concurrency, discovery, response-size, endpoint, or operation caps. Bay submits once and displays the resulting 202, validation error, conflict, or typed quota error; it never retries or chooses an alternative automatically.
bay graph (-q|--query TEXT | -k|--kind KIND[,KIND...] | -r|--recent DAYS|DATE | -m|--mine) [-l|--limit N] [-c|--cursor TOKEN] [-j|--json] [-M|--with-meta]Search the community graph with bounded, server-side filters. At least one of --query, --kind, --recent, or --mine is required; Bay rejects broad unfiltered listings before opening a connection. --query searches names and descriptions. The deprecated -s and --search spellings remain aliases for -q, --query. Valid kinds are person, event, talk, company, project, topic, photo, and video; use commas to select several. --recent accepts an ISO date or a number from 1 to 3650 meaning the last N days. --mine restricts results to claimed, created, or affiliated records and requires an authenticated account.
--limit is 25 by default and accepts 1 through 50. Search costs 10 units for up to 25 returned rows or 20 units for 26 through 50. A response can include an opaque next cursor. Continue with --cursor while repeating the same query, kind, recency, My Graph, and limit values: cursors are signed, short-lived, and bound to those filters. Bay never downloads a corpus and filters it locally, never follows cursors automatically, and never hides a partial page. It writes the complete response unchanged, including pageInfo when the API emits it and the currently supported top-level nextCursor; in normal compact mode, a continuation notice with the next cursor is also written to standard error.
bay topic browse [-j|--json] [-M|--with-meta]Fetch the currently published topic ontology from GET /api/topics. The response contains one versioned snapshot with each concept's id, slug, name, summary, area, focus, or topic level, selectable state, approved aliases, parent and child ids, and primary path. The ontology is a polyhierarchy: a concept may have more than one parent even though the interface presents one upper, middle, and lower band at a time. Concept ids are stable server-assigned ontology:* keys: copy them from browse or search rather than deriving them from a name. Use those ids for interests and parent selection; use the public slug with bay topic contents.
The server returns the bounded published snapshot in one request so clients can present the same three progressive bands without crawling graph records. A separate first-party browser endpoint issues path-measurement tokens; Bay does not submit fabricated path telemetry. This curated catalog does not consume community-record discovery slots. Browsing costs five weighted units.
bay topic search QUERY [-j|--json] [-M|--with-meta]Match a 1–80 character query against canonical topic names and approved aliases through GET /api/topics?q=QUERY. Exact canonical or alias reuse wins over prefix, token, and similarity candidates. Results include match evidence and the concept's full path so a human can distinguish similarly named topics without seeing the whole ontology tree. Short names such as R, Go, or C are exact-only to avoid unsafe fuzzy matches. Search costs five weighted units and returns at most the server's bounded candidate set; it has no automatic pagination or corpus download.
Run this before proposing a topic. A response with exactMatchId identifies an existing concept that should be selected instead. canSuggest says whether the proposal gate can be opened; it is not a promise that a later proposal will be accepted.
bay topic contents TOPIC-SLUG [-k|--kind KIND] [-s|--sort ORDER] [-l|--limit N] [-c|--cursor TOKEN] [-V|--ontology-version UUID] [-j|--json] [-M|--with-meta]List graph records connected to a published topic through GET /api/topics/:slug/contents. bay topic show is a visible alias for this command. --kind accepts all, talk, person, event, project, company, video, or photo and defaults to all. --sort accepts newest, relevance, strength, or name; newest is the default and orders records by their domain date, then activity date, with a stable id tie-breaker. The other rankings are explicit opt-ins. --limit accepts 1 through 50.
The response includes the topic, bounded records, per-kind counts, total count, ontologyVersionId, and an opaque nextCursor when another page exists. Continue by repeating the same slug, kind, sort, and limit with both -V, --ontology-version and --cursor. The version pin keeps the sequence on its immutable archived snapshot if a newer ontology publishes between requests. Bay prints an exact continuation reminder in compact mode but never follows the cursor automatically. Each page costs ten weighted units.
bay topic suggest NAME -p|--parent CONCEPT-ID -s|--summary TEXT [-N|--confirmed-no-match] [-j|--json] [-M|--with-meta]Suggest a topic that is genuinely absent from the current ontology through POST /api/topics/proposals. --parent is the existing area or focus concept id where the proposal belongs. --summary must contain 12–500 characters explaining the distinct meaning. The server normalizes the name and reconciles it against canonical names and approved aliases again at write time.
Do not start with --confirmed-no-match. If the server returns similar existing concepts, inspect them with bay topic search or bay topic contents. Select the existing concept when it fits. Only after that review, repeat the same suggestion with -N, --confirmed-no-match to attest that none is the intended concept. An exact unambiguous match is returned for explicit selection instead of creating a duplicate; suggesting never changes the account's interests implicitly. A genuinely new suggestion enters reconciliation and administrator review; it does not become a public graph node immediately. Submission costs five weighted units and Bay never retries a conflict or confirms a new topic on the user's behalf.
bay interests [ls|list] [-j|--json] [-M|--with-meta]List the active account's selected topic concept ids and records from GET /api/account/interests. The default command is ls; list is a visible alias. The server returns the newest selection activity first with a stable concept-id tie-breaker. Interests are private by default. Reading them costs one weighted unit.
bay interests set CONCEPT-ID... [-j|--json] [-M|--with-meta]Replace the complete private interest set through PUT /api/account/interests. Pass 1–100 active selectable concept ids; duplicate ids are removed while preserving their first supplied order. This is replacement, not addition: any previously selected id omitted from the command is no longer selected. The server validates all ids and applies the replacement atomically. Writing costs five weighted units.
bay interests set -C|--clear [-j|--json] [-M|--with-meta]Explicitly replace the interest set with an empty list. Bay requires --clear when no concept id is supplied and rejects mixing it with ids, so an accidentally incomplete command cannot clear interests.
bay entity show ENTITY-ID [-j|--json] [-M|--with-meta]Fetch one known public graph record from GET /api/entities/:id. The entity id is URL-encoded by Bay, so ids such as person:ada and ids containing slashes are sent safely. Exact detail costs 5 weighted units and returns { "entity": ENTITY_DETAIL } with the node, description, source URL, bounded properties, handles, claim state, up to 40 ranked connections, and up to 20 provenance sources. It is not a graph-export path. Bay preserves this body unchanged. Weighted metadata, low-allowance warnings, and typed 429 behavior follow the global output contract.
bay entity create KIND NAME [-s|--slug SLUG] [-d|--description TEXT] [-u|--source-url URL] [-i|--image-url URL] [-p|--properties JSON] [-c|--connect TARGET-ID:LABEL]...Create a graph entity. KIND is one of person, event, talk, company, project, photo, or video. Topics are reconciled ontology concepts rather than generic graph writes; use bay topic suggest so existing names and aliases are checked first. The server derives a slug when omitted. --properties defaults to {} and must be a JSON object. Repeat --connect to create up to 30 labeled edges; every value must include a target id and label. The parser splits the final colon, so person:ada:speaker targets person:ada with label speaker, while the incomplete person:ada is rejected. When an owned person creates a talk or video, devreal also adds its authored relationship.
bay claim [ls]List the active account's person claims and their name, affiliation, and review status.
bay claim add PERSON-IDClaim a person node using the LinkedIn identity already bound to the account. Normalized first and last name must match. A verified current company or a verified historical company overlapping dated graph work permits automatic approval; otherwise the claim enters administrator review.
bay claim remind CLAIM-IDRemind administrators about a pending claim. The first reminder becomes available 24 hours after submission, and subsequent reminders are limited to one per 24 hours. bay claim ls reports reminder_available_at and reminder_ready for clients that want to schedule this action.
bay event edit EVENT-ID [-n|--name NAME] [-d|--description TEXT] [-u|--source-url URL] [-r|--reason TEXT]Edit an event you created or one connected to an approved claimed person; administrators may edit any active event. The previous snapshot is appended to immutable version history. The server computes Levenshtein distance and normalized edit ratio; edits above the configured threshold notify administrators.
bay event ingest LUMA-URL [-u|--additional-url URL]... [-t|--talk TALK-ID]... [-m|--talk-map TALK-ID=CANDIDATE-KEY]... [-e|--event-id EVENT-ID | -N|--create-new] [-n|--name NAME] [-d|--description TEXT] [-s|--starts-at ISO-8601] [-f|--ends-at ISO-8601] [-z|--timezone ZONE] [-l|--location TEXT] [-i|--image-url URL] [-r|--review-hash HASH -c|--commit]Fetch a public Luma event and preview the normalized event, extracted source snapshots, agenda candidates, likely Functional.TV talk matches, possible existing event matches, and review warnings. Preview is the default and never changes the graph. This reviewed ingestion workflow currently requires an administrator Bay key. Repeat --additional-url for up to five public HTTPS agenda, announcement, or recap pages whose evidence should be reconciled with Luma. Repeat --talk for up to 50 existing public talk ids that should receive a presented at edge when committed. When automatic matching is absent or ambiguous, repeat --talk-map TALK-ID=CANDIDATE-KEY to bind a selected talk to one or more talkCandidates[].key values from the preview. Every mapped talk id must also be supplied with --talk; repeated mappings for one talk are grouped into its talkMappings array.
Use --event-id to select an existing event after reviewing the preview's event matches. Use --create-new to confirm that a similar name belongs to a separate recurring occurrence. These options are mutually exclusive. The name, description, start, end, timezone, location, and image options override extracted values in both preview and commit requests. --starts-at and --ends-at accept ISO 8601 date-times; an end cannot precede its start.
The preview response includes bounded normalized source text, selected talk titles and revisions, automatic or explicit agenda mappings, the selected target revision when applicable, and reviewHash, a digest of the exact proposed event, source evidence, merge-or-create choice, target revision, and talk connections. After checking the preview, repeat the same ingestion inputs, including every --talk-map, with --review-hash HASH --commit. Bay requires these two options together and then sends the hash with commit: true and reviewed: true. The server fetches and normalizes the sources again and commits only if the new digest matches; a changed source, selected talk, agenda mapping, input, or target is rejected without writes, after which a fresh preview is required. A matching commit can create or version the event, preserve source observations and URL aliases, and add the selected talk connections atomically. Luma source identity reuses the existing event on repeated commits. Name/date matches are suggestions only and require explicit --event-id to merge or --create-new to create a separate occurrence; a removed record, concurrent revision, or source attached to another event is rejected rather than reassigned.
bay talk import URL... [-s|--speaker PERSON-ID] [-c|--connect ENTITY-ID]... [-d|--date YYYY-MM-DD]Import up to 25 YouTube recordings in one request. Each URL may use the canonical, short, embed, live, or Shorts form. Devreal reuses an existing video or talk when present, reads public YouTube metadata for missing recordings, connects the talk to the account's verified person, and adds a recorded as edge to the video. Repeat --connect up to 30 times with event, company, project, topic, or photo ids; the server assigns the appropriate relationship label. --speaker selects one of the account's claimed people when it owns more than one. --date records a shared talk/event date in YYYY-MM-DD form.
The operation is idempotent by YouTube video id. The importer does not resurrect records marked unavailable in existing history.
bay admin reviewList pending person claims, open edit notifications, and temporary-allowance requests. The key must belong to an administrator account. Allowance-request entries include the id accepted by bay admin grant.
bay admin claim CLAIM-ID approve|reject [-n|--note TEXT]Approve or reject a pending person claim. Approval binds the person node unless another account already owns it.
bay admin grant REQUEST-ID -d|--decision approve|reject [-u|--units UNITS] [-j|--json] [-M|--with-meta]Review one pending temporary-allowance request through POST /api/admin/quota-grants/:id. The request id comes from bay admin review. --decision is required and accepts approve or reject. For approval, omit --units to grant the amount requested by the account or pass 1 through 10,000 to grant a reviewed amount instead. --units has no effect on a rejection. The approved grant uses the request's reviewed 1–72 hour duration; Bay cannot silently alter that window.
The key must belong to an administrator account. This operation costs five weighted data units and remains subject to minute, concurrency, and operation caps. Bay sends exactly one decision request and preserves normal response metadata and typed error behavior.
bay request get|post|patch PATH [-b|--body JSON] [-j|--json]Send a raw authenticated request for forward-compatible devreal tasks. --body must be a JSON object and is used by POST and PATCH.
bay man [show]Print this complete embedded section-1 manual.
bay man install [-d|--dir DIR]Install bay.1 using Somme's shared installer. Without --dir, standard Homebrew, local, user-local, and system section-1 directories are tried.
Successful remote quota, graph, topic, interests, entity, claim, event, talk, admin, and raw-request commands write the API response JSON to standard output. Local account, configuration, and manual commands retain their text output. --json changes only JSON indentation. --with-meta wraps an API response below data and adds meta.requestId plus meta.rateLimit.limit, remaining, resetEpochSeconds, unlimited, cost, retryAfter, warning, and tier. This wrapper is opt-in so existing scripts keep their response shape. Operational notices stay on standard error.
After a metered response, standard error reports the exact settled cost, remaining and total daily units, reset epoch, tier, and request id supplied by the server. Only a valid short-lived admin:quota-bypass key reports an unlimited daily allowance. The server's low-allowance warning is displayed; Bay also warns when the headers show 20 percent or less remaining even if an older server omitted the warning header.
An HTTP 429 remains a typed Somme API error and exits nonzero. Bay reports the limiting scope, requested cost, remaining units or shortfall, Retry-After, absolute retry time, request id, and every lower-cost alternative returned by the server. Alternatives are advice, not commands: Bay never runs one automatically. Retry-After is also advice; Bay does not sleep or automatically retry GET, POST, PUT, PATCH, or raw requests. Reduce the requested work or explicitly run it again after the reported time. Bay does not cache response bodies or ETags between invocations, so it does not issue conditional requests on the user's behalf.
API keys are generated with a bay_sk_ prefix, stored only as SHA-256 hashes in Neon, shown once, and independently revocable. The key binds all CLI actions to one devreal account, and creating another key does not create another allowance. Quotas use weighted units in a rolling 24-hour window: signed-in accounts receive 1,000 daily units and accounts with an approved claimed person receive 2,000. Administrator ownership alone does not change those finite limits. Unlimited daily use requires an unexpired key carrying admin:quota-bypass, owned by an administrator, with no more than 24 hours between creation and expiry. Administrator commands additionally require admin:write; ordinary administrator-owned keys cannot review or mutate administrative state. Per-minute, concurrency, endpoint-response, and operation caps still apply. Administrator status, scopes, and expiry are checked server-side and cannot be forged by a client.
Successful metered responses expose X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Cost, X-RateLimit-Tier, and X-Request-Id. A response below 20 percent also exposes X-RateLimit-Warning. A 429 additionally carries Retry-After and structured fair-use details. Costs are selected by the destination route; neither bay request nor a client-supplied value can lower them.
A LinkedIn-authenticated account can own one or more approved person claims. Automatic claim matching uses the identity-report first/last name and company-email workplace evidence. Historical affiliations stay in administrator review unless LinkedIn supplies a verified dated employment period that overlaps the talk. Affiliated event changes never erase prior versions. Large textual edits notify administrators, and historical audit rows remain intact.
BAY_API_KEYBAY_API_BASEBAY_API_KEY; it follows the same HTTPS or exact-loopback HTTP validation as --api-base.bay/config.tomlbay login -t bay_sk_example -a work
bay quota status -j
bay quota request -u 2000 -d 24 -r "Reconcile public conference talks and recordings"
bay graph -k talk -q wasm -l 25 -j
bay graph -k talk -q wasm -l 25 -c OPAQUE_NEXT_CURSOR
bay graph -r 30 -k event -M
bay graph -m -l 50
bay topic browse -j
bay topic search "Rust AI"
bay topic contents rust -k talk -s newest -l 25
bay topic contents rust -k talk -s newest -l 25 -c OPAQUE_NEXT_CURSOR
bay interests
bay interests set ONTOLOGY_TOPIC_ID ANOTHER_ONTOLOGY_TOPIC_ID
bay topic suggest "Agentic Rust" -p ONTOLOGY_FOCUS_ID -s "Rust patterns for building durable AI agents"
bay topic suggest "Agentic Rust" -p ONTOLOGY_FOCUS_ID -s "Rust patterns for building durable AI agents" -N
bay entity show person:ada -j
bay entity create talk "Graph operations in WASM" -u https://youtube.com/watch?v=example -c person:ada:speaker
bay talk import https://youtu.be/dQw4w9WgXcQ https://youtube.com/watch?v=aqz-KE-bpKQ -c event:devrelcon -c topic:developer-relations -d 2026-05-12
bay claim add person:ada
bay claim remind 5ea88c8e-3208-40e1-a44f-3cdd49b60fb8
bay -j event ingest https://luma.com/ai-zt65 -u https://example.com/agenda -e event:existing -t talk:session -m talk:session=org:querygraph
bay event ingest https://luma.com/ai-zt65 -u https://example.com/agenda -e event:existing -t talk:session -m talk:session=org:querygraph -r REVIEW_HASH -c
bay event edit event:devrelcon -n "DevRelCon 2026" -r "Official title"
bay admin review -j
bay admin grant 5ea88c8e-3208-40e1-a44f-3cdd49b60fb8 -d approve -u 1500
bay man install -d ~/.local/share/man/man1Zero indicates success. Nonzero indicates parser validation, a rejected broad graph listing, invalid topic or interest input, missing local credentials, rejected or revoked keys, HTTP or JSON failure, quota exhaustion (including typed 429 errors), authorization failure, graph validation failure, or manual installation failure.
somme(1), suffix(1), https://devreal.ai/cli, and https://devreal.ai.