The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Alphadesk Terminal listing page.
A dense, fast market-research terminal and integration platform. Readers connect their own market-data and news providers; AlphaDesk is the workspace that connects, checks and presents what those providers — and the public record at SEC EDGAR and the US Treasury — actually say. Questions are asked in the reader's own AI agent (Claude, ChatGPT, Codex, Cursor, opencode), which reads the same records through 50 read-only agent tools (MCP).
AlphaDesk reads: quotes and charts, news, SEC filings, financial statements, ownership and insider activity, earnings and corporate calendars, options, crypto. It does not trade, route orders, hold positions, score ideas or write summaries.
Two ways to use it — the managed cloud or your own server. The code is open source under the GNU AGPL-3.0, with a commercial licence for anyone who cannot meet its terms. See Licence.


Figures in every screenshot are blurred on purpose: they came from a reader's own vendor keys, and vendors restrict public display of their data. The layout is the real thing.
![]() | ![]() |
| Chart — your own SVG engine, session bands, drawings | Earnings week — dated by the company's own release and its SEC filing |
![]() | ![]() |
| News — your feeds in one three-day window, searched by word or meaning | Options — chains by expiry, calls and puts either side of the price |
| AlphaDesk is | AlphaDesk is not |
|---|---|
| A consumption terminal: it fetches, checks and presents market information | A trading system — there is no order routing, position state or broker integration |
| An integration platform: every vendor figure runs on the reader's own key | An aggregator — the server holds no vendor keys and never shares one reader's data with another |
| A presenter of records: filings, statements, stories and prices, shown whole with their source | A summariser — no model writes, paraphrases or scores anything here |
| Pluggable: news feeds, market data, transcripts and dashboard tiles are swappable providers | A black box — every list is chronological, alphabetical or ordered by the figure it shows |
It is offered free at present (payments are designed but switched off; see Accounts).
| Option A — Managed cloud | Option B — Self-hosted | |
|---|---|---|
| Price | Free during early access. Planned: $19 a month or $190 a year, announced before it starts | Free |
| Licence | Commercial terms of service — no AGPL obligations for you | GNU AGPL-3.0 |
| You run | Nothing: sign in with GitHub | One container or one Python process, and a database |
| Search by meaning | Included (the embedding model runs on our servers) | Runs on your CPU (~1.2 GB model, 2 vCPU / 4 GiB recommended) or switched off |
| Vendor keys | Your own, connected on the Account page | Your own, in .env or the Account page |
| Updates | Continuous | git pull and restart |
You need a SEC User-Agent with real contact details (SEC blocks requests without one), Python 3.11+ or Docker, and — for anything beyond EDGAR and Treasury data — your own vendor keys.
1. Configure. Copy the template and fill in the two required values:
Setting in .env | Required | What to put |
|---|---|---|
ALPHADESK_VAULT_KEY | yes | 32 random bytes, base64 — seals stored vendor keys; keep a copy, losing it makes them unreadable |
SEC_USER_AGENT | yes | AlphaDesk (you@example.com) — a name and a real email |
ALPHADESK_AUTH | for one person | off: a single local account with no sign-in |
ALPHADESK_DATABASE_URL | no | a postgres:// URL; unset, SQLite in ALPHADESK_DATA (~/.alphadesk) |
ALPACA_API_KEY, ALPACA_SECRET_KEY, FMP_API_KEY, FINNHUB_API_KEY, POLYGON_API_KEY, ALPHAVANTAGE_API_KEY, COINGECKO_API_KEY | no | your own keys; sealed into the local account with python -m alphadesk.main keys import-env (or connect them on the Account page instead) |
ALPHADESK_SEMANTIC_SEARCH | no | off skips the ~1.2 GB embedding model; search then matches words only |
GOOGLE_CLIENT_ID / GITHUB_CLIENT_ID (+ secrets), ALPHADESK_BASE_URL | for several people | single sign-on for a shared instance |
Generate the vault key with:
2a. Install from PyPI — the shortest route; the built interface ships with the package:
The terminal is at http://127.0.0.1:8000. The first start downloads the
embedding model into the Hugging Face cache (skip it with
ALPHADESK_SEMANTIC_SEARCH=off).
2b. Or run from a clone, which is what you want if you intend to change anything:
2c. Or run with Docker. The image bakes the embedding model in, so a container downloads nothing at start:
With ALPHADESK_AUTH left on and no sign-on provider configured, create a
password account inside the container:
3. Keep it private or publish your changes. Under the AGPL, if you let
other people use a modified copy over a network, you must offer them the
source of your version. Using it yourself, unmodified, or keeping your
changes to yourself on your own machine carries no such obligation. Billing
stays off (ALPHADESK_BILLING_ENFORCE is off by default), so every account
on your instance has full access.
These are the product. Much of what might look missing was built, measured and removed on purpose — DECISIONS.md says what and why. Bring evidence and open an issue.
| Page | What it shows |
|---|---|
Landing (/) | Product overview with blurred screenshots; sign-in and sign-up |
| Markets | A composable board: chart, equity overview, funds built on the stock, stock/ETF/crypto/currency/option movers, Treasury yields, heatmap, news. Stock and ETF movers step back to a past session, computed from the whole market that day against the session before it |
| Chart | Full workspace: candles, line, area, step and other styles; 1-minute to multi-year intervals; indicators and templates; drawing tools (desktop, per visit); multi-chart layouts; overnight, pre-market, after-hours and weekend session shading |
| Analysis | One name end to end: chart, filings, price performance, key statistics, earnings history and consensus, analysts, rating changes, financials as filed, splits, dividends, institutional and insider ownership, news. Funds add holdings and breakdown; coins get their CoinGecko record instead of stock-only panels |
| Profile | Who a company is: EDGAR registrant facts, the latest 10-K/20-F business and properties sections verbatim, locations, officers; a coin's CoinGecko record |
| News | Each reader's merged feeds, three days deep, newest first; filter by words, source or board; search by words and by meaning; an in-page reader with full text where the feed carries it |
| Earnings | The week's reporters, dated by the company's own release and joined to its SEC results filing; sessions predicted from history; estimates, actuals, surprise, market cap, volatility, liquidity |
| Calendars | Economic releases, dividends, corroborated splits and IPOs |
| Options | Chains with implied volatility, calls green and puts red; options flow seen live |
| Sectors | Sector funds by weight and dollars traded, with breadth |
| Baskets | 36 curated baskets grouped by the news that moves them (rates, oil, tariffs, chip export rules, bitcoin, …), plus the reader's own |
| Portfolio / custom views | The reader's saved boards |
| Account | Coverage matrix of connected vendors and feeds, agent access (tokens and connected apps), sign-in methods and sessions |
| Admin | Owners only: accounts, last seen, sign-in methods, sign-out-everywhere, disable, delete |
| Terms, Privacy, Disclaimer | Public drafts pending legal review |
| Vendor | Carries (plan-dependent) |
|---|---|
| Alpaca | Consolidated (SIP) and IEX bars, overnight (Blue Ocean) session, quotes, movers, crypto, option chains with IV, options flow, corporate actions |
| Financial Modeling Prep | Calendars (earnings, economic, dividends, splits, IPOs), key statistics, profiles, analysts, market caps, currencies, press releases, fund data |
| Polygon (Massive) | Bars, quotes, movers, currencies, options |
| Finnhub | Company metrics, profiles, earnings calendar and sessions |
| Alpha Vantage | Company overview, bars |
| CoinGecko | Worldwide crypto prices, volume, market caps and coin records |
For each panel the reader's connected vendors are asked in a fixed, documented order; the first that carries the figure answers. Charts and option chains are pinned to one vendor, never stitched across tapes.
Alpaca (Benzinga), Polygon, Finnhub, Benzinga, Tiingo, Alpha Vantage, Marketaux and FMP. Several feeds merge into one window per reader, de-duplicated by URL. Alpaca's news streams live; the rest poll every five minutes.
A feed whose terms forbid keeping what it sends is not kept: Tiingo's Starter and trial plans may not have their data written to durable storage, so a key declared as one has its stories fetched and dropped, and the Account page says "Not kept" rather than showing a feed that polls and produces nothing.
Three sources need no key because there is nothing to buy: the reader turns each on with a button on the Account page.
| Source | Carries |
|---|---|
| Nasdaq | Earnings, dividend, split and listing calendars — and today's trading halts, which no vendor in the catalogue carries at all |
| Yahoo | Charts, quotes and daily history from the public chart endpoint |
| Social | A mirror of one public account's posts |
Two rules keep them honest. A keyed vendor is always asked first — every
licensed vendor is ordered ahead of every scraped one, so a scraped source
answers only where none does. And provenance travels with the answer:
the catalogue marks the source unofficial, each payload carries it, the tile
subtitle reads "scraped", and the data_sources agent tool resolves any
vendor name back to licensed-or-read. The marker protects the reader's
reasoning; it is not consent from the site.
No ticker is ever read out of a social post: a ticker inside a post is the author's claim, and attaching it would route an unverified assertion into that symbol's context.
Every source, how it is collected and its terms are listed in docs/data-sources.md. Vendor terms are separate from the code licence; see Known limitations.
News search works two ways at once, everywhere a reader searches — the News
filter box, "Search all" and the agent's news_search tool:
By words — one rule shared by the server and the browser: whole words in order, plurals matched to singulars, a capitalised ticker matched exactly, and a query that names a company also finds stories tagged with it ("robinhood" finds stories tagged HOOD).
By meaning — stories whose headline is close in meaning to the query are added and marked related, so "AI data center spending" finds "Equinix plans $5B–$7B annual data center buildout" without a shared phrase. This uses Qwen3-Embedding-0.6B (Apache 2.0), self-hosted inside the server: no text leaves AlphaDesk and there is no model key. Headlines are embedded once as they arrive; the threshold (cosine 0.50) was calibrated so that only on-topic stories are added. Results remain newest first.
The embedding work never competes with the site: the model runs on a single CPU thread, the background worker runs at the lowest operating system priority, and it embeds only while no request is being served. Searches take about a third of a second.
A coin's news panel reads all crypto and what moves it — any coin's stories, crypto stocks, stories naming crypto, and Fed and rates headlines — each marked with the reason it is there.
AlphaDesk exposes the same records the interface shows as 50 read-only
tools over the Model Context Protocol,
at /api/agent/tools/mcp. Every call runs as the reader, on their keys,
rate-limited to 120 requests a minute per token.
Connecting
Tools
| For | Tools |
|---|---|
| Today | market_today, market_tape, movers (stocks, ETFs, indices, crypto, currencies, options, bonds), sector_performance, sector_breadth |
| The reader's names | my_board, quotes, screener_window, baskets, find_symbol |
| One company | quote, key_stats, company_profile, fund_profile, analyst_view, financial_statements, earnings_history, ownership, insider_activity, peers, compare_metrics |
| Prices | price_history, price_chart |
| News | symbol_news, news_search, news_story |
| Filings and calls | list_filings, filing_text, transcripts, transcript_text |
| Calendars | earnings_calendar, recently_reported, economic_calendar, corporate_calendar |
| Options | option_expirations, option_chain, options_flow |
| What just happened | catalysts (filings, halts, government action and social posts on one tape), filing_feed, trading_halts, government_actions, social_posts |
| A past session | movers(session=…) for stocks and ETFs, with market_sessions for the days the market actually opened |
| Provenance | data_sources — whether a figure came from a licensed vendor or a scraped page |
The tools are written for an agent that cannot see the screen: find_symbol
resolves a name to a ticker from the SEC list rather than letting an agent
guess; price_chart returns a thinned series carrying each point's RSI and
MACD; filing_text and transcript_text return whole documents in pages;
news_search marks each story as a word or meaning match. Tools that return
publisher or filer text say that it is untrusted input. Every tool carries
readOnlyHint, so a client can call them without asking permission for each
read.
The full account, session, key-vault and agent-credential design is in docs/hosted-mode.md.
Backend — Python 3.11+. FastAPI with synchronous handlers on a
40-worker thread pool and explicit socket deadlines for every upstream.
Providers are structural Protocols (NewsProvider, PriceProvider,
TranscriptProvider), built per reader from their sealed keys and
discoverable through entry points. The request's reader identity travels in
a context variable; background threads deliberately do not inherit it. The
store speaks SQLite locally and Postgres through the pure-Python pg8000
driver in production. The embedding model runs in process on CPU via
sentence-transformers and PyTorch's CPU build.
Frontend — TypeScript, React 19 and Vite, built to static files the Python process serves. Tailwind CSS v4 carries the design tokens (14-pixel root, 4-pixel spacing grid, six type roles, light and dark). TanStack Query shares one query per endpoint. There is no component library and no chart library: primitives are hand-rolled, and the chart is AlphaDesk's own SVG renderer, with candles batched into four paths so the node count is constant in bar count.
ALPHADESK_SEMANTIC_SEARCH=off)Generate a vault key (32 random bytes, base64):
For local work without sign-in, set ALPHADESK_AUTH=off (one local
account), put your own vendor keys in .env, and seal them into that
account:
Frontend with hot reload (proxies /api to the running server):
| Command | Purpose |
|---|---|
python -m alphadesk.main dashboard | The web server and background loops |
python -m alphadesk.main keys import-env | Development: seal .env vendor keys into the local account |
python -m alphadesk.main earnings | Stamp today's EDGAR results releases and list the last three days |
python -m alphadesk.main backfill --hours 72 | Backfill EDGAR results releases |
python -m alphadesk.main calendar-accuracy --days 30 | Score calendar vendors against EDGAR release days |
python -m alphadesk.main mcp [--http] | The agent tools standalone (EDGAR only — no reader identity) |
python -m alphadesk.main user … | Manage password accounts for instances without SSO |
ALPHADESK_PLUGINS) or the alphadesk.providers entry point —
docs/providers.md.ui/src/widgets/, or serve tiles
from an external JSON backend (ALPHADESK_WIDGET_BACKENDS) —
docs/widgets.md.Environment variables (also read from .env). Only the first two are
required.
| Variable | Purpose |
|---|---|
ALPHADESK_VAULT_KEY | Required. 32 bytes, base64: seals every reader's keys. Losing it makes them unreadable |
SEC_USER_AGENT | Required. Descriptive User-Agent with contact details, as SEC asks |
ALPHADESK_DATABASE_URL | Postgres connection string; unset uses SQLite in ALPHADESK_DATA |
ALPHADESK_DATA | Data directory for SQLite (default ~/.alphadesk) |
ALPHADESK_AUTH | off for a single local account without sign-in |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | Google sign-in (likewise GITHUB_…, MICROSOFT_…) |
ALPHADESK_BASE_URL | Public URL; OAuth redirects and the agent host allowlist depend on it |
ALPHADESK_SECRET | Session signing secret |
ALPHADESK_COOKIE_SECURE | Secure cookies (on behind HTTPS) |
ALPHADESK_OWNER_EMAILS | Owner accounts (Admin page, never gated) |
ALPHADESK_TRIAL_DAYS / ALPHADESK_BILLING_ENFORCE / ALPHADESK_BILLING_PROVIDER | Trial length, access gate (on for the managed service; off by default), payment processor (stripe when a Stripe key is set) |
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET | Managed service only: Stripe checkout and signed webhooks at /api/billing/webhook. Unset, checkout answers 503 and nothing is charged |
STRIPE_PRICE_ID_MONTHLY / STRIPE_PRICE_ID_YEARLY | The two plans' Stripe price IDs ($19 a month, $190 a year) |
ALPHADESK_SEMANTIC_SEARCH | off disables search by meaning |
ALPHADESK_EMBED_MODEL / ALPHADESK_SEMANTIC_THRESHOLD | Embedding model (default Qwen/Qwen3-Embedding-0.6B) and similarity cutoff (0.50) |
ALPHADESK_PLUGINS / ALPHADESK_WIDGET_BACKENDS | Provider plugins; external tile backends |
NEWS_REFRESH_MINUTES / NEWS_LOOKBACK_HOURS / NEWS_KEEP_DAYS | News poll interval (5), window (72 h), retention (7 days) |
CHART_MIN_COVERAGE / CHART_MAX_MEDIAN_GAP_MIN | The indicator coverage gate |
DASHBOARD_HOST / DASHBOARD_PORT | Web server bind (Cloud Run injects PORT) |
MCP_HOST / MCP_PORT | Standalone agent server bind (default port 8010) |
The full annotated template is alphadesk/deploy/env.example; every
setting's default lives in alphadesk/config.py.
The reference service runs on Google Cloud Run (alphadesk, us-east4)
with Cloud SQL for Postgres.
| Setting | Value | Why |
|---|---|---|
| Size | 2 vCPU, 4 GiB | The embedding model and the web server share the instance |
| Instances | exactly 1 (min = max = 1) | One writer for the background loops and live sockets |
| CPU | always allocated, startup boost | Background loops run between requests |
| Image | Python 3.12 slim, PyTorch CPU build, model baked in (~1.2 GB) | Nothing is downloaded at start; model loads in seconds |
Deploying — continuous integration runs the tests, lint and build on
every pull request; deploying stays a maintainer's step. After a merge to
main:
The script refuses unless the checkout is a clean main matching the
remote, builds the image on Cloud Build, rolls the service with the new
image only (environment, database mount and scaling untouched), and checks
that the live page serves the new build. The frontend bundle is committed
under alphadesk/app/static, so the image needs no Node build step.
Operations
Logs: Cloud Logging for the alphadesk service; the ingest loops,
pruning and the embedding worker log their progress there.
Always-on is required as built; approximate cost at this size is $110–120 a month for the service (plus Cloud SQL). The lever for cost is a smaller embedding model, not scaling to zero.
Graceful shutdown is bounded: a revision stops within seconds.
Kill switch for search by meaning. If the service ever slows or refuses requests, turn it off without a rebuild — search falls back to words alone:
Always use --update-env-vars (adds or changes one variable), never
--set-env-vars (replaces every variable). The worker's start-up log line
reports the cores the machine claims and the thread the model uses
(expected: one).
Background work is shipped switched off, then enabled and watched. A 2-vCPU container reports more cores than it has, so behaviour on a many-core laptop does not predict production: sizing threads from the reported core count once starved the web server of a live instance.
| Check | Command | Scope |
|---|---|---|
| Backend tests | python -m pytest -q | ~720 tests: providers, calendars, EDGAR parsing, news rules, search, agent tools, auth, accounts, retention |
| Frontend tests | cd alphadesk/ui && pnpm test | Pure logic under src/lib/__tests__ (chart scales, sessions, news matching, layouts) |
| Type-check and build | cd alphadesk/ui && pnpm build | tsc -b (project references — tsc --noEmit checks nothing here) then Vite |
| Lint | python -m ruff check alphadesk | Python |
AlphaDesk became a consumption terminal by subtraction. Screener ranking, operator-held data and unofficial sources, the in-app agent and the in-app language model were each removed in turn, every one for a measured or stated reason — see DECISIONS.md. The one model that remains is the self-hosted embedding model used for search.
AlphaDesk is dual-licensed. Copyright © 2026 Vignesh Murugan.
Open source — GNU AGPL-3.0 (LICENSE). You may use, study, modify and redistribute AlphaDesk. The AGPL is a strong copyleft licence with one clause beyond the GPL: if you run a modified copy and let others use it over a network, you must offer those users the complete source of your version under the same licence. Distributing copies, modified or not, likewise carries the source with it. Running it for yourself imposes nothing.
Commercial licence. For organisations that want to embed AlphaDesk in a proprietary product, run a modified hosted service without publishing their changes, or need an enterprise exception, a commercial licence is available — contact muruganvignesh0810@gmail.com. The managed cloud is offered under its own terms of service; subscribers take on no AGPL obligations.
Contributions are accepted under a contributor licence agreement, so the project can continue to offer both licences; contributors keep the copyright in their work.
Dependencies are all under permissive licences (MIT, ISC, BSD, Apache
2.0), and no copyleft dependency may be added — it would prevent the
commercial licence. The web interface ships its third-party notices at
/third-party-notices.txt, written by every build from the packages the
bundle actually contains (the fonts are under the SIL Open Font License). The embedding model, Qwen3-Embedding-0.6B, is Apache 2.0.
Data is not code. The code licence grants nothing over market data. Each vendor's terms govern the data fetched on your key; see docs/data-sources.md.