Chrome Devtools MCP
managedcode/dotnet-skills
Use Chrome DevTools MCP from .NET agents and .NET-focused repos to inspect, debug, and automate Chrome through an MCP client.
This skill should be used when the user is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w, interface design (accept interfaces return structs)…
$ npx skills add chromedp/chromedp --skill go-pedantry -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install chromedp/chromedp go-pedantry --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/go-pedantry .claude/skills/go-pedantry && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .claude/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantryType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add chromedp/chromedp --skill go-pedantry -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install chromedp/chromedp go-pedantry --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/go-pedantry .agents/skills/go-pedantry && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .agents/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add chromedp/chromedp --skill go-pedantry -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install chromedp/chromedp go-pedantry --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/go-pedantry .cursor/skills/go-pedantry && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .cursor/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/chromedp/chromedp.git --path .agents/skills/go-pedantry--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add chromedp/chromedp --skill go-pedantry -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install chromedp/chromedp go-pedantry --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/go-pedantry .gemini/skills/go-pedantry && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .gemini/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install chromedp/chromedp go-pedantryInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add chromedp/chromedp --skill go-pedantry -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/go-pedantry .github/skills/go-pedantry && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .github/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add chromedp/chromedp --skill go-pedantry -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install chromedp/chromedp go-pedantry --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/chromedp/chromedp.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/go-pedantry .opencode/skills/go-pedantry && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "go-pedantry" agent skill from https://github.com/chromedp/chromedp/tree/main/.agents/skills/go-pedantry into .opencode/skills/go-pedantry/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "go-pedantry", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
go-pedantryThis skill should be used when the user is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w, interface design (accept interfaces return structs)…
Go Pedantry is an agent skill from chromedp/chromedp. This skill should be used when the user is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w, interface design (accept interfaces return structs), package naming conventions, struct field ordering, receiver naming, golangci-lint configuration, and Go-specific patterns that go beyond universal principles.
Its SKILL.md is about 3.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files (for example `examples/error-wrapping.md` and `examples/interface-design.md`).
It sits in Development, covering API design, Linting and formatting and Browser testing. It works with Chrome DevTools and Go. The repository describes itself as: A faster, simpler way to drive browsers supporting the Chrome DevTools Protocol. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit dddfecf. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are go and yaml).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Go Pedantry loads about 3.7k tokens when it runs. Until then it costs about 91 tokens; SKILL.md has 777 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from chromedp/chromedp at commit dddfecf, republished under its MIT licence (© chromedp). 777 words, ~3,697 tokens.
.claude/skills/go-pedantry/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Go is a language that already has strong opinions: gofmt, short variable names, explicit error handling, no exceptions. But the language's opinions stop at syntax. How you wrap errors, design interfaces, name packages, order struct fields, and configure your linter -- these are decisions Go leaves to you. This skill makes those decisions for you, because inconsistency in these areas is what turns a Go codebase from clean to chaotic.
%w, Never %s or %vWhen wrapping an error with fmt.Errorf, ALWAYS use %w. This preserves the error chain so that errors.Is() and errors.As() work. Using %s or %v converts the error to a string and destroys the chain. This is not a style preference -- it is the difference between errors that can be programmatically handled and errors that can only be logged.
// BAD -- error chain is destroyed, errors.Is() will not work
func GetUser(ctx context.Context, id string) (*User, error) {
user, err := db.QueryUser(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get user %s: %s", id, err.Error())
}
return user, nil
}
// BAD -- %v also destroys the chain
func GetUser(ctx context.Context, id string) (*User, error) {
user, err := db.QueryUser(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get user %s: %v", id, err)
}
return user, nil
}// GOOD -- %w preserves the error chain
func GetUser(ctx context.Context, id string) (*User, error) {
user, err := db.QueryUser(ctx, id)
if err != nil {
return nil, fmt.Errorf("getting user %s: %w", id, err)
}
return user, nil
}
// Now callers can inspect the error chain:
user, err := GetUser(ctx, "usr_123")
if errors.Is(err, sql.ErrNoRows) {
// handle not found
}Error message conventions:
"getting user %s: %w" not "an error occurred while attempting to retrieve the user with ID %s from the database: %w"Sentinel errors (package-level error values) follow a strict naming convention:
// GOOD -- exported, Err prefix, PascalCase after prefix
var (
ErrNotFound = errors.New("not found")
ErrAlreadyExists = errors.New("already exists")
ErrInvalidInput = errors.New("invalid input")
ErrUnauthorized = errors.New("unauthorized")
ErrRateLimited = errors.New("rate limited")
)// BAD -- every one of these violates the convention
var (
NotFoundError = errors.New("not found") // wrong: no Err prefix
errnotfound = errors.New("not found") // wrong: unexported + no camelCase
NOT_FOUND = errors.New("not found") // wrong: not Go convention
UserNotFound = errors.New("user not found") // wrong: no Err prefix
)Custom error types follow the same prefix pattern:
// GOOD
type ErrValidation struct {
Field string
Message string
}
func (e *ErrValidation) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message)
}Functions accept interfaces so they can work with any implementation. Functions return concrete structs so the caller has the full type. This is the fundamental Go interface rule.
// BAD -- returning an interface hides the concrete type
func NewUserService(db Database) UserServiceInterface {
return &UserService{db: db}
}
// BAD -- accepting a concrete type prevents testing and alternative implementations
func ProcessOrder(service *StripeService, order *Order) error {
return service.Charge(order.Total)
}// GOOD -- accept interface, return struct
func NewUserService(db UserRepository) *UserService {
return &UserService{db: db}
}
// GOOD -- accept interface for the dependency
func ProcessOrder(payment PaymentProcessor, order *Order) error {
return payment.Charge(order.Total)
}Go interfaces should be small. One to three methods. If your interface has more than three methods, it is probably doing too much.
// BAD -- too many methods, too specific
type UserManager interface {
GetUser(ctx context.Context, id string) (*User, error)
CreateUser(ctx context.Context, input CreateUserInput) (*User, error)
UpdateUser(ctx context.Context, id string, input UpdateUserInput) (*User, error)
DeleteUser(ctx context.Context, id string) error
ListUsers(ctx context.Context, opts ListOptions) ([]*User, error)
SearchUsers(ctx context.Context, query string) ([]*User, error)
CountUsers(ctx context.Context) (int, error)
}// GOOD -- small, focused interfaces
type UserReader interface {
GetUser(ctx context.Context, id string) (*User, error)
}
type UserWriter interface {
CreateUser(ctx context.Context, input CreateUserInput) (*User, error)
UpdateUser(ctx context.Context, id string, input UpdateUserInput) (*User, error)
DeleteUser(ctx context.Context, id string) error
}
type UserLister interface {
ListUsers(ctx context.Context, opts ListOptions) ([]*User, error)
}Interfaces belong where they are used, not where they are implemented. The consumer defines what it needs; the implementation satisfies it without knowing.
// BAD -- interface defined in the implementation package
// package database
type UserStore interface {
Get(ctx context.Context, id string) (*User, error)
Save(ctx context.Context, user *User) error
}
type PostgresUserStore struct { ... }// GOOD -- interface defined where it is used
// package handler (the consumer)
type UserGetter interface {
Get(ctx context.Context, id string) (*User, error)
}
type GetUserHandler struct {
users UserGetter // accepts interface
}
// package database (the implementation)
type PostgresUserStore struct { ... }
func (s *PostgresUserStore) Get(ctx context.Context, id string) (*User, error) { ... }
// PostgresUserStore satisfies handler.UserGetter without importing itSingle-method interfaces are named: Verb + "er".
| Method | Interface Name |
|---|---|
Read() | Reader |
Write() | Writer |
Close() | Closer |
Format() | Formatter |
Validate() | Validator |
Handle() | Handler |
Encode() | Encoder |
Go packages have strict naming conventions that the community enforces by reputation.
Rules:
user, auth, config, orderuserservice not userService or user_serviceuser.Service not user.UserServiceutils, helpers, common, misc, shared, base -- these are organizational failures// BAD -- package naming violations
package userService // camelCase
package user_service // underscores
package utils // meaningless
package common // meaningless
package helpers // meaningless
// In user package:
type UserService struct{} // stutters: user.UserService
type UserRepository struct{} // stutters: user.UserRepository// GOOD -- clean package names
package user
type Service struct{} // user.Service -- reads naturally
type Repository struct{} // user.Repository -- no stutter
package auth
type Token struct{} // auth.Token
type Middleware struct{} // auth.Middleware
package order
type Processor struct{} // order.ProcessorStruct fields are ordered by purpose, not alphabetically. Exported fields come first. Related fields are grouped. Groups are separated by blank lines.
// BAD -- no logical grouping
type Server struct {
addr string
logger *slog.Logger
TLS bool
db *sql.DB
Port int
Host string
readTimeout time.Duration
cache *Cache
WriteTimeout time.Duration
maxConns int
}// GOOD -- grouped by purpose, exported first within groups, tags consistent
type Server struct {
// Configuration (exported)
Host string `json:"host" yaml:"host"`
Port int `json:"port" yaml:"port"`
TLS bool `json:"tls" yaml:"tls"`
ReadTimeout time.Duration `json:"read_timeout" yaml:"read_timeout"`
WriteTimeout time.Duration `json:"write_timeout" yaml:"write_timeout"`
MaxConns int `json:"max_conns" yaml:"max_conns"`
// Dependencies (unexported)
db *sql.DB
cache *Cache
logger *slog.Logger
}Rules:
json:"snake_case")Receivers are one or two lowercase letters derived from the type name. They are consistent across ALL methods on the type. Never use this or self.
// BAD -- inconsistent receivers, verbose names
func (server *Server) Start() error { ... }
func (s *Server) Stop() error { ... }
func (this *Server) Addr() string { ... }
func (self *Server) IsRunning() bool { ... }// GOOD -- consistent single-letter receiver
func (s *Server) Start() error { ... }
func (s *Server) Stop() error { ... }
func (s *Server) Addr() string { ... }
func (s *Server) IsRunning() bool { ... }| Type | Receiver |
|---|---|
Server | s |
User | u |
OrderProcessor | op |
ConfigService | cs |
Handler | h |
Client | c |
Repository | r |
Two-letter receivers are for when the single letter would be ambiguous (multiple types starting with the same letter in the same file).
context.Context is always the first parameter. Always named ctx. Never stored in a struct.
// BAD -- context in wrong position
func GetUser(id string, ctx context.Context) (*User, error) { ... }
// BAD -- context stored in struct
type Service struct {
ctx context.Context
db *sql.DB
}
// BAD -- context not named ctx
func GetUser(c context.Context, id string) (*User, error) { ... }// GOOD -- context first, named ctx
func GetUser(ctx context.Context, id string) (*User, error) { ... }
func (s *Service) ProcessOrder(ctx context.Context, order *Order) error { ... }# .golangci.yml
linters:
enable:
- errcheck # unchecked errors
- gosimple # simplifications
- govet # suspicious constructs
- ineffassign # unused assignments
- staticcheck # advanced static analysis
- unused # unused code
- gocritic # opinionated checks
- revive # flexible linter
- errorlint # error wrapping correctness
- nilerr # returning nil when err is not nil
- wrapcheck # errors from external packages are wrapped
- prealloc # slice pre-allocation
- unconvert # unnecessary type conversions
- tenv # os.Setenv in tests (use t.Setenv)
linters-settings:
gocritic:
enabled-checks:
- appendAssign
- argOrder
- badCall
- badCond
- dupArg
- dupBranchBody
- dupCase
- elseif
- flagDeref
- nilValReturn
- singleCaseSwitch
- underef
- unnecessaryBlock
revive:
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-naming
- name: error-return
- name: error-strings
- name: exported
- name: increment-decrement
- name: indent-error-flow
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: var-naming
- name: unexported-return
errorlint:
errorf: true # check fmt.Errorf uses %w
asserts: true # check errors.As uses pointer
comparison: true # check errors.Is instead of ==Working implementations in examples/:
examples/error-wrapping.md -- Complete Go examples showing proper error wrapping with %w, error message conventions, sentinel errors, and custom error types with errors.Is/errors.As patternsexamples/interface-design.md -- Go examples showing interface design patterns: accept interfaces/return structs, small interfaces, consumer-side definition, and the Verb+er naming conventionWhen reviewing Go code:
fmt.Errorf("context: %w", err) -- never %s or %v for errorsErr prefix with PascalCase: ErrNotFound, ErrInvalidInputReader, Writer, Validator)utils, helpers, commonuser.Service not user.UserServicejson:"snake_case")this or self receiverscontext.Context is always the first parameter, always named ctx, never stored in a structgolangci-lint is configured with at minimum: errcheck, gosimple, govet, staticcheck, unused, gocritic, revive, errorlint© chromedp, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files in .agents/skills/go-pedantry of chromedp/chromedp.
Open the folder on GitHubat commit dddfecf
Go Pedantry next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Go Pedantry this skillchromedp/chromedp | 13k | — | ~3.7k | Automated safety check: Pass | MIT | |
| Chrome Devtools MCPmanagedcode/dotnet-skills | 486 | — | ~2.2k | Automated safety check: Pass | MIT | |
| System Bridge Testing Workflowtimmo001/system-bridge | 357 | — | ~844 | Automated safety check: Pass | Apache-2.0 | |
| Browser Tools981377660LMT/algorithm-study | 277 | 1 repos | ~1.3k | Automated safety check: Pass | None | |
| Run Dozzle Dev Instanceamir20/dozzle | 15k | — | ~747 | Automated safety check: Pass | MIT | |
| Extension Puppeteer Debuggingmengxi-ream/read-frog | 10k | — | ~2k | Automated safety check: Notes | GPL-3.0 |
managedcode/dotnet-skills
Use Chrome DevTools MCP from .NET agents and .NET-focused repos to inspect, debug, and automate Chrome through an MCP client.
timmo001/system-bridge
How to test System Bridge - Go table-driven tests and commands, web-client quality checks (lint/typecheck/format, no unit tests), the Chrome DevTools MCP interactive test loop for UI and WebSocket…
981377660LMT/algorithm-study
Interactive browser automation via Chrome DevTools Protocol.
amir20/dozzle
Starts a Dozzle dev server on a port derived from the current worktree so you can test by hand in a browser, without disturbing instances started elsewhere.
mengxi-ream/read-frog
Debug the built Read Frog extension in real Chrome. An agent skill from mengxi-ream/read-frog.
TracecatHQ/tracecat
A skill your agent uses when adding or updating documentation pages in an existing docs site.
Works with
Categories
This skill should be used when the user is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w, interface design (accept interfaces return structs)…. Go Pedantry is an agent skill from chromedp/chromedp.Errorf and %w, interface design (accept interfaces return structs), package naming conventions, struct field ordering, receiver naming, golangci-lint configuration, and Go-specific patterns that go beyond universal principles.
Go Pedantry fits situations like: is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w; interface design (accept interfaces return structs); package naming conventions; struct field ordering.
Run `npx skills add chromedp/chromedp --skill go-pedantry -a claude-code`. Or copy the skill folder (.agents/skills/go-pedantry in chromedp/chromedp) into .claude/skills/go-pedantry in your project. Claude Code loads it when a task matches its description.
Run `npx skills add chromedp/chromedp --skill go-pedantry -a codex`. Or copy the skill folder (.agents/skills/go-pedantry in chromedp/chromedp) into .agents/skills/go-pedantry in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add chromedp/chromedp --skill go-pedantry -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/go-pedantry, .gemini/skills/go-pedantry, .github/skills/go-pedantry and .opencode/skills/go-pedantry in your project.
SKILL.md names no scripts, command-line tools or credentials: Go Pedantry is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Go Pedantry is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.7k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Go Pedantry: Chrome Devtools MCP (managedcode/dotnet-skills, 486 stars), System Bridge Testing Workflow (timmo001/system-bridge, 357 stars), Browser Tools (981377660LMT/algorithm-study, 277 stars) and Run Dozzle Dev Instance (amir20/dozzle, 15k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
chromedp (a GitHub organization) maintains it in chromedp/chromedp, which has 13,301 GitHub stars. The repository was last updated on October 5, 2026.
Source: chromedp/chromedp on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.