Context for coding agents working in parsely-cli.
Parsely CLI is a full-screen terminal recipe scraper built with Ink. The app takes a recipe URL, tries to recover structured recipe data from the page, and renders the result as a plated terminal view with ingredients, timings, and instructions.
The runtime flow is:
src/cli.tsxparses CLI args, enters the alternate screen, and mounts Ink.src/app.tsxruns a phase-based UI state machine:idle -> scraping -> displayorerror.src/services/scraper.tsattempts browser/schema extraction first, then falls back to OpenAI only when needed.- The display phase renders a dedicated recipe layout in
src/components/RecipeCard.tsx.
- Node.js 18+
- TypeScript with ESM (
"type": "module") - React 18
- Ink v5 for terminal rendering
ink-text-inputfor URL entryink-spinnerfor scrape statuspuppeteer-corefor browser extractioncheeriofor schema parsing- OpenAI SDK for fallback extraction
cfontsandink-big-textfor terminal wordmark/large display text
src/components/LandingScreen.tsx- Minimal landing view on the paper background (
#FDFFF7) - Uses a single fixed Parsely block wordmark
- Centers the logo and URL input as a single measured block
src/components/LoadingScreen.tsx- Shows only a centered loading indicator between the landing screen and the recipe page
src/components/RecipeCard.tsx- Dedicated recipe screen instead of the general app shell
- Uses Parsely green palette and paper background
src/components/ErrorDisplay.tsx- Retry path routes back through
URLInput
- The CLI uses the terminal alternate screen while Parsely is open.
src/utils/terminal.tsdeliberately leaves one row free so Ink stays on incremental rendering and does not clear the whole viewport on every update.- Ghostty synchronized output is enabled by default through the CLI/stdout wrapper.
src/hooks/useDisplayPalette.tssets the terminal background color during the landing and recipe display screens.Ctrl+Cshould abort any in-flight scrape before exit.
Do not move alternate-screen control into the React tree. It belongs in src/cli.tsx.
Primary path:
- Launch system Chrome/Chromium via Puppeteer
- Load the page and recover HTML
- Parse
application/ld+jsonblocks with Cheerio - Extract a
Recipeschema when available
Fallback path:
- Detect that browser/schema extraction was insufficient
- Call OpenAI
gpt-4o-mini - Normalize the result into the shared
Recipeshape
The app is intentionally browser-first. Do not make AI the default path.
src/cli.tsx: CLI entrypoint, alternate screen, stdout wrappingsrc/app.tsx: state machine, input flow, scrape orchestrationsrc/services/scraper.ts: browser extraction, schema parsing, AI fallbacksrc/components/LandingScreen.tsx: idle/landing viewsrc/components/URLInput.tsx: paste-safe single-line URL inputsrc/components/RecipeCard.tsx: recipe presentationsrc/utils/helpers.ts: URL normalization and input sanitizationsrc/utils/terminal.ts: render-height, synchronized output, background helperssrc/theme.ts: shared color palette and symbols
npm install
npm start
npm run dev
npm run typecheck
npm test
npm run build- Prefer
rgfor search. - Use
apply_patchfor file edits. - Keep the terminal UI minimal; avoid reintroducing clutter on the landing screen.
- Preserve the paper background and Parsely green branding in the landing and recipe display screens.
- Keep layout responsive to narrow and short terminals.
- Avoid changes that reintroduce full-screen redraw flicker.
- If you change terminal rendering behavior, verify in a real TTY, not only with static reads.
Before finishing UI or scraper changes, run:
npm run typecheck
npm test
npm run buildIf the work touches React layout or terminal rendering, also run:
npx -y react-doctor@latest . --verbose --diffREADME.mdalready exists and covers install, usage, and developer setup.CLAUDE.mdcontains broader assistant-oriented project notes, but may lag behind the newest UI changes.