Skip to content

SimonSaysGiveMeSmile/ask-gstack

Repository files navigation

ask-gstack

A desktop-launchable chat UI that lets you ask questions as if you're talking to Garry Tan, grounded in the gstack ethos. Each reply is produced by a fresh, isolated Claude Code instance spawned via the Claude Agent SDK — fully independent from your own Claude Code sessions.

What it is

  • Frontend: single-page chat (dark, amber accent, Satoshi / DM Sans / JetBrains Mono) using gstack's own design system.
  • Backend: Node HTTP server streaming SSE. Every POST /api/chat spawns an independent claude subprocess via @anthropic-ai/claude-agent-sdk.
  • Persona: a system prompt synthesized from the public gstack repo — ETHOS.md (Boil the Lake, Search Before Building, User Sovereignty), README.md, DESIGN.md, and the full slash-command index.
  • One-command desktop launch: ./launch.sh handles first-run install, starts the server, and opens your browser.

Prereqs

Run it

cp .env.example .env
# open .env and paste your ANTHROPIC_API_KEY
./launch.sh

The launcher installs deps on first run, starts the server on http://localhost:5173, and opens it in your default browser.

Manual run

npm install
ANTHROPIC_API_KEY=sk-ant-... node server.mjs

Configuration

Two ways to set an API key / base URL — the in-app settings panel (gear icon, top-right) takes precedence over .env.

In-app settings (stored in browser localStorage):

  • Provider: Official Anthropic or Custom base URL
  • Base URL: any Anthropic-compatible endpoint (LiteLLM, OpenRouter, your own gateway)
  • API Key: required — either an sk-ant-... key or your proxy's key
  • Model: optional override; leave blank to use the server default

.env fallbacks (used when the UI leaves a field blank):

Var Default Notes
ANTHROPIC_API_KEY optional — UI can supply one instead
ANTHROPIC_BASE_URL optional — e.g. https://openrouter.ai/api/v1
MODEL claude-sonnet-4-5 any Claude model id works — e.g. claude-opus-4-7
PORT 5173 local port
HOST 127.0.0.1 loopback-only by default since the UI handles API keys

Usage limits

Anonymous visitors get 5 questions/day, 1000 words per question. The counter lives in a signed cookie (HMAC-SHA256, no database). Signing in with the unlock account removes both caps. A pill in the header shows usage and opens the login modal.

Required env vars (set in Vercel for the deployed copy, in .env for local):

Var Notes
SESSION_SECRET random 48-byte string. node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"
UNLOCK_EMAIL e.g. admin@example.com. Leave blank to disable login.
UNLOCK_PASSWORD the password
DAILY_QUESTION_LIMIT optional, default 5
WORDS_PER_QUESTION_LIMIT optional, default 1000

How it's wired

public/          static chat UI (no bundler, no framework)
server.mjs       Node HTTP server + SSE streaming
persona.mjs      Garry-Tan-flavored system prompt from gstack docs
rag.mjs          zero-dep BM25 retriever over YC directory + news
fetch-yc.mjs     pulls all YC companies from yc-oss.github.io/api
fetch-news.mjs   pulls recent Garry Tan / YC news
data/            corpus (yc-companies.json, garry-news.txt — gitignored)
gstack-ref/      clone of garrytan/gstack (grounding material, gitignored)
launch.sh        desktop launcher

Grounding data

The assistant can cite specific YC companies with links. Refresh the corpus with:

npm run fetch-yc      # ~5900 companies from the yc-oss mirror (daily updates)
npm run fetch-news    # recent Garry Tan / YC news

Both write to data/ and are re-read on next query (mtime-based cache). launch.sh runs fetch-yc on first launch if the corpus is missing.

On each user message, server.mjs calls the SDK's query() with:

  • systemPrompt = the persona
  • settingSources: [] — no CLAUDE.md or user settings leak in
  • allowedTools: [] — pure conversation, no filesystem or web tools
  • maxTurns: 1 — one reply per request
  • includePartialMessages: true — token-level streaming to the browser

That instance is isolated: no shared session state, no access to your machine, no memory between requests. Short conversation history is re-sent by the browser each turn so context is preserved without persistence.

The persona

The system prompt draws directly from the gstack repo and refuses to invent facts. Key frames:

  • The Golden Age — a single person with AI builds what used to take a team of twenty.
  • Boil the Lake — the complete implementation costs minutes more than the shortcut, so do it.
  • Search Before Building — three layers of knowledge; prize first-principles observations.
  • User Sovereignty — AI recommends, users decide. Always.
  • Build for Yourself — specificity of a real problem beats generality of a hypothetical one.

If the user asks whether it's really Garry, it says no and offers to keep helping.

Not affiliated with

Y Combinator or Garry Tan. This is a fan-built persona grounded in public writing. Trademarks belong to their owners.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors