Mincdp – Give Claude eyes and hands in a browser, in ~410 lines of C Mincdp, a minimal C and Java client library (~410 lines), allows direct control of headless Chrome via the Chrome DevTools Protocol without Selenium or chromedriver, enabling browser automation for testing and AI agent tasks. The library focuses on simplicity and zero dependencies, supporting navigation, JavaScript evaluation, typing, and screenshots. Drive a real headless Chrome for tests without Selenium or a version-matched chromedriver. Two tiny, dependency-free clients that speak the Chrome DevTools Protocol CDP straight to the browser over a WebSocket, in the language of your stack: C : c/cdp.h , a single header-only library ~410 lines, libc + POSIX sockets only . Java : java/Cdp.java , a single file JDK java.net.http only, nothing to vendor . Same idea, same small command set, one demonstration each against the same page. The image above was produced by mincdp itself: the demo typed into the page, pressed Enter, then captured this driven state with cdp screenshot Page.captureScreenshot . CDP is the wire protocol Puppeteer and Playwright use under the hood. Talking it directly means no chromedriver middleman and no external dependency to vendor and keep version-matched to Chrome. For a fixed set of internal pages, headless, one browser, that is a good trade: the client is small enough to read in a sitting, and if Chrome ever ships a breaking CDP change you fix the one file rather than wait for an upstream driver release. It is deliberately not a general framework. It knows only the commands a click-and-assert test needs: navigate, evaluate JS, type text, press a key. If you need cross-browser Firefox/Safari or a rich interaction API, use Playwright; this earns its place only where minimalism and zero dependencies do. Needs a headless Chrome/Chromium on PATH and curl , and cc / javac . make ut the whole regression suite see Tests make demo-c build c/demo and run it against page.html make demo-java build java/Demo and run it against page.html make demo both make shot screenshot page.html so you can SEE it make agent GOAL="..." let Claude drive the page toward a goal needs an API key Each demo prints a series of assertions and a demo: N passed, 0 failed line. It first inspects the page's internals title, attribute, text, computed style, geometry , then drives the real input path: type "mincdp works", press Enter, and assert the page echoes it. Set CDP DEBUG=1 to see every CDP frame. make ut runs the full regression, in two kinds, so a test set has both hands and eyes: codeut -- "regular" browser-free unit tests of the client's pure helpers base64, JSON escaping , several examples each. No Chrome needed, so it always runs tests/codeut.c . uiut -- the client driving real headless Chrome, in two kinds: page internals + hands -- the demos inspect the rendered DOM presence, attribute, text, computed style, geometry through Runtime.evaluate , then interact type, press Enter, assert the DOM changed , then screenshot the driven state over the protocol cdp screenshot - Page.captureScreenshot and assert a valid PNG c/demo.c , java/Demo.java . eyes, for agents -- tests/shot.sh is the standalone shell version: screenshots a fresh page load with Chrome's --screenshot , no client code needed. It complements the demos' protocol screenshot which captures a driven state . Either PNG is there to be looked at: open it, or have an agent Read it. Each layer reports PASS / FAIL / SKIP a missing toolchain SKIPs, exit 77 ; the suite fails only if a non-skipped layer fails: mincdp regression: codeut units PASS uiut hands: C PASS uiut hands: Java PASS uiut eyes: shot PASS The demos double as the interaction tests; make demo-c / demo-java run them on their own. You start Chrome; the client attaches. demo.sh does that wiring launch a headless Chrome with --remote-debugging-port , run the demo, tear down , and it invokes both demos with the same contract, so one launcher and one page.html serve both languages: PROG... 127.0.0.1