Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Agent toolchain

Canonical policy lives in [`/AGENTS.md`](../AGENTS.md). This directory only
holds:

- [`skills/`](skills) — playbooks for coding agents. Read a skill's
`SKILL.md` only when its description matches the task at hand.
56 changes: 56 additions & 0 deletions .agents/skills/concise-writing/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: concise-writing
description: Keep everything written in this repo — commit messages, PR titles/descriptions, and code comments — clear and terse. Use whenever creating a git commit, opening or updating a pull request, or writing/reviewing a code comment; also covers /commit and requests like "commit this", "open a PR", or "write a comment explaining this".
---

Everything written *about* the code in this repo — commit messages, PR descriptions, code comments — should say the minimum needed to be understood, and no more. The reader (a maintainer, a reviewer, a future agent) can already read the diff; don't narrate it back to them. Say what isn't obvious from the code itself: the *why*, not the *what*.

This applies across three surfaces. Jump to the one you need:

## Commit messages

Gather context first — run together, since none depends on the others:
- `git status` — what's changed and what's untracked
- `git diff` (unstaged) and `git diff --staged` — the actual content
- `git log --oneline -15` — refresh on this repo's message style

This repo's history is consistently `type: terse imperative summary`, e.g.:
```
fix: serialize per-package releases in release.yml
fix: correct .npmignore packaging rules across all 3 driver packages
test: split edgedriver's unit.test.ts by source module
fix: harden edgedriver install.ts against Windows and Zip Slip bugs
```
- One line, imperative mood, `type: summary`, no trailing period.
- Lead with *why*, not a mechanical restatement of the diff (bad: "update release.yml"; good: "detect which driver package changed before releasing 'all'").
- Only add a body if the one-liner genuinely can't carry the reasoning — rare in this repo's history. Default to skipping it.
- Pick the type by what changed: `fix`, `feat`, `test`, `ci`, `chore`, `docs`, `refactor`.

**Staging**: stage specific files by name (`git add path/to/file`), never a blanket `git add -A` or `git add .` — this repo's workflows and driver packages touch config and secrets-adjacent files, and a blind add risks scooping up something that doesn't belong. Check `git status` first for anything unexpected or secret-looking (`.env`, `credentials.json`, `*.pem`, `*token*`) and flag it instead of silently staging it.

**Committing**: pass the message via a heredoc so formatting survives:
```bash
git commit -m "$(cat <<'EOF'
type: terse summary here
EOF
)"
```
Append whatever attribution footer this session's own instructions specify — don't hardcode one here, since it can change independently of this skill.

Never amend an existing commit unless explicitly asked — a fresh commit is the default. Never pass `--no-verify` or otherwise skip hooks unless explicitly told to; if a pre-commit hook fails, fix the underlying issue and commit again. After committing, run `git status` to confirm it landed, and report back in one line what was committed — don't dump the full diff back at the user.

## PR titles and descriptions

- Title under ~70 characters, same "why, not what" rule as commit summaries.
- Body: a short `## Summary` (1-3 bullets, what changed and why it was needed — not a file-by-file listing the diff already shows) plus a `## Test plan` checklist of what was actually run. Skip sections that would just restate the diff.
- Don't repeat the same information across every commit in the PR *and* the PR description *and* a summary comment — pick the level (usually the PR description) and let the rest stay terse.
- When reviewing someone else's PR description for terseness, flag sentences that only restate a line from the diff without adding reasoning, and padding like "This PR also includes minor cleanup" with nothing concrete after it.

## Code comments

Default to no comment. Well-named functions and variables already say *what* the code does. Only add a comment when it carries information the code can't:
- a non-obvious constraint or invariant
- the reason for a workaround (link the issue/bug if there is one)
- behavior that would genuinely surprise a reader

One line is almost always enough. This repo's existing multi-line comments are the exception that proves the rule — e.g. `packages/node-edgedriver/src/finder.ts` explains a 3-step platform-detection fallback that genuinely isn't obvious from the code alone — not a narration of what each line does. If removing a comment wouldn't leave a future reader confused, remove it.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ coverage
*.tgz
*.tsbuildinfo
.DS_Store
.claude/
70 changes: 70 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# AGENTS.md

Entry point for coding agents in this repo. See [.agents/README.md](.agents/README.md)
for available skills — read a skill's `SKILL.md` when its description matches
the task, don't duplicate its rules here.

No tool-specific agent config is committed beside `.agents/` — permissions,
hooks, and other per-tool settings (e.g. `.claude/`) stay personal and local,
never added to this repo. A thin adapter file like `CLAUDE.md` is the one
exception: it only points here, it doesn't hold its own copy of these rules.

## Repo map

pnpm workspace, no lerna/nx. The three driver packages are independent —
no shared dependencies between them, no monorepo-wide version to keep in sync:

```
packages/node-edgedriver Edge driver binary manager → npm: edgedriver
packages/node-geckodriver Firefox driver binary manager → npm: geckodriver
packages/node-safaridriver Safari driver manager → npm: safaridriver
packages/e2e real-browser e2e tests for all three
scripts/ shared build helpers (e.g. copy-cjs-pkg.mjs)
```

Each driver package has its own `.release-it.json`, `package.json` version,
and `.npmignore`.

## Setup

Node from [`.nvmrc`](.nvmrc) (24), pnpm pinned in `package.json#packageManager`.

```sh
pnpm install
pnpm run build # tsc -b per package + CJS shim (scripts/copy-cjs-pkg.mjs)
```

`src/` edits aren't visible to tests or `postinstall` until rebuilt — use
`pnpm run watch` (all packages) or `pnpm --filter <pkg> run watch` (one).

## Test selection

Don't default to `pnpm run checks:all` — it's lint + unit + e2e for every
package. Prefer the smallest proof:

| Change | Run |
|---|---|
| One driver package | `pnpm --filter <pkg> test` (that package's lint + unit) — `<pkg>` is the npm name (`edgedriver`, `geckodriver`, `safaridriver`, `e2e`), not the `packages/node-*` directory name |
| Root config, `scripts/`, or more than one package | `pnpm run test:lint`, then `pnpm test` |
| Driver launch / real browser behavior | `pnpm run test:e2e` — needs real Edge/Firefox/Safari installed; CI runs it under xvfb on macOS/Linux/Windows, skip locally if you don't have the browsers |

Lint is oxlint ([`.oxlintrc.json`](.oxlintrc.json)), not eslint —
`@stylistic/eslint-plugin` is only pulled in as an oxlint plugin. Husky runs
`test:lint` pre-commit and `pnpm test` pre-push; don't bypass either with
`--no-verify`.

## Releases

Manual, via the "Manual NPM Publish" GitHub Action
([.github/workflows/release.yml](.github/workflows/release.yml)) — never
automatic on merge. It runs `release-it` per package, tags as
`<driver>@<version>`, and auto-skips packages with no changes since their
last tag when `driver: all` is selected (picking one driver explicitly always
releases it). Use `dryRun: yes` to exercise the whole flow without publishing
or tagging anything for real.

## Working agreement

Commit messages, PR descriptions, code comments, and how to stage changes:
see the [concise-writing](.agents/skills/concise-writing/SKILL.md) skill —
same "why, not what" rule across all of it.
4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Claude Code

Follow [AGENTS.md](./AGENTS.md). It is the canonical agent guide for this
repository. Do not add a second copy of those rules here.
Loading