pinchtab-dev
GitHubPinchTab项目开发指南,涵盖Go后端与React前端构建、测试及E2E流程。用于本地开发、功能实现、Bug修复及PR准备。
Trigger Scenarios
Install
npx skills add pinchtab/pinchtab --skill pinchtab-dev -g -y
SKILL.md
Frontmatter
{
"name": "pinchtab-dev",
"description": "Develop and contribute to the PinchTab project. Use when working on PinchTab source code, adding features, fixing bugs, running tests, or preparing PRs. Triggers on \"work on pinchtab\", \"pinchtab development\", \"contribute to pinchtab\", \"fix pinchtab bug\", \"add pinchtab feature\"."
}
PinchTab Development
PinchTab is a browser control server for AI agents — Small Go binary with HTTP API.
Project Location
Run everything from the repository root (a clone of github.com/pinchtab/pinchtab).
Dev Commands
All development commands run via ./dev:
| Command | Description |
|---|---|
./dev build |
Build the application |
./dev dev |
Build & run |
./dev dashboard |
Hot-reload dashboard development (Vite + Go) |
./dev run |
Run the application |
./dev check |
All checks (Go + Dashboard + Plugin) |
./dev check go |
Go checks only |
./dev check dashboard |
Dashboard checks only |
./dev test unit |
Go unit tests |
./dev test dashboard |
Dashboard unit tests |
./dev e2e basic |
Basic suite (api + cli + infra) |
./dev e2e extended |
Extended suite (all extended) |
./dev e2e smoke |
Smoke suite |
./dev smoke |
Host Docker smoke checks (--browser=chrome|cloak|all) |
./dev e2e test "<name>" |
Run a single E2E test by start_test name |
./dev all |
check + test + e2e extended (pre-push gate) |
./dev binaries |
Build the full release binary matrix into dist/ |
./dev doctor |
Setup dev environment |
Architecture
cmd/pinchtab/ CLI entry point
internal/
bridge/ Chrome CDP communication
handlers/ HTTP API handlers
server/ HTTP server
dashboard/ Embedded React dashboard
config/ Configuration
routes/ API route catalogue
assets/ Embedded assets (stealth.js)
dashboard/ React dashboard source (Vite + TypeScript)
tests/e2e/ E2E runner, fixtures, scenarios/{api,cli,infra,plugin}/
Workflow: New Feature or Bug Fix
-
Create branch from
main:git checkout main && git pull git checkout -b feat/my-feature # or fix/my-bug -
Make changes — follow code patterns in existing files
-
Run checks locally:
./dev all # check + test + e2e (one-shot pre-push gate) # …or individually: ./dev check # Lint + format + typecheck ./dev test unit # Go unit tests ./dev e2e basic # E2E tests (Docker required) -
Commit with conventional commits, usually scoped —
fix(extract): … (PIN-394):feat:new featurefix:bug fixrefactor:code change without behavior changetest:adding testsdocs:documentationchore:maintenance
-
Push and create PR
Definition of Done (PR Checklist)
Required — Code Quality
- Error handling explicit — all errors wrapped with
%w, no silent failures - No regressions — verify stealth, token efficiency, session persistence
- SOLID principles — functions do one thing, testable
- No redundant comments — explain why, not what
Required — Testing
- New/changed functionality has tests
- Docker E2E tests pass locally:
./dev e2e basic(or./dev allfor the full chain) - If npm wrapper touched:
npm packandnpm installwork
Required — Documentation
- README.md updated if user-facing changes
- /docs/ updated if API/architecture changed
Required — Review
- PR description explains what + why
- Commits are atomic with good messages
Key Files
| File | Purpose |
|---|---|
internal/assets/stealth.js |
Bot detection evasion (light/medium/full levels) |
internal/bridge/bridge.go |
Chrome CDP bridge |
internal/handlers/*.go |
HTTP API endpoints |
dashboard/src/ |
React dashboard source |
internal/routes/routes.go |
API route catalogue |
tests/e2e/scenarios/api/ |
API E2E tests |
tests/e2e/scenarios/cli/ |
CLI E2E tests |
Testing
Unit Tests
./dev test unit # All Go tests
go test ./internal/handlers # Specific package
E2E Tests (requires Docker)
./dev e2e basic # Basic suite (api + cli + infra)
./dev e2e api # API basic tests
./dev e2e cli # CLI basic tests
./dev e2e infra # Infra basic tests
./dev e2e api-extended # API extended tests (multi-instance)
./dev e2e cli-extended # CLI extended tests
./dev e2e infra-extended # Infra extended tests (multi-instance)
./dev e2e extended # Full extended suite (all extended tests)
./dev smoke # Host Docker smoke checks (not an e2e suite)
# Run specific test file(s) with filter (second argument)
./dev e2e api clipboard # Run only clipboard-basic.sh
./dev e2e api-extended tabs # Run tabs-extended.sh
./dev e2e cli browser # Run browser-basic.sh in CLI suite
# Run a single test by its start_test name (fastest debug loop)
./dev e2e test "click with humanize: click input by ref"
./dev e2e test "scroll (down)"
./dev e2e test "low-level mouse"
The scenario filter is one plain substring (no regex, no |) matched against scenario file names, groups, tiers, helpers and tags. Requires Docker daemon running.
Single-test mode (dev e2e test "<name>")
Use this when iterating on one specific E2E failure. The runner:
- Greps
tests/e2e/scenarios/**/*.shforstart_test "...<name substring>...". - Auto-picks the suite (
api/cli/infra/plugin) and-extendedvariant (orsmokefor*-smoke.sh) from the matching scenario file's path. - Builds the images (
compose build, thenup) and runs, inside that scenario file, only thestart_test...end_testblocks whose name contains the substring — the scenario preamble (helper sourcing,FIXTURES_URL, etc.) is preserved, every other test in the file is skipped.
Notes:
- The substring is literal (fgrep), so colons/parens/quotes in test names work without escaping.
- If several tests match, the scenario file of the first match is used and the others are printed — pass a longer/more-specific substring to disambiguate. It is not a way to run a group of tests; for a whole scenario use
go run ./tests/tools/runner e2e --suite <suite> --filter <stem>. - Logs stream to the terminal by default (unlike full suites which hide logs); helpful for debugging.
- Implemented by
scripts/dev-e2e.sh→go run ./tests/tools/runner e2e --suite … --filter <stem> --test "<name>", which passesE2E_TEST_FILTERtotests/e2e/run.sh.
Dashboard Tests
./dev test dashboard # Vitest
cd dashboard && npm test
Dashboard Development
Setup
Start hot-reload development:
./dev dashboard
This runs:
- Backend on
:9867 - Vite dev server on
:5173with hot-reload - Dashboard at
http://localhost:5173/dashboard/
Development Workflow (Use PinchTab to Develop PinchTab)
Do not assume changes worked. Use pinchtab itself to verify changes visually:
-
Start dev mode:
./dev dashboard -
Make changes to files in
dashboard/src/ -
Verify with pinchtab — use the pinchtab skill to inspect the dashboard:
# ./dev dashboard runs the backend with token "dev" # Navigate to the page under development curl -X POST http://localhost:9867/navigate -H "Authorization: Bearer dev" \ -d '{"url":"http://localhost:5173/dashboard/settings"}' # Take a screenshot (written under the state dir; response carries "path") curl -H "Authorization: Bearer dev" "http://localhost:9867/screenshot?output=file" # Or get a snapshot to inspect elements curl -s -H "Authorization: Bearer dev" http://localhost:9867/snapshot | jq . -
Provide evidence — when reporting changes, include:
- Link to the page:
http://localhost:5173/dashboard/{page} - Screenshot of the result
- Relevant snapshot data if inspecting specific elements
- Link to the page:
Example: Verifying a Settings Page Change
# Navigate to settings
curl -X POST http://localhost:9867/navigate -H "Authorization: Bearer dev" \
-d '{"url":"http://localhost:5173/dashboard/settings"}'
# Screenshot the result (beyondViewport=true captures the full page)
curl -H "Authorization: Bearer dev" \
"http://localhost:9867/screenshot?output=file&beyondViewport=true"
# Find an element by description (semantic match, not a CSS selector)
curl -X POST http://localhost:9867/find -H "Authorization: Bearer dev" \
-d '{"query":"stealth level setting"}'
Key Dashboard Pages
| Page | URL | Purpose |
|---|---|---|
| Monitoring | /dashboard/monitoring |
Instance overview (/dashboard/ redirects here) |
| Activity | /dashboard/activity |
Activity log |
| Profiles | /dashboard/profiles |
Browser profiles |
| Agents | /dashboard/agents |
Agents |
| Settings | /dashboard/settings |
Configuration |
Dashboard Tech Stack
- React 19 + TypeScript
- Vite (build/dev)
- Tailwind CSS
- Zustand (state)
- Vitest (tests)
Stealth Module
The stealth module (internal/assets/stealth.js) has three levels:
| Level | Features | Trade-offs |
|---|---|---|
light |
webdriver, CDP markers, plugins, hardware | None — safe |
medium |
+ userAgentData, chrome.runtime.connect, puppeteer/playwright marker cleanup | May affect error monitoring, extension messaging |
full |
+ screen/window realism, headless-only WebGL vendor/renderer spoofing (canvas/audio/WebRTC stay native) | May break graphics-dependent sites in headless mode |
Configure in ~/.pinchtab/config.json:
{
"instanceDefaults": {
"stealthLevel": "medium"
}
}
Common Tasks
Add new API endpoint
- Create handler in
internal/handlers/ - Add the endpoint to
internal/routes/routes.goand bind it in therouteBindingtable ininternal/handlers/handlers.go - Add tests in same package
- Add E2E test in
tests/e2e/scenarios/api/
Modify stealth behavior
- Edit
internal/assets/stealth.js - Run
./dev build(embeds via go:embed) - Test with
./dev e2e infra stealth(infra scenarios matchingstealth;infra-extended stealthfor the extended ones)
Update dashboard
- Run
./dev dashboardfor hot-reload - Edit files in
dashboard/src/ - Run
./dev check dashboardbefore commit
Version History
-
83666d2
Current 2026-09-22 22:12
更新开发脚本说明,修正e2e runner调用方式;调整项目路径为仓库根目录;架构文档移除routes/config模块并补充plugin测试路径。
- d81a2a8 2026-08-20 08:45


