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/help/version and hands control tosrc/cli-runtime.ts.src/cli-runtime.tsowns the alternate screen, synchronized stdout proxying, Ink mounting, and terminal cleanup.src/app.tsxruns a phase-based UI state machine:idle -> scraping -> display,idle/scraping -> error, and retry submit from the error screen back intoscraping.- The UI swaps between dedicated phase screens instead of keeping a single general shell mounted across the whole flow.
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 is its own error-phase layout:
ErrorDisplay+ retryURLInput+PhaseRail+Footer - Submitting the retry field transitions the app back into
scraping; there is no directerror -> idlejump unless the user exits
- The CLI uses the terminal alternate screen while Parsely is open.
src/cli-runtime.tsowns alternate-screen entry/exit, stdout wrapping, and shutdown cleanup. Keep that behavior out ofsrc/cli.tsxand out of the React tree.src/utils/terminal.tsdeliberately leaves one row free so Ink stays on incremental rendering and does not clear the whole viewport on every update.- Synchronized output defaults on only for Ghostty, WezTerm, and Kitty-compatible terminals unless
PARSELY_SYNC_OUTPUToverrides it. src/hooks/useDisplayPalette.tsapplies the active app background from the rootApptree when palette support is enabled, and runtime cleanup resets the terminal default background on exit.Ctrl+Cshould abort any in-flight scrape before exit.
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: thin CLI entrypoint for args/help/versionsrc/cli-runtime.ts: terminal runtime, alt-screen lifecycle, synchronized stdout wrapping, cleanupsrc/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/shortcuts.ts: phase-aware keyboard shortcut helperssrc/utils/text-layout.ts: wrapping helpers for titles and instructionssrc/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 --diffThe current docs and tests should stay aligned on coverage for:
- CLI runtime teardown in
test/cli-runtime.test.ts - PTY alt-screen smoke coverage in
test/cli-pty.test.ts - Shortcut helpers in
test/shortcuts.test.ts - Text layout helpers in
test/text-layout.test.ts
README.mdalready exists and covers install, usage, and developer setup.README.mdshould describe phase-aware shortcuts,src/cli-runtime.ts, and the dedicated idle/scraping/display/error screens.CLAUDE.mdcontains broader assistant-oriented project notes and should stay aligned with the current runtime/test structure.