@orangecollective/oc
v0.5.0
Published
Orange Collective in your terminal — the YC research agent, batch digests, and company context
Readme
oc
The OC-IDE research agent in your terminal: the same yc-research-agent, the same
models, the same @-mention context, and the same batch activity digest the web
app greets you with.
Install
Needs Node 22 or newer (Ink's floor — check with node -v).
npm i -g @orangecollective/oc
oc login # opens your browser to authorize this machine
ocUpgrade with the same command. oc --version prints what you have.
You need an Orange Collective account that belongs to at least one team — oc
exits with "Your account isn't on a team yet" otherwise. Run it in a real
terminal: Ink needs a TTY, so it can't be piped.
If the install fails with EACCES, your npm prefix is root-owned. Fix the
prefix rather than reaching for sudo, which leaves root-owned files that break
later installs:
npm config set prefix ~/.npm-global # then add ~/.npm-global/bin to PATHFrom source
For working on the CLI itself:
git clone [email protected]:davecyen/oc-ide.git
cd oc-ide/cli
npm run setup # install + build + link `oc` to this checkoutUse
oc login # authorize this machine in your browser
oc # greeting + digest, then chat
oc logout
oc --host http://localhost:3000 login # target a dev server (or set OC_HOST)In the chat:
| | |
|---|---|
| @name | mention a company, founder, batch or skill — it stays in your text, highlighted, and goes to the agent as context |
| / | open the command list (tab to complete) |
| /model [name] | switch model (no argument lists them) |
| /web | toggle web search |
| /team [slug] · /batch [W26] | change scope |
| /digest [-r] | re-run the digest (-r regenerates it server-side) |
| /activity [n] | the latest batch activity (default 10) |
| /activity on · off | the live ticker — new batch activity prints as it happens (on by default, polled once a minute) |
| /portfolio [team] | your fund's positions: deployed, priced-round MOIC, and each company's latest update |
| /updates [n] | the latest investor updates from portfolio companies, newest first (default 8) |
| /updates <company> | one company's progress — current focus, recent milestones, hiring, asks, recent updates (/updates @Halluminate works too) |
| /top [traction \| traffic \| stars] [n] | the batch page's leaders: stated traction, search traffic, GitHub stars |
| /fav <company> [in <folder>] | add a company to a favorites folder (/fav @Lyon works too; a folder that doesn't exist is created) |
| /unfav <company> | remove your favorite |
| /favs [folder] | list your team's folders, or one folder's companies |
| /new · /clear · /quit | |
| ? | shortcuts (on an empty prompt) |
| ↑ ↓ | history, or move through a list |
| esc | interrupt · close a list |
| ctrl-c ×2 | exit |
For LPs
oc is also the quickest way to keep up with the portfolio. On launch it tells
you how many investor updates have come in since you last looked:
◆ 4 new portfolio updates since you last looked — Halluminate, Mastra, Didit · /updates/updates reads them (newest first: headline, summary, key signals) and marks
them read; new ones print as a line while oc is open. /portfolio shows where
the fund stands, and /updates <company> shows one company's arc, including its
asks — the intros founders are looking for, where an LP can often help.
MOIC is priced-round MOIC only: it appears once a priced round converts the
SAFE, and until then a position is shown at cost (—). SAFE markups are never
shown. You can also just ask — "how is Halluminate doing?" or "which companies
raised this quarter?" — and the agent answers from the same data.
Activity rows led by an orange ◆ are things a teammate did (favorited a
company, made a folder, joined) — the same events the web app's Activity tab
shows. Rows led by · are the sync pipeline noticing a change (a new launch, an
edited one-liner).
Config lives in ~/.oc/ — credentials.json (session) and state.json (model,
team, batch, thread, which updates you've read), both 0600. Set OC_CONFIG_DIR to relocate them.
Development
npm run dev # tsx, no build step
npm run typecheck
npm run build # esbuild → dist/oc.jsNotes for anyone editing this:
- All key handling lives in one
useInputinsrc/ui/App.tsx. Editing and the pickers are interleaved, and two competing handlers race on the same keypress. Ctrl-C is handled there too, which is whyoc.tsxrenders withexitOnCtrlC: false. - Colour comes from
src/ui/theme.ts— one orange ramp, used for the wordmark gradient and as the single accent. Don't introduce raw ANSI colour names. Logo.tsxrows are exactly 43 columns each and drop to a two-row wordmark under 45 columns.- Pass
onErrortoreadUIMessageStream— it defaults to swallowing upstream errors, which makes a bad provider key look like a hung CLI. - Finished output goes into Ink's
<Static>, which is what keeps terminal scrollback and piping working. Only the in-flight turn re-renders. - Streaming re-renders are throttled (
FLUSH_INTERVAL_MS) and the in-progress answer renders as raw text; markdown is parsed once, when the turn completes. A half-written code fence renders as garbage otherwise. - This package is not an npm workspace of the app, and the app's
tsconfig/ eslint config exclude it. It carries its own React and Ink; hoisting those into the app'snode_moduleswould affect the Next build. build.mjsresolves the app's@/alias so a small allowlist of pure modules can be shared (the digest wire format). Never import anything that touchesnext/headers, a Supabase server client, or React components.- An accepted
@-mention is ordinary text (@Label) plus a record attached behind it. The record lives exactly as long as its@Labelis in the prompt — delete the text and the context goes with it — andfindMentionSpansinApp.tsxis what both highlights it and stops the picker reopening inside it. - Server-side pieces this depends on:
lib/supabase/request.ts(bearer auth),app/api/cli/*(bootstrap, activity, favorites),app/auth/cli/[port]/[code]/page.tsx,lib/cli-auth.ts,lib/favorites-core.ts. See theocCLI section in the repo'sCLAUDE.md.
