AI News HubLIVE
站内改写6 min read

Show HN: Nexus, ask AI about sensitive spreadsheets locally

Nexus is a local-first open-source tool that lets AI agents (like Claude Code) query and manipulate local spreadsheets (CSV, XLSX, SQLite, Google Sheets) without uploading data to the cloud. It exposes data via MCP protocol, supports non-destructive derivations (views, branches, snapshots), and includes an optional semantic reading layer called Iris.

SourceHacker News AIAuthor: scottbuilds

Notifications You must be signed in to change notification settings

Fork 0

Star 2

BranchesTags

Open more actions menu

Folders and files

NameName

Last commit message

Last commit date

Latest commit

History

12 Commits

12 Commits

.github/ISSUE_TEMPLATE

.github/ISSUE_TEMPLATE

app

app

cli

cli

components/render

components/render

docs

docs

lib

lib

public

public

scripts

scripts

tests

tests

.gitignore

.gitignore

AGENTS.md

AGENTS.md

CLAUDE.md

CLAUDE.md

LICENSE

LICENSE

README.md

README.md

eslint.config.mjs

eslint.config.mjs

next.config.ts

next.config.ts

package-lock.json

package-lock.json

package.json

package.json

postcss.config.mjs

postcss.config.mjs

tsconfig.cli.json

tsconfig.cli.json

tsconfig.json

tsconfig.json

tsup.config.ts

tsup.config.ts

Repository files navigation

Local-first agent layer for tabular data.

Drop 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.

Obsidian gave us local-first notes. Nexus does the same for structured data.

Vision post · Issues · MIT licensed

Why

When you hand your data to AI tools today, it goes to their cloud. Salesforce + ChatGPT, Sheets + Gemini, Notion + Claude — same pattern.

Nexus 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, find_rows, create_collection, …). The master sheet is never mutated — collections, branches (what-if cell overlays), views, snapshots, and annotations all layer on top non-destructively.

The four pillars:

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.

Install & first run (under 60 seconds)

1. Point Nexus at any local sheet

npx @pixeldesigns/nexus connect ~/Downloads/customers.csv

2. Start the MCP server (HTTP on localhost:5391/mcp by default)

npx @pixeldesigns/nexus serve

3. In another terminal, connect Claude Code to it

claude mcp add --transport http nexus http://localhost:5391/mcp claude > what does this sheet contain? > find stale customers and draft outreach emails > save the stale customers as a collection called "needs-outreach"

That'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.

Private Google Sheets first run

Public 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:

1. Sign in once. The top-level alias is equivalent.

nexus auth login google

or: nexus login google

2. Quote the URL so shells do not treat ? or #gid as syntax.

nexus connect "https://docs.google.com/spreadsheets/d//edit#gid=0"

3. Query saved views from the cached latest rows without reconnecting.

nexus query

Nexus 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 runs.

Going faster after the first run

Install globally so the command is just nexus:

npm install -g @pixeldesigns/nexus nexus connect ~/Downloads/customers.csv nexus serve

Requirements

Node.js 20+

For private Google Sheets: nothing extra — Nexus ships with a registered Google OAuth client, so nexus auth login google just works. (Contributors who want to BYO credentials can set NEXUS_GOOGLE_CLIENT_ID / NEXUS_GOOGLE_CLIENT_SECRET.)

Nexus 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:

Claude Code if claude is on your PATH. Uses your existing Claude Code auth — no second key. Each nexus connect consumes a small amount of your Claude usage.

OpenRouter if OPENROUTER_API_KEY is set (env or ~/.nexus/config.json).

Local — no LLM. nexus connect ingests, types columns, and persists rows. Your agent forms its own description of the sheet on first MCP contact.

Force a specific backend with --sampler local|claude-code|openrouter on nexus connect, or NEXUS_SAMPLER=... env. Override the model picked by Claude Code or OpenRouter with NEXUS_MODEL=....

To use OpenRouter, get a key at openrouter.ai/keys, then either:

Option A: store it once (writes ~/.nexus/config.json, chmod 600)

nexus config set-key sk-or-...

Option B: export per-shell (env always wins over the stored key)

export OPENROUTER_API_KEY=sk-or-...

Check what's set with nexus config get. Remove the stored key with nexus config unset-key.

Commands

nexus connect Register a sheet/database as a master source. Supports: .csv, .tsv, .xlsx, .xls, .sqlite, and public/private Google Sheets URLs. --sampler Iris backend: local | claude-code | openrouter. Auto-detected if omitted. --skip-iris Don't run Iris at all (alias for --sampler local).

