pentestcode
AGENTS.md884 starsChanged 4 months agoMITView on GitHub
Use a short branch name of at most three words, separated by hyphens. Do not use slashes or type prefixes such as feat/ or fix/. Examples: session-recovery, fix-scroll-state, regenerate-sdk. Use conventional commit-style messages and PR titles: type(scope): summary. Valid types are feat, fix, docs, chore, refactor, and test. Scopes are optional; use the affected package or area when helpful, e.g. core, opencode, tui, app, desktop, sdk, or plugin. Examples: fix(tui): simplify thinking toggle styling, docs: update contributing guide, chore(sdk): regenerate…
We split this AGENTS.md into the rules it gives an agent
30 rules. About 0 are common, 11 are distinctive, and 19 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈11
Distinctive · estimate
This author's own choices. Worth a look.
19
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 2
After changing the public Protocol or Server HttpApi, run bun run generate from packages/client.
- Very specific: line 3
Keep runtime dependencies directed from Schema to Core and Protocol, then from Core and Protocol to Server.
- Very specific: line 9
Use a short branch name of at most three words, separated by hyphens.
- Very specific: line 15
Use conventional commit-style messages and PR titles: type(scope): summary.
- Distinctive: line 25
Keep things in one function unless composable or reusable
- Distinctive: line 26
Do not extract single-use helpers preemptively.
- Very specific: line 27
Avoid try/catch where possible
- Very specific: line 28
Avoid using the any type
- Very specific: line 29
Use Bun APIs when possible, like Bun.file()
- Distinctive: line 31
Prefer functional array methods (flatMap, filter, map) over for loops.
- Distinctive: line 48
Avoid unnecessary destructuring.
- Very specific: line 61
Never alias imports. Do not use import { foo as bar } from "..." or renamed imports like resolve as pathResolve.
- Very specific: line 62
Never use star imports. Do not use import * as Foo from "..." or import type * as Foo from "...".
- Very specific: line 63
If a namespace-style value is needed, import the module's own exported namespace by name, for example import { Project } from …
- Very specific: line 68
Prefer const over let. Use ternaries or early returns instead of reassignment.
- Very specific: line 82
Avoid else statements. Prefer early returns.
- Distinctive: line 100
When a function has several validation branches or supporting details, make the main function read as the happy path and move supporting …
- Distinctive: line 115
Keep helpers close to the code they support, below the main export when that improves readability.
- Very specific: line 116
Do not over-abstract simple expressions into many single-use helpers.
- Very specific: line 117
Do not return Effect from helpers unless they actually perform effectful work.
- Very specific: line 118
Prefer Effect schema helpers such as Schema.UnknownFromJsonString and Schema.decodeUnknownOption over manual JSON.parse wrapped in …
- Distinctive: line 119
Add comments for non-obvious constraints and surprising behavior, not for obvious assignments or control flow.
- Distinctive: line 123
Use snake_case for field names so column names don't need to be redefined as strings.
- Distinctive: line 143
Avoid mocks as much as possible, you shouldn't be using globalThis.\* at all unless it's the only option.
- Distinctive: line 144
Test actual implementation, do not duplicate logic into tests
- Very specific: line 149
Always run bun typecheck from package directories (e.g., packages/opencode), never tsc directly.
- Very specific: line 153
Keep durable prompt admission separate from model execution.
- Very specific: line 156
Keep SessionRunner, model resolution, tool registry, permissions, and filesystem Location-scoped.
- Distinctive: line 160
Keep EventV2 replay owner claims separate from clustered Session execution ownership.
- Very specific: line 161
Keep the System Context algebra, registry, and built-ins in src/system-context.
≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
- To regenerate the legacy JavaScript SDK, run
./packages/sdk/js/script/build.ts. - After changing the public Protocol or Server
HttpApi, runbun run generatefrompackages/client. Do not editsrc/generatedorsrc/generated-effectdirectly. - Keep runtime dependencies directed from Schema to Core and Protocol, then from Core and Protocol to Server. Client runtime code may depend on Schema and Protocol but never Core or Server;
sdk-nextcomposes Client, Core, and Server. - The default branch in this repo is
dev. - Local
mainref may not exist; usedevororigin/devfor diffs.
Branch Names
Use a short branch name of at most three words, separated by hyphens. Do not use slashes or type prefixes such as feat/ or fix/.
Examples: session-recovery, fix-scroll-state, regenerate-sdk.
Commits and PR Titles
Use conventional commit-style messages and PR titles: type(scope): summary.
Valid types are feat, fix, docs, chore, refactor, and test. Scopes are optional; use the affected package or area when helpful, e.g. core, opencode, tui, app, desktop, sdk, or plugin.
Examples: fix(tui): simplify thinking toggle styling, docs: update contributing guide, chore(sdk): regenerate types.
Style Guide
General Principles
- Keep things in one function unless composable or reusable
- Do not extract single-use helpers preemptively. Inline the logic at the call site unless the helper is reused, hides a genuinely complex boundary, or has a clear independent name that improves the caller.
- Avoid
try/catchwhere possible - Avoid using the
anytype - Use Bun APIs when possible, like
Bun.file() - Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity
- Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream
- In
src/config, follow the existing self-export pattern at the top of the file (for exampleexport * as ConfigAgent from "./agent") when adding a new config module. - In Effect generators, bind services to named variables before calling methods. Do not use nested service yields such as
yield* (yield* Foo.Service).bar().
Reduce total variable count by inlining when a value is only used once.
// Good
const journal = await Bun.file(path.join(dir, "journal.json")).json()
// Bad
const journalPath = path.join(dir, "journal.json")
const journal = await Bun.file(journalPath).json()Destructuring
Avoid unnecessary destructuring. Use dot notation to preserve context.
// Good
obj.a
obj.b
// Bad
const { a, b } = objImports
- Never alias imports. Do not use
import { foo as bar } from "..."or renamed imports likeresolve as pathResolve. - Never use star imports. Do not use
import * as Foo from "..."orimport type * as Foo from "...". - If a namespace-style value is needed, import the module's own exported namespace by name, for example
import { Project } from "@pentestcode/core/project", then referenceProject.ID. - Prefer dynamic imports for heavy modules that are only needed in selected code paths, especially in startup-sensitive entrypoints. Destructure dynamic import bindings near the top of the narrowest scope that needs them so they read like normal imports. Avoid inline chains such as
await import("./module").then((mod) => mod.value())or(await import("./module")).value(). Keep branch-specific imports inside the branch that needs them to preserve lazy loading.
Variables
Prefer const over let. Use ternaries or early returns instead of reassignment.
// Good
const foo = condition ? 1 : 2
// Bad
let foo
if (condition) foo = 1
else foo = 2Control Flow
Avoid else statements. Prefer early returns.
// Good
function foo() {
if (condition) return 1
return 2
}
// Bad
function foo() {
if (condition) return 1
else return 2
}Complex Logic
When a function has several validation branches or supporting details, make the main function read as the happy path and move supporting details into small helpers below it.
// Good
export function loadThing(input: unknown) {
const config = requireConfig(input)
const metadata = readMetadata(input)
return createThing({ config, metadata })
}
function requireConfig(input: unknown) {
...
}- Keep helpers close to the code they support, below the main export when that improves readability.
- Do not over-abstract simple expressions into many single-use helpers; extract only when it names a real concept like
requireConfigorreadMetadata. - Do not return
Effectfrom helpers unless they actually perform effectful work. Synchronous parsing, validation, and option building should stay synchronous. - Prefer Effect schema helpers such as
Schema.UnknownFromJsonStringandSchema.decodeUnknownOptionover manualJSON.parsewrapped inEffect.trywhen parsing untrusted JSON strings. - Add comments for non-obvious constraints and surprising behavior, not for obvious assignments or control flow.
Schema Definitions (Drizzle)
Use snake_case for field names so column names don't need to be redefined as strings.
// Good
const table = sqliteTable("session", {
id: text().primaryKey(),
project_id: text().notNull(),
created_at: integer().notNull(),
})
// Bad
const table = sqliteTable("session", {
id: text("id").primaryKey(),
projectID: text("project_id").notNull(),
createdAt: integer("created_at").notNull(),
})Testing
- Avoid mocks as much as possible, you shouldn't be using globalThis.* at all unless it's the only option.
- Test actual implementation, do not duplicate logic into tests
- Tests cannot run from repo root (guard:
do-not-run-tests-from-root); run from package dirs likepackages/opencode.
Type Checking
- Always run
bun typecheckfrom package directories (e.g.,packages/opencode), nevertscdirectly.
V2 Session Core
- Keep durable prompt admission separate from model execution.
SessionV2.prompt(...)admits one durablesession_inputrow before scheduling advisorySessionExecution.wake(sessionID)unlessresume: falserequests admit-only behavior. The serialized runner promotes admitted inputs into visible user messages at safe boundaries. - Reusing a Session ID adopts the existing Session. Reusing a prompt message ID reconciles an exact retry only when Session, prompt, and delivery mode match; conflicting reuse fails. Historical projected prompts lazily synthesize promoted inbox records during exact retry.
- Keep
SessionExecutionprocess-global and Session-ID based. Its local implementation owns the process-local Session coordinator and discovers placement throughSessionStoreplusLocationServiceMap.get(session.location)only when a drain starts; no layer should take a Session ID. V2 interruption targets the active process-local ownership chain for that Session; idle or missing interruption is a no-op. - Keep
SessionRunner, model resolution, tool registry, permissions, and filesystem Location-scoped. OmittedLocation.workspaceIDmeans implicit-local placement; explicit workspace identity remains reserved for future placement semantics. - Preserve one explicit
llm.stream(request)call per provider turn and reload projected history before durable continuation. Do not bridge through legacySessionPrompt.loop(...)or delegate orchestration to an in-memory tool loop. - Keep local Session drains process-local until clustering is implemented.
SessionRunCoordinatorjoins explicit same-Session resumes, coalesces prompt wakeups, and allows different Sessions to run concurrently. Advisory wakes drain eligible durable inbox rows only; post-crash continuation recovery requires a separate explicit design before it may retry provider work. A drain has no durable identity or transcript boundary. - Keep delivery vocabulary explicit. Prompts steer by default and promote at the next safe provider-turn boundary while the current drain requires continuation. An explicit
queueinput remains pending until the Session would otherwise become idle; promote one queued input at that boundary, then reevaluate continuation before promoting another. Promoting any new user input resets the selected agent's provider-turn allowance; a batch of steers resets it once. - Keep EventV2 replay owner claims separate from clustered Session execution ownership.
- Keep the System Context algebra, registry, and built-ins in
src/system-context; keep Context Source producers with their observed domains, and keep Session History selection plus Context Epoch persistence Session-owned.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository31 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- enumeration-phaseSkill
- exploitation-phaseSkill
- post-exploit-phaseSkill
- recon-phaseSkill
- reporting-phaseSkill
- vuln-assess-phaseSkill
- playbook-adSkill
- playbook-apiSkill
- playbook-cloudSkill
- playbook-methodologySkill
- playbook-social-engineeringSkill
- playbook-webappSkill
- svc-cicdSkill
- svc-databaseSkill
- svc-docker-k8sSkill
- svc-ftpSkill
- svc-mobile-androidSkill
- svc-mobile-iosSkill
- svc-pivotingSkill
- svc-smbSkill
- svc-sshSkill
- svc-web-serverSkill
- web-auth-bypass-idorSkill
- web-deserializationSkill
- web-lfi-traversalSkill
- web-sqliSkill
- web-ssrfSkill
- web-sstiSkill
- web-upload-rceSkill
- web-xxeSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

