Imported from ktchung/steamdb-exact-price-calc (
AGENTS.md). Install upstream withnpx skills add ktchung/steamdb-exact-price-calc. Copyright stays with the author.
AGENTS.md
Repository guidance for coding agents working in this project.
Project Snapshot
- Repo purpose: Chrome extension for SteamDB sales scraping and exact-price combinations.
- Product spec source:
PRD.md(current source of truth). - Toolchain: Vite+ is configured (
vite-plusindevDependencies). - Existing key files:
PRD.md,manifest.json,README.md,AGENTS.md,vite.config.ts. - Runtime implementation status: TypeScript runtime scaffold is present (
index.html,popup.ts,background.ts,content.ts).
External Agent Rules Discovery
- Checked
.cursorrules: not present. - Checked
.cursor/rules/: not present. - Checked
.github/copilot-instructions.md: not present. - Therefore: no repository-local Cursor/Copilot rule files to merge.
Build / Lint / Test Commands
Use Vite+ commands (vp ...) as the default workflow. Do not call npm, pnpm, or yarn directly for normal development tasks.
Current Commands (preferred)
- Install dependencies:
vp install - Development server:
vp dev - Full checks (format + lint + type checks):
vp check - Lint only:
vp lint - Format only:
vp fmt - Run tests:
vp test - Build production output:
vp build - Chromium extension dev loop:
vp run dev:chromium - Chromium dev profile clean only:
vp run clean:chromium - Clean profile then launch Chromium:
vp run dev:chromium:clean
Running a Single Test
Single test execution depends on test file patterns and argument passthrough.
- Single test file:
vp test -- path/to/file.test.js - Single test by name:
vp test -- -t "test name"
If your local vp test does not pass args through, use:
vp exec vitest run path/to/file.test.jsvp exec vitest run -t "test name"
Notes About Scripts
package.jsoncurrently includes:prepare: vp configclean:chromium(removes.chromium-dev-profile)dev:chromium(runsvp build --watch+ launches Chromium with unpacked extension)dev:chromium:clean(runsclean:chromiumthendev:chromium)test:e2e(runs headless Playwright checks againstvp preview)test:e2e:headed(runs Playwright checks in headed mode)
- If custom scripts are added later, run them with
vp run <script-name>.
Extension Manual Verification (expected)
- Open Chrome:
chrome://extensions - Enable Developer Mode.
- Load unpacked extension root directory.
- Verify popup starts on SteamDB sales pages.
- Verify crawl progress and stop behavior.
- Verify exact-sum combination output.
Architecture and File Layout Conventions
When creating the first implementation, use this structure unless a maintainer says otherwise.
manifest.json(Manifest V3)background.js(service worker orchestration)content.js(DOM parsing, pagination traversal)popup.htmlpopup.csspopup.jslib/for shared pure utilities (price parse, combinatorics, messaging constants)tests/for unit tests when test runner is added
Keep logic split by responsibility:
- Content script: page reads/writes and navigation only.
- Background: run state, workflow, policy decisions.
- Popup: UI state rendering and user interactions.
- Shared modules: pure, deterministic, unit-testable logic.
Coding Style Guidelines
TypeScript Baseline
- Use modern ES syntax supported by Chrome Extensions MV3.
- Use explicit types for exported APIs and message payloads.
- Prefer
const, thenlet; avoidvar. - Use semicolons consistently.
- Use single quotes for strings unless escaping is reduced with double quotes.
- Prefer strict equality (
===,!==). - Keep functions small and focused.
- Avoid deep nesting; return early on invalid states.
Imports and Module Boundaries
- If using modules, use relative imports with explicit file extensions where required.
- For toolchain config/tests, import from
vite-pluswrappers rather thanvite/vitest. - Group imports in this order: browser/chrome APIs, third-party (if introduced), local modules.
- No circular dependencies.
- Keep side effects out of shared utility modules.
Naming Conventions
- Files: kebab-case for multiword files (for example
price-parser.js). - Variables/functions: camelCase.
- Constants: UPPER_SNAKE_CASE.
- Classes (if used): PascalCase.
- Boolean flags: prefix with
is,has,can, orshould. - Message/event types: SCREAMING_SNAKE_CASE string constants.
Types and Data Contracts
- This project uses TypeScript; keep strict type safety for exported functions.
- Document all message payload shapes between popup/background/content.
- Use explicit object schemas for:
- sale item records
- scan state
- search config
- search results and pagination metadata
- Validate external data (DOM text, URLs, prices) before use.
Formatting
- Indentation: 2 spaces.
- Max line length target: 100 chars.
- Trailing commas in multiline objects/arrays.
- One statement per line.
- Keep CSS class names readable and consistent (BEM-like is acceptable).
Error Handling and Resilience
- Never swallow errors silently.
- Throw or return structured errors with actionable messages.
- Include context in logs (page index, selector used, operation step).
- Handle these expected failures gracefully:
- unsupported URL/path
- selector mismatch due to site changes
- navigation timeout
- parse failures for localized price text
- user-stop or user-decline decisions
- Use user-friendly popup messages; avoid raw stack traces in UI.
Async and Performance
- Use
async/awaitover promise chains for readability. - Guard long-running loops with cancellation checks.
- Use integer minor units (cents) for all price math.
- Respect PRD crawl pacing: include ~500ms delay before page switches (tunable).
- For long searches, prompt user every 3000ms to continue or stop.
Security and Privacy
- Restrict permissions to minimum required by features.
- Scope host permissions to
https://steamdb.info/*. - Do not collect credentials or personal data.
- Do not add analytics/telemetry without explicit product decision.
Testing Guidance
- Prioritize unit tests for pure logic first:
- price parsing to cents
- exact-sum combination algorithm
- deduplication behavior
- pagination/result slicing
- Add integration-style tests for message contract boundaries when possible.
- Use
vp testas the default test command. - Optional E2E: add Playwright for extension smoke tests, but keep unit tests as the primary gate.
- Prefer headless E2E runs by default (
vp run test:e2e); use headed mode only when interactive debugging is needed. - Manual QA is required for DOM selector stability on live SteamDB pages.
PRD Alignment Requirements
Implementation must follow PRD.md unless the PRD is updated.
- One item can only appear once in a combination.
- Exclude free items (0 price).
- Operate on
/salespath including query/filter variants. - Ask user confirmation before crawling beyond 10 pages.
- Default max combination size is 5, configurable.
- Show all exact combinations with paginated results (default 5/page, configurable).
- No hard compute timeout; continue/stop prompts at 3000ms intervals.
- Nearest-under/over suggestions are v1.1, not v1.
Agent Workflow Expectations
- Read
PRD.mdbefore any substantial code changes. - Prefer small, focused patches.
- Update docs when behavior or contracts change.
- Run
vp checkandvp testbefore handoff when feasible. - If scripts are added, update this file with exact
vpcommands. - If Cursor/Copilot rule files are later added, merge their guidance here.
Using Vite+, the Unified Toolchain for the Web
This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called vp. Vite+ is distinct from Vite, but it invokes Vite through vp dev and vp build.
Vite+ Workflow
vp is a global binary that handles the full development lifecycle. Run vp help to print a list of commands and vp <command> --help for information about a specific command.
Start
- create - Create a new project from a template
- migrate - Migrate an existing project to Vite+
- config - Configure hooks and agent integration
- staged - Run linters on staged files
- install (
i) - Install dependencies - env - Manage Node.js versions
Develop
- dev - Run the development server
- check - Run format, lint, and TypeScript type checks
- lint - Lint code
- fmt - Format code
- test - Run tests
Execute
- run - Run monorepo tasks
- exec - Execute a command from local
node_modules/.bin - dlx - Execute a package binary without installing it as a dependency
- cache - Manage the task cache
Build
- build - Build for production
- pack - Build libraries
- preview - Preview production build
Manage Dependencies
Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the packageManager field in package.json or package manager-specific lockfiles.
- add - Add packages to dependencies
- remove (
rm,un,uninstall) - Remove packages from dependencies - update (
up) - Update packages to latest versions - dedupe - Deduplicate dependencies
- outdated - Check for outdated packages
- list (
ls) - List installed packages - why (
explain) - Show why a package is installed - info (
view,show) - View package information from the registry - link (
ln) / unlink - Manage local package links - pm - Forward a command to the package manager
Maintain
- upgrade - Update
vpitself to the latest version
These commands map to their corresponding tools. For example, vp dev --port 3000 runs Vite's dev server and works the same as Vite. vp test runs JavaScript tests through the bundled Vitest. The version of all tools can be checked using vp --version. This is useful when researching documentation, features, and bugs.
Common Pitfalls
- Using the package manager directly: Do not use pnpm, npm, or Yarn directly. Vite+ can handle all package manager operations.
- Always use Vite commands to run tools: Don't attempt to run
vp vitestorvp oxlint. They do not exist. Usevp testandvp lintinstead. - Running scripts: Vite+ commands take precedence over
package.jsonscripts. If there is atestscript defined inscriptsthat conflicts with the built-invp testcommand, run it usingvp run test. - Do not install Vitest, Oxlint, Oxfmt, or tsdown directly: Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands.
- Use Vite+ wrappers for one-off binaries: Use
vp dlxinstead of package-manager-specificdlx/npxcommands. - Import JavaScript modules from
vite-plus: Instead of importing fromviteorvitest, all modules should be imported from the project'svite-plusdependency. For example,import { defineConfig } from 'vite-plus';orimport { expect, test, vi } from 'vite-plus/test';. You must not installvitestto import test utilities. - Type-Aware Linting: There is no need to install
oxlint-tsgolint,vp lint --type-awareworks out of the box.
Review Checklist for Agents
- Run
vp installafter pulling remote changes and before getting started. - Run
vp checkandvp testto validate changes.