nexus list List derivations (views, collections, branches, snapshots, annotations) for the active source.

nexus list --sources List every connected master source.

nexus query Run a saved view and print rows.

nexus tools Print the MCP tool definitions Iris exposes for the active source.

nexus serve Start the MCP server. --port HTTP port (default 5391) --host Bind address (default 127.0.0.1) --stdio Serve over stdio (for claude mcp add stdio mode)

nexus config get Show resolved config (secrets masked). nexus config set-key [] Store OpenRouter API key (or pipe via stdin). nexus config unset-key Remove the stored key. nexus config path Print the config file path.

nexus auth login google Sign in to Google for private Sheets access. Alias: nexus login google --force Force re-consent / refresh-token rotation.

nexus auth logout google Remove stored Google OAuth tokens. Alias: nexus logout google

Private Google Sheets

Public Google Sheets still work through the no-auth CSV export path. For private sheets, sign in once:

nexus auth login google # or: nexus login google nexus connect "https://docs.google.com/spreadsheets/d//edit#gid=0"

Nexus 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 with owner-only file permissions and can be removed with nexus auth logout google or nexus logout google.

Troubleshooting:

Shell says no matches found or mangles the URL: quote Google Sheet URLs. ? and #gid=0 have meaning in shells like zsh.

Google did not return a refresh token: run nexus auth login google --force to force the consent screen and rotate the refresh token.

Session expired or revoked: run nexus auth login google again.

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.

Connecting from Claude Code

HTTP transport (recommended):

nexus serve --port 5391 claude mcp add --transport http nexus http://localhost:5391/mcp

stdio transport (Claude Code launches Nexus itself):

claude mcp add nexus -- npx @pixeldesigns/nexus serve --stdio

Once added, /mcp inside Claude Code shows Nexus's tools, including auto-generated ones (query_, read_) that reflect the derivations you've saved.

How Nexus compares to similar tools

Nexus Datasette DuckDB UI Quadratic Rill OpenAI Code Interpreter Copilot for Excel

Runs entirely on your machine ✅ ✅ ✅ ❌ ✅ ❌ ❌

Reads CSV / XLSX / SQLite / Sheets ✅ ⚠️ SQLite-first ✅ ⚠️ in-app only ⚠️ Parquet-first ⚠️ upload ❌ Excel only

Exposes data to your AI agent (MCP) ✅ ❌ ❌ ⚠️ in-app AI ❌ ❌ ⚠️ in-app AI

Typed semantic layer (not raw cells) ✅ Iris ❌ ❌ ❌ ✅ metrics ❌ ⚠️ partial

Non-destructive derivations (views, branches, snapshots) ✅ ❌ ❌ ❌ ⚠️ dashboards ❌ ❌

Open source ✅ MIT ✅ Apache ✅ MIT ⚠️ AGPL/cloud ✅ Apache ❌ ❌

When to pick which:

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.

Security model — Google OAuth credentials

Nexus 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:

Google's Desktop app client type requires client_secret on every token exchange. PKCE-only is not viable (empirically verified — see lib/auth/google/client-creds.ts). The token endpoint returns 400 client_secret is missing. when 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.

Every comparable OSS CLI ships its embedded secret. gcloud, gh, firebase, and npm all distribute Google OAuth client secrets in their binaries.

What this gives you:

Zero configuration. Install Nexus and nexus auth login google works.

PKCE still protects against auth-code interception.

Your refresh token, your scope, your data — all on your machine.

What this means for the client identity:

Nexus users authenticate as themselves to Google, 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.

To use your own credentials instead (uncommon, but supported): set NEXUS_GOOGLE_CLIENT_ID and NEXUS_GOOGLE_CLIENT_SECRET in the environment. They override the embedded constants.

Where your data lives

Everything stays in ~/.nexus// — a SQLite database for derivations + the master sheet metadata. Nothing is uploaded.

To inspect:

ls ~/.nexus/

To remove a connected source, delete its directory.

What's in v0.3.0

✅ CSV / TSV / XLSX / SQLite / public Google Sheets ingestion

✅ Private Google Sheets ingestion through Google OAuth and Sheets API v4

✅ Top-level Google auth aliases: nexus login google and nexus logout google

✅ Cached master.latest rows so nexus query can run after connect without refetching a private sheet

✅ Iris semantic read (column types, subject, suggested questions, row Tells)

✅ Derivations: views, collections, branches (what-if overlays), snapshots, annotations

✅ MCP server with auto-generated semantic tools per derivation

✅ HTTP and stdio transports

✅ Local SQLite kernel — every operation is persistent across runs

✅ Release-quality harde

[truncated for AI cost control]