Well-architected foundation for a niche but real use case (CLI video downloads). Architectural choices (React Context for theming, frame-capture for clicks, terminal lifecycle cleanup) demonstrate thoughtfulness and will scale cleanly to 5, 10x feature size.
Primary blockers to 1.0 are QA depth (test coverage ~5%, no e2e), error UX (crashes degrade gracefully but user-facing failures have no recovery), and observability (no logging or metrics). Team should prioritize end-to-end download paths, integration tests against real URLs, and a hardened error boundary before calling it production-ready.
Clipboard injection and hostname-sanitization tensions (from CISO review) are real but lower-priority than functional completeness. Worth shipping at 0.5, 1.0 if targeting early-adopter developers.
AI Readiness score, how production-ready this repo is for AI-assisted workflows.
Transferable, 2-persona convergence, near-zero adoption cost; eliminates entire class of drift bugs; only constraint is immutable package.json + build-time hash
Transferable, standard pattern, one-time setup cost, scales unboundedly; CTO-flagged; no CISO surface; pays off at 3+ components
Transferable, already implemented, security-critical (SSRF/protocol confusion), zero marginal cost; only gap is scheme allowlist enforcement (http/https only)
Transferable, graceful degradation, medium cost but amortized across every terminal environment; pairs with React Context idea above
Transferable, 2-persona convergence, ~20 LOC, tension is resolvable (log-then-cleanup pattern); critical for TUI reliability
Transferable, clean pattern, low cost, no persona flagged but no risks either; dedup and cap are best practices any persistent store needs
Transferable, CISO-flagged, medium cost to harden; current hand-rolled parser is injection surface; whitelist + enum validation is straightforward fix
Transferable, CISO-flagged, low cost once hostname sanitization is added; crafted hostnames are real terminal-injection vector
Transferable, 2-persona convergence but tension depresses score; safe version requires NO_SHELL, timeout, and encoding validation; worth it after hardening
Transferable, no persona flagged, medium cost; good UX foundation but lower urgency than security and theme infrastructure
Transferable, CTO-flagged, but high adoption cost, tight coupling to Ink internals, un-audited ANSI stripping; defer until Ink exposes stable click primitives
Transferable, vendor-directly mode, foundational but already committed; no new decision signal here
Domain-specific, no persona signal, vendor-directly; useful but narrow
Domain-specific, no persona signal, purely aesthetic; last priority
Domain-specific, doc-source only, purely cosmetic; zero generality
Yoinks is a terminal UI video downloader that wraps yt-dlp and ffmpeg, letting users paste a URL and download videos from 1800+ platforms (YouTube, X, Instagram, TikTok, etc.) with interactive format/resolution selection, all without leaving the terminal.
React-as-TUI via Ink with custom theme system (auto/light/dark modes) + frame-capture click hit-testing. Alternatively: first yt-dlp wrapper that prioritizes terminal UX over feature parity with the underlying tool.
README claims polished terminal UX with interactive format selection; code lacks error recovery UI, has ~5% test coverage, and no logging or metrics for production reliability.
Prevents crashed stack traces from being wiped by alternate screen; critical reliability pattern for TUI applications at scale
Cost Requires platform-specific ANSI escape sequence knowledge; ~20 LOC to implement safely across exit paths
Eliminates prop threading as app grows; scales to 10x components without refactor; single source of truth for color surface
Cost Low; standard React pattern; one-time setup cost amortized immediately
Graceful degradation strategy; auto mode survives terminal retheming without code change; forced modes guarantee consistency across platforms
Cost Medium; requires dual rendering paths but pays for itself in reduced environment-specific bugs
Unlocks mouse interaction in TUI without re-rendering logic; architectural bet that pays compound interest if interaction model expands
Cost High; non-obvious ANSI stripping logic; tight coupling to stdout; breaks if Ink internals change
Eliminates version drift in release pipelines; single source of truth; catches automation failures early
Cost Negligible; one require() call; requires shipping package.json in dist
Cross-platform resilience without heavy dependencies; graceful UX when primary tool unavailable
Cost Low for current three-platform support; scales linearly with platform count; external tool availability risk
URL parsing is a vector for SSRF, open-redirect, and injection attacks; permissive parsing (e.g., treating javascript: or data: URIs as valid) would enable protocol confusion.
Cost Already implemented; validate that only http/https pass isProbablyUrl filter and reject file://, javascript:, data: schemes.
Hand-rolled parsers are prone to option injection, argument smuggling, and bypass of validation; lack of escaping on error messages could leak paths or environment.
Cost Add explicit checks: reject any option not in whitelist (--theme, -h, -v), validate themeMode against enum, sanitize error messages to avoid leaking internal paths.
Spawning shell commands (xclip, pbpaste, Get-Clipboard) without strict validation opens code injection if clipboard contents are malicious; fallback chain reduces visibility into which tool ran.
Cost Run clipboard tools in isolated child processes with NO_SHELL flag, timeout each call, validate output encoding, log which tool succeeded for forensics.
Hostname extracted from user URL is rendered/logged without sanitization; crafted hostnames (e.g., '<!-- inject -->', ANSI escape codes) could pollute logs or inject into terminal rendering.
Cost Sanitize hostname before any output (strip ANSI, validate as valid DNS label), log platform detection results only with explicit approval.
Dynamic version read via require(import.meta.url) is safe if package.json is immutable post-build; risk if attacker modifies package.json in node_modules or if version is used in security decisions.
Cost Verify package.json is not writable by child processes, sign or hash version at build time, never use version for privilege or capability checks.
Suppressing stack traces on crash hides security-relevant errors (auth failure, injection attempt); leaveAltScreen on exception is good but could be bypassed if exception occurs after stdout is redirected.
Cost Log full exception (including stack) to stderr/syslog before cleanup, ensure leaveAltScreen is synchronous and does not throw, test crash path with SIGTERM/SIGKILL.
Solid foundations: React Context for theming, platform detection by hostname matching, terminal lifecycle cleanup with ANSI escape codes, frame-capture for click hit-testing. Thoughtful separation of concerns (lib/, components/, theme context). Will scale to 5, 10x feature size without major refactor. Tension: frame-capture wrapper tightly couples to Ink internals and Ink's stdout, high fragility risk if library internals change. Theme system dual-paths (auto vs forced modes) add complexity but justify it with graceful degradation story.
v0.3.1 is early iteration. Build pipeline exists (tsup, prepublishOnly, test script). Terminal cleanup and error handler restoration show production thinking. Critical gaps: no error recovery UI for failed downloads (crashes degrade but user-facing failures have no recovery path), test coverage ~5% (only args/panel/theme tested; app.tsx and main download loop untested), no e2e or integration tests against real platform URLs, no logging or observability, README-only documentation (no troubleshooting, known limitations, or env var guidance). Clipboard reading spawns without NO_SHELL or timeout. Not production-ready; early-adopter viable if targeting developers only.
URL validation via native URL constructor with try/catch is sound. Scheme enforcement (http/https only in isProbablyUrl) is correct. Critical gaps flagged by CISO review: (1) hand-rolled arg parser lacks whitelist validation, accepts any --option without checking enum (--wat is caught but only by error message, not validation gate); (2) clipboard reading spawns xclip/pbpaste/Get-Clipboard without NO_SHELL, timeout, or output encoding validation, injection surface if clipboard holds malicious content; (3) hostname rendering lacks ANSI sanitization, crafted hostnames with escape codes could inject into terminal output; (4) error messages not sanitized (could leak internal paths). Frame-capture ANSI stripping logic un-audited. Package version immutability not verified at startup. Fixes are straightforward (whitelist enum, NO_SHELL spawns, hostname strip-ANSI) but absent.
High reusability potential across several dimensions. Theme system (auto/light/dark with Context API + hook access) transfers directly to any React TUI. Terminal lifecycle pattern (enter/leaveAltScreen, error handlers) is ~20 LOC and transferable to any TUI framework. URL validation, platform detection, argument parsing, clipboard fallback chain, and history dedup/cap are generic utilities (no domain coupling). Frame-capture for click hit-testing is reusable but couples tightly to Ink and stdout, lower transfer value. ProgressBar, TextInput, Shortcuts, Panel are React TUI components but narrow applicability (TUI-only, Ink-dependent). Handwritten borders for aesthetic effect are cosmetic, zero reuse value. No package exports (dist/ only bundles CLI); utilities are co-located and not published separately.
README is minimal and accurate: covers usage (yoinks [url], examples, options) and correctly names platforms (1800+ sites via yt-dlp). Omits troubleshooting, known limitations, environment setup, how to uninstall, FAQ. Per-file summaries (in repo) are present but sparse. No docstrings or inline comments in complex files (frame-capture ANSI stripping, click-map logic, terminal lifecycle cleanup). TypeScript types are clear (Theme type definition, Platform type, themeMode enum) and reduce comment burden. Test file (args.test.ts) doubles as spec (tests enumerate all parsing rules, effective but not called-out as documentation). No CHANGELOG or release notes. Missing: why auto mode delegates to terminal defaults, how click hit-testing works, failure recovery guidance, external tool requirements (yt-dlp, ffmpeg, clipboard tool detection). Claims 'polished interface' but no screenshots or demo. Docs do not misstate scope but are incomplete (incomplete ≠ dishonest; score reflects coverage, not accuracy).
Coverage ~5%. Only three files have tests: args.test.ts (9 tests covering parseArgs, theme mode validation, enum cycles), panel.test.ts (1 test; forces truecolor and checks theme rendering), theme.ts (no dedicated test file but relied on by args.test.ts). Untested: app.tsx (main component, download orchestration, URL input flow), cli.tsx (entry point, clipboard detection, TTY detection), all components except Panel (FramedInput, TextInput, ProgressBar, Shortcuts, Logo, 8 LOC-heavy components), all lib/ modules except args (ytdlp, platforms, history, clipboard, use-mouse-click, click-map, format). No e2e tests (no simulated downloads, no real URL probes). No integration tests. Test framework is Node.js built-in (test module via tsx), sufficient but no CI runner visible. Assertion style is strict (node:assert/strict), good. Test quality: args.test.ts is comprehensive for its scope (spaced/equals options, error cases, enum cycles). panel.test.ts is brittle (forces truecolor, checks color values). No snapshot tests. No property-based tests. No fuzz testing on URL or clipboard inputs. Prepublish hook runs tests but they're trivial to pass.
Zero-drift version sourcing is universally applicable; copy verbatim into any Node/TS project
Canonical pattern worth extracting as a template; teaches clean separation of theme state from components
Security-critical, zero-dependency, directly portable; add http/https scheme allowlist on extraction
Core concept is reusable but terminal-specific env-var checks (NO_COLOR, TERM) must be stripped for non-TUI targets
Critical reliability pattern for any TUI; log-then-cleanup solves the error-wipe tension cleanly
Dedup plus bounded cap is a reusable pattern for any persistent list; extract as generic capped-dedup store
Hand-rolled parser is an injection surface; extract the whitelist-validation skeleton but replace parser with a hardened lib (minimist, parseArgs)
Hostname-to-platform map is reusable; must add hostname sanitization before display to close terminal-injection vector
Fallback chain pattern is sound; harden with NO_SHELL guard, per-command timeout, and output encoding validation before reusing
Good UX foundation; extract as standalone Ink component for reuse across TUI projects
Tightly coupled to Ink internals; ANSI stripping is un-audited; wait for stable Ink click primitives
Already committed; no new decision, but document it as the architectural spine so future contributors know the rendering model
Domain-specific; existing Ink ecosystem libs cover this; not worth extracting as a pattern
Purely aesthetic, domain-specific; no generality for architecture extraction
Cosmetic only, zero generality
Extract in this order: (1) URL validator with scheme allowlist, highest security value, 10 min; (2) runtime version-from-package.json, prevents drift in any project, 5 min; (3) React Context theme template, architectural pattern worth documenting as a reusable scaffold; (4) terminal lifecycle manager, copy into any TUI skeleton; (5) capped-dedup history store, generalize with configurable path and cap; (6) adapt clipboard chain after hardening. Biggest risk: the clipboard fallback chain is the easiest to copy and the most dangerous to copy unsanitized, do not extract it before adding NO_SHELL guard and timeout, or you carry the shell-injection surface into every downstream project.