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
1 change: 1 addition & 0 deletions .claude/skills
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
cooldown:
default-days: 3
groups:
dev-dependencies:
dependency-type: development
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
cooldown:
default-days: 3
groups:
actions:
patterns: ["*"]
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
check:
name: lint, format, types, unused code
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm format:check
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm knip

test:
name: test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm test:coverage
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
node_modules
coverage
*.tsbuildinfo
# Auto-generated by dotagents — do not commit these files.
agents.lock
.agents/.gitignore
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
5 changes: 5 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 80,
"ignorePatterns": ["pnpm-lock.yaml", "coverage/**"]
}
47 changes: 47 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": [
"eslint",
"typescript",
"unicorn",
"oxc",
"import",
"node",
"promise",
"vitest"
],
"categories": {
"correctness": "error",
"suspicious": "error",
"perf": "error"
},
"options": {
"typeAware": true,
"reportUnusedDisableDirectives": "error"
},
"rules": {
"eqeqeq": "error",
"no-var": "error",
"prefer-const": "error",
"typescript/no-explicit-any": "error",
"typescript/switch-exhaustiveness-check": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/prefer-nullish-coalescing": "error",
"typescript/prefer-optional-chain": "error",
"typescript/no-import-type-side-effects": "error",
"import/no-cycle": "error",
"import/no-duplicates": "error",
"node/no-process-env": "off",
"eslint/no-await-in-loop": "off",
"typescript/no-unsafe-type-assertion": "off"
},
"ignorePatterns": ["coverage/**"],
"overrides": [
{
"files": ["tests/**"],
"rules": {
"typescript/no-non-null-assertion": "off"
}
}
]
}
46 changes: 46 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Agent Instructions

## Package Manager

- Use **pnpm** (`pnpm install`) on Node 24 (`.node-version`).
- Install agent skills with `pnpm skills:install` (`agents.toml`).

## Commands

| Task | Command |
| ---------------- | ------------------------------------------------- |
| Test file | `pnpm exec vitest run tests/roach.test.ts` |
| Test case | `pnpm exec vitest run tests/roach.test.ts -t "…"` |
| Lint file | `pnpm exec oxlint --deny-warnings src/server.ts` |
| Format | `pnpm format` |
| Typecheck | `pnpm typecheck` |
| Unused code/deps | `pnpm knip` |
| Everything (CI) | `pnpm check` |

## External References

| Need | File |
| -------------------------------------- | ---------------------- |
| Usage, config, recordings, control API | `README.md` |
| Public types | `src/types.ts` |
| Map of source files | "Files" in `README.md` |

## Key Conventions

- Add no runtime dependencies. Use Node built-ins and the `openssl` command only.
- Node runs `src/` as TypeScript with type stripping. Use only erasable syntax, and import local files with the `.ts` extension.
- Use functions and plain objects, not classes.
- Start each source file with a comment that says what the file owns. Give each export a short JSDoc.
- Update `README.md` in the same change when behavior, config, or the control API changes.
- Test through a real proxy and a local upstream server in `tests/`. Do not mock modules. Do not reach the internet.
- The proxy decrypts HTTPS. Never write a credential: every recording and miss file goes through `src/secrets.ts`.
- The upstream host always comes from `allow`, never from the client.
- Write docs in ASD-STE100 English: common words, active voice, short sentences.

## Commit Attribution

AI commits MUST include:

```
Co-Authored-By: (the agent's name and attribution byline)
```
1 change: 1 addition & 0 deletions CLAUDE.md
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,19 @@ All calls need `Authorization: Bearer <token>`. `client.ts` calls them.
Returns HTTP 409 when the session is not open.
- `GET /__roach/stats`: the totals of the run.

## Development

```sh
pnpm install
pnpm check # format, lint, types, unused code, and tests, as CI runs them
```

`AGENTS.md` has the conventions and the commands for one file.

## Files

All source files are in `src/`. Tests are in `tests/`.


- `types.ts`: the configuration and the results.
- `server.ts`: sockets, HTTPS interception, the allow list, and the control
API.
Expand Down
31 changes: 31 additions & 0 deletions agents.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version = 1
# Skills always fetch the latest version; the lockfile tracks names only.
agents = ["claude", "codex", "cursor"]

[[skills]]
name = "commit"
source = "getsentry/skills"

[[skills]]
name = "pr-writer"
source = "getsentry/skills"

[[skills]]
name = "code-review"
source = "getsentry/skills"

[[skills]]
name = "find-bugs"
source = "getsentry/skills"

[[skills]]
name = "security-review"
source = "getsentry/skills"

[[skills]]
name = "gha-security-review"
source = "getsentry/skills"

[[skills]]
name = "agents-md"
source = "getsentry/skills"
5 changes: 5 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"project": ["src/**/*.ts", "tests/**/*.ts"],
"ignoreBinaries": ["openssl"]
}
52 changes: 42 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"private": true,
"description": "A recording HTTPS proxy for tests.",
"license": "Apache-2.0",
"type": "module",
"engines": {
"node": ">=22.18"
"repository": {
"type": "git",
"url": "git+https://github.com/getsentry/roach.git"
},
"packageManager": "pnpm@11.8.0",
"bin": {
"roach": "./src/cli.ts"
},
"type": "module",
"exports": {
"./client": "./src/client.ts",
"./report": "./src/report.ts",
Expand All @@ -20,13 +20,45 @@
"./values": "./src/values.ts"
},
"scripts": {
"check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm knip && pnpm test",
"format": "oxfmt",
"format:check": "oxfmt --check",
"knip": "knip",
"lint": "oxlint --deny-warnings",
"lint:fix": "oxlint --fix",
"prepare": "simple-git-hooks",
"skills:install": "dotagents --project install",
"test": "vitest run",
"typecheck": "tsc --noEmit"
"test:coverage": "vitest run --coverage",
"typecheck": "tsc -p ."
},
"devDependencies": {
"@types/node": "^25.9.1",
"typescript": "^6.0.3",
"undici": "7.29.0",
"vitest": "^4.1.7"
}
"@sentry/dotagents": "^3.3.0",
"@types/node": "^24.19.1",
"@vitest/coverage-v8": "^5.0.3",
"knip": "^6.40.0",
"lint-staged": "^17.6.0",
"oxfmt": "^0.72.0",
"oxlint": "^1.87.0",
"oxlint-tsgolint": "^7.0.2003",
"simple-git-hooks": "^2.14.0",
"typescript": "^7.0.2",
"undici": "^8.11.2",
"vitest": "^5.0.3"
},
"simple-git-hooks": {
"pre-commit": "pnpm exec lint-staged",
"pre-push": "pnpm typecheck"
},
"lint-staged": {
"*.{ts,mts,js,mjs}": [
"oxlint --fix --deny-warnings",
"oxfmt --no-error-on-unmatched-pattern"
],
"*.{json,jsonc,md,yml,yaml}": "oxfmt --no-error-on-unmatched-pattern"
},
"engines": {
"node": ">=24"
},
"packageManager": "pnpm@11.8.0"
}
Loading
Loading