{"slug": "show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally", "title": "Show HN: Nexus, ask AI about sensitive spreadsheets locally", "summary": "Nexus, a new open-source tool, allows users to query sensitive spreadsheets with AI agents while keeping all data stored locally on their machine. The tool converts CSV, XLSX, SQLite, and Google Sheets files into a local MCP server that AI agents like Claude Code and Cursor can query and manipulate without sending data to external cloud services. Nexus provides non-destructive features such as collections, branches, and snapshots, and is available under an MIT license.", "body_md": "**Local-first agent layer for tabular data.**\n\nDrop any CSV, XLSX, or SQLite file. Get a local MCP server your AI agent can query and manipulate — without your data ever leaving your machine.\n\nObsidian gave us local-first notes. Nexus does the same for structured data.\n\n[Vision post](https://scottshapiro.substack.com/) · [Issues](https://github.com/scottshapiro142/nexuscli/issues) · MIT licensed\n\nWhen you hand your data to AI tools today, it goes to their cloud. Salesforce + ChatGPT, Sheets + Gemini, Notion + Claude — same pattern.\n\nNexus inverts that. **Your data stays on your machine.** Claude Code, Cursor, and any other MCP-aware agent talks to a local server that exposes your sheets as semantically meaningful tools (`describe_source`\n\n, `find_rows`\n\n, `create_collection`\n\n, …). The master sheet is never mutated — collections, branches (what-if cell overlays), views, snapshots, and annotations all layer on top non-destructively.\n\nThe four pillars:\n\n**Universal input.** CSV, XLSX, SQLite, Google Sheets — one CLI, any tabular source.**Agent-native.** Every sheet becomes an MCP server. Claude Code or Cursor sees it as a domain-specific tool palette.**Non-destructive derivations.** Save subsets, what-if scenarios, filters, point-in-time snapshots, and row annotations — all without touching the master.**Selective cloud publishing.** Coming in v0.3.x — share specific derivations to the cloud while the master stays local.\n\n```\n# 1. Point Nexus at any local sheet\nnpx @pixeldesigns/nexus connect ~/Downloads/customers.csv\n\n# 2. Start the MCP server (HTTP on localhost:5391/mcp by default)\nnpx @pixeldesigns/nexus serve\n\n# 3. In another terminal, connect Claude Code to it\nclaude mcp add --transport http nexus http://localhost:5391/mcp\nclaude\n> what does this sheet contain?\n> find stale customers and draft outreach emails\n> save the stale customers as a collection called \"needs-outreach\"\n```\n\nThat's the whole local-file flow. Iris (the LLM that reads your sheet semantically) generates a description, columns get typed, suggested questions appear, and your agent gets a tool palette named after your data.\n\nPublic Google Sheets work without auth when the sheet is shared as “Anyone with the link → Viewer.” Private sheets need a one-time Google sign-in:\n\n```\n# 1. Sign in once. The top-level alias is equivalent.\nnexus auth login google\n# or: nexus login google\n\n# 2. Quote the URL so shells do not treat ? or #gid as syntax.\nnexus connect \"https://docs.google.com/spreadsheets/d/<sheet-id>/edit#gid=0\"\n\n# 3. Query saved views from the cached latest rows without reconnecting.\nnexus query <view-name>\n```\n\nNexus still tries the public CSV export first. If Google responds with a private/login page and you have Google OAuth tokens, Nexus uses the Sheets API v4, converts those rows into the same CSV ingestion pipeline, and stores the latest master snapshot locally for later `nexus query`\n\nruns.\n\nInstall globally so the command is just `nexus`\n\n:\n\n```\nnpm install -g @pixeldesigns/nexus\nnexus connect ~/Downloads/customers.csv\nnexus serve\n```\n\n**Node.js 20+****For private Google Sheets:** nothing extra — Nexus ships with a registered Google OAuth client, so`nexus auth login google`\n\njust works. (Contributors who want to BYO credentials can set`NEXUS_GOOGLE_CLIENT_ID`\n\n/`NEXUS_GOOGLE_CLIENT_SECRET`\n\n.)\n\nNexus uses an LLM (Iris) to pre-read your sheet — typed columns, structural summary, suggested views, and non-obvious patterns (\"Tells\"). Iris is optional. Three backends, auto-detected in this order:\n\n**Claude Code** if`claude`\n\nis on your`PATH`\n\n. Uses your existing Claude Code auth — no second key. Each`nexus connect`\n\nconsumes a small amount of your Claude usage.**OpenRouter** if`OPENROUTER_API_KEY`\n\nis set (env or`~/.nexus/config.json`\n\n).**Local**— no LLM.`nexus connect`\n\ningests, types columns, and persists rows. Your agent forms its own description of the sheet on first MCP contact.\n\nForce a specific backend with `--sampler local|claude-code|openrouter`\n\non `nexus connect`\n\n, or `NEXUS_SAMPLER=...`\n\nenv. Override the model picked by Claude Code or OpenRouter with `NEXUS_MODEL=...`\n\n.\n\nTo use OpenRouter, get a key at [openrouter.ai/keys](https://openrouter.ai/keys), then either:\n\n```\n# Option A: store it once (writes ~/.nexus/config.json, chmod 600)\nnexus config set-key sk-or-...\n\n# Option B: export per-shell (env always wins over the stored key)\nexport OPENROUTER_API_KEY=sk-or-...\n```\n\nCheck what's set with `nexus config get`\n\n. Remove the stored key with `nexus config unset-key`\n\n.\n\n```\nnexus connect <path-or-url>    Register a sheet/database as a master source.\n                                 Supports: .csv, .tsv, .xlsx, .xls, .sqlite,\n                                 and public/private Google Sheets URLs.\n  --sampler <backend>            Iris backend: local | claude-code | openrouter.\n                                 Auto-detected if omitted.\n  --skip-iris                    Don't run Iris at all (alias for --sampler local).\n\nnexus list                      List derivations (views, collections,\n                                 branches, snapshots, annotations) for the\n                                 active source.\n\nnexus list --sources            List every connected master source.\n\nnexus query <view-name>         Run a saved view and print rows.\n\nnexus tools                     Print the MCP tool definitions Iris exposes\n                                 for the active source.\n\nnexus serve                     Start the MCP server.\n  --port <n>                    HTTP port (default 5391)\n  --host <h>                    Bind address (default 127.0.0.1)\n  --stdio                       Serve over stdio (for `claude mcp add` stdio mode)\n\nnexus config get                Show resolved config (secrets masked).\nnexus config set-key [<key>]    Store OpenRouter API key (or pipe via stdin).\nnexus config unset-key          Remove the stored key.\nnexus config path               Print the config file path.\n\nnexus auth login google         Sign in to Google for private Sheets access.\n                                Alias: nexus login google\n  --force                       Force re-consent / refresh-token rotation.\n\nnexus auth logout google        Remove stored Google OAuth tokens.\n                                Alias: nexus logout google\n```\n\nPublic Google Sheets still work through the no-auth CSV export path. For private sheets, sign in once:\n\n```\nnexus auth login google         # or: nexus login google\nnexus connect \"https://docs.google.com/spreadsheets/d/<sheet-id>/edit#gid=0\"\n```\n\nNexus first tries the public CSV export URL. If Google returns a private/login response and Google OAuth tokens are available, it falls back to the Google Sheets API and then feeds the returned rows through the same CSV parser used by local/public sheets. Stored Google tokens live under `~/.nexus/auth/google.json`\n\nwith owner-only file permissions and can be removed with `nexus auth logout google`\n\nor `nexus logout google`\n\n.\n\nTroubleshooting:\n\n**Shell says** quote Google Sheet URLs.`no matches found`\n\nor mangles the URL:`?`\n\nand`#gid=0`\n\nhave meaning in shells like zsh.**Google did not return a refresh token:** run`nexus auth login google --force`\n\nto force the consent screen and rotate the refresh token.**Session expired or revoked:** run`nexus auth login google`\n\nagain.**Permission denied from Google:** make sure the signed-in account can view the sheet, or switch the sheet to “Anyone with the link → Viewer” and use the public path.\n\n**HTTP transport (recommended):**\n\n```\nnexus serve --port 5391\nclaude mcp add --transport http nexus http://localhost:5391/mcp\n```\n\n**stdio transport (Claude Code launches Nexus itself):**\n\n```\nclaude mcp add nexus -- npx @pixeldesigns/nexus serve --stdio\n```\n\nOnce added, `/mcp`\n\ninside Claude Code shows Nexus's tools, including auto-generated ones (`query_<your-view>`\n\n, `read_<your-collection>`\n\n) that reflect the derivations you've saved.\n\nNexus |\nDatasette | DuckDB UI | Quadratic | Rill | OpenAI Code Interpreter | Copilot for Excel | |\n|---|---|---|---|---|---|---|---|\n| Runs entirely on your machine | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |\n| Reads CSV / XLSX / SQLite / Sheets | ✅ | ✅ | ❌ Excel only | ||||\n| Exposes data to your AI agent (MCP) | ✅ | ❌ | ❌ | ❌ | ❌ | ||\n| Typed semantic layer (not raw cells) | ✅ Iris | ❌ | ❌ | ❌ | ✅ metrics | ❌ | |\n| Non-destructive derivations (views, branches, snapshots) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | |\n| Open source | ✅ MIT | ✅ Apache | ✅ MIT | ✅ Apache | ❌ | ❌ |\n\n**When to pick which:**\n\n**Datasette**— best for publishing a SQLite database as a browsable web UI. Different audience (data journalism, public datasets), no agent integration.**DuckDB UI**— best for fast local analytical SQL over Parquet/CSV. Querying engine, not agent layer.** Quadratic / Copilot / Code Interpreter**— best when uploading is fine and you want a polished in-app AI experience. Nexus exists for the case when uploading is*not*fine.**Rill**— best for local-first BI dashboards. Overlapping local-first ethos; different primitive (dashboards vs. agent tools).** Nexus**— best when you want your existing AI agent (Claude Code, Cursor, any MCP client) to query your spreadsheets*in place*, without uploading, with a non-destructive layer for what-ifs.\n\nNexus ships with a registered Google \"Desktop app\" OAuth client embedded in the binary. The client ID and secret are visible in the published source and npm tarball. This is deliberate:\n\n**Google's Desktop app client type requires** PKCE-only is not viable (empirically verified — see`client_secret`\n\non every token exchange.`lib/auth/google/client-creds.ts`\n\n). The token endpoint returns`400 client_secret is missing.`\n\nwhen the secret is omitted.**Google explicitly states** the Desktop client secret \"is obviously not treated as a secret\" — see[https://developers.google.com/identity/protocols/oauth2](https://developers.google.com/identity/protocols/oauth2).**Every comparable OSS CLI ships its embedded secret.**`gcloud`\n\n,`gh`\n\n,`firebase`\n\n, and`npm`\n\nall distribute Google OAuth client secrets in their binaries.\n\nWhat this gives you:\n\n- Zero configuration. Install Nexus and\n`nexus auth login google`\n\nworks. - PKCE still protects against auth-code interception.\n- Your refresh token, your scope, your data — all on your machine.\n\nWhat this means for the client identity:\n\n- Nexus users authenticate as themselves to Google,\n*via*the registered PixelDesigns \"Nexus\" app. The consent screen shows \"Nexus wants to access your Google Sheets.\" - PixelDesigns can see, in the GCP Console audit log, that a given Google account granted Nexus access at a given time. PixelDesigns cannot see the data — it never passes through PixelDesigns infrastructure.\n\nTo use your own credentials instead (uncommon, but supported): set `NEXUS_GOOGLE_CLIENT_ID`\n\nand `NEXUS_GOOGLE_CLIENT_SECRET`\n\nin the environment. They override the embedded constants.\n\nEverything stays in `~/.nexus/<source-hash>/`\n\n— a SQLite database for derivations + the master sheet metadata. Nothing is uploaded.\n\nTo inspect:\n\n```\nls ~/.nexus/\n```\n\nTo remove a connected source, delete its directory.\n\n- ✅ CSV / TSV / XLSX / SQLite / public Google Sheets ingestion\n- ✅ Private Google Sheets ingestion through Google OAuth and Sheets API v4\n- ✅ Top-level Google auth aliases:\n`nexus login google`\n\nand`nexus logout google`\n\n- ✅ Cached\n`master.latest`\n\nrows so`nexus query <view>`\n\ncan run after`connect`\n\nwithout refetching a private sheet - ✅ Iris semantic read (column types, subject, suggested questions, row Tells)\n- ✅ Derivations: views, collections, branches (what-if overlays), snapshots, annotations\n- ✅ MCP server with auto-generated semantic tools per derivation\n- ✅ HTTP and stdio transports\n- ✅ Local SQLite kernel — every operation is persistent across runs\n- ✅ Release-quality hardening: lint, type-check, build, package dry-run, and Sheets ingestion/query-cache tests\n\nDeferred to v0.3.x:\n\n- Selective cloud publishing (share specific derivations, master stays local)\n- Project concept (group multiple sheets, one MCP surface)\n- Web UI (the local kernel's third surface, alongside CLI and MCP)\n\nBug reports and feature requests welcome at [github.com/scottshapiro142/nexuscli/issues](https://github.com/scottshapiro142/nexuscli/issues).\n\nPull requests welcome but please open an issue first to discuss approach — this is a young project and the surface is still hardening.\n\nMIT — see [LICENSE](/scottshapiro142/nexuscli/blob/main/LICENSE).\n\nBuilt by [PixelDesigns LLC](https://github.com/pixeldesignsllc).", "url": "https://wpnews.pro/news/show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally", "canonical_source": "https://github.com/scottshapiro142/nexuscli", "published_at": "2026-06-04 19:27:27+00:00", "updated_at": "2026-06-04 19:50:43.892972+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "ai-products", "ai-infrastructure", "ai-startups"], "entities": ["Nexus", "Claude Code", "Cursor", "MCP", "Obsidian", "Salesforce", "ChatGPT", "Google Sheets"], "alternates": {"html": "https://wpnews.pro/news/show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally", "markdown": "https://wpnews.pro/news/show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally.md", "text": "https://wpnews.pro/news/show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally.txt", "jsonld": "https://wpnews.pro/news/show-hn-nexus-ask-ai-about-sensitive-spreadsheets-locally.jsonld"}}