✦ Built with Claude Code

Planning an eBay Watch Tracker in One Session

A walkthrough of how I used Claude Code's GSD workflow to go from a rough idea to a fully-planned, research-backed project — requirements, roadmap, and executable plans — in a single conversation.

📅 March 22, 2026 ⏱ ~30 min session 🗂 21 requirements 🗺 4 phases 📋 3 executable plans

What We Built (in planning)

A personal web app that searches eBay for watch listings — capturing both active listings (asking prices) and completed/sold listings (actual sale prices) — and stores comprehensive details to help track market value and time purchases.

Core Value

"Know what a watch actually sells for (not just what people ask) so you can time purchases well and understand what your collection is worth."

Key Features

🔍 Search & Ingest — eBay search returning both active and sold/completed listings with full details: title, price, condition, images, seller, URLs

📁 Saved Searches — Named, persistent searches tagged as "Wishlist" or "Research" — unified concept with target price threshold and notes

📈 Price History — Timestamped snapshots on every background refresh, displayed as Chart.js line charts with avg/median sold price

💼 Portfolio — Track owned watches with purchase price linked to live market data for real P&L tracking

🔔 Alerts — In-app price drop indicator when a saved search's average sold price drops below a configurable threshold

⏰ Auto-Refresh — Background APScheduler job refreshes all saved searches daily; macOS launchd ensures it survives reboots

Tech Stack

Chosen through parallel research agents investigating stack, features, architecture, and pitfalls:

Python 3.11+ FastAPI 0.135 SQLite + SQLModel Alembic migrations APScheduler 3.x HTTPX BeautifulSoup4 Vanilla JS Chart.js launchd (macOS)
⚠ Critical Research Finding
The eBay Finding API (findCompletedItems) was decommissioned February 5, 2025. Sold/completed listing data now requires HTML scraping via ?LH_Sold=1&LH_Complete=1. The research agents caught this before any code was written — saving a full rework of the data layer.

How Claude Code Was Used

This project used the GSD (Get Shit Done) workflow — a set of Claude Code skills that structure software projects from idea to executable plans. Here's the sequence:

1

Deep Questioning (/gsd:new-project)

Claude asked targeted follow-up questions to extract what mattered: sold vs. active prices, wishlist vs. portfolio distinction, alert delivery, data refresh model. Not a form — a conversation.

2

Parallel Research (4 agents)

Four specialist agents ran simultaneously — Stack, Features, Architecture, and Pitfalls — each writing a research document. A fifth synthesized them into a SUMMARY.md.

3

Requirements Definition

Research findings drove a structured requirements session. 21 requirements scoped with REQ-IDs, organized by category, with explicit v2 and out-of-scope sections.

4

Roadmap Creation (gsd-roadmapper agent)

A specialized agent decomposed requirements into 4 phases with observable success criteria — each requirement mapped to exactly one phase, 100% coverage verified.

5

Phase Research + Planning + Verification (/gsd:plan-phase 1)

Phase-specific researcher confirmed eBay API status live. Planner created 3 executable PLAN.md files. Plan checker verified all requirements covered, dependencies correct, tests mapped.

★ Why This Approach Works

The key insight is separating "what to build" from "how to build it". The new-project flow forces you to answer the hardest questions (scope, constraints, core value) before any code is written. By the time you get to execution, there's nothing left to guess — each plan is a specific, verifiable, ordered set of tasks with known dependencies.


How the Conversation Went

The initial prompt was intentionally vague. Claude used the GSD questioning workflow to extract what was actually needed. Here's the key exchange:

User Opening message
I want to build an app that checks ebay for prices/listings on watches and stores them along side actual sales prices - Id like to capture details including text, pricing, images etc
Claude Follow-up question (interactive UI)
When you say "actual sales prices" — what's the distinction you're drawing there? Is the idea that eBay shows both active listings (asking prices) AND completed/sold listings, and you want to track both?
User
yes

From there, Claude asked 6 structured questions (using an interactive UI) to extract:

Purpose
Both buying research + portfolio tracking

Interaction model
Search-driven (not a fixed watchlist)

Interface
Web app in browser

Alerts
In-app price drop alerts only

Portfolio type
Owned watches + wishlist (both)

Data refresh
Scheduled auto-refresh

The entire requirements and roadmap session then ran without further input. Claude handled all the scoping, research, and planning autonomously — only surfacing decisions that required human judgment.

GSD Skill How to invoke this workflow
# In a new empty project directory: # 1. Start Claude Code claude # 2. Just describe your idea — Claude detects the empty directory # and auto-invokes /gsd:new-project "I want to build an app that..." # OR — invoke explicitly /gsd:new-project # 3. After project init, plan each phase: /gsd:plan-phase 1 # 4. Execute: /gsd:execute-phase 1
★ Prompt Design Insight

The opening prompt was deliberately vague — "I want to build an app..." You don't need a detailed spec to start. The GSD workflow is designed to extract the spec through conversation. The more specific your opening prompt, the less value the questioning phase adds. Start with the idea; let Claude ask what matters.


What Was Produced

Every artifact was committed to git automatically after it was created.

📋 Requirements (21 total)

ID Requirement Phase
INGEST-01User can search eBay by keyword and view active listings1
INGEST-02User can view completed/sold listings separately from active1
INGEST-03Each listing stores title, price, condition, images, seller, URL, date1
INGEST-04Box & papers auto-detected from listing title keywords1
SCHED-01System auto-refreshes all saved searches on a background schedule2
SCHED-02UI shows "last refreshed" timestamp per saved search2
SCHED-03Scheduler persists on macOS via launchd2
SRCH-01User can save a named search query3
SRCH-02User can tag searches as "Wishlist" or "Research"3
SRCH-03User can set a target price threshold on a saved search3
SRCH-04User can add notes to a saved search3
SRCH-05User can view current eBay listings per saved search3
PORT-01User can add owned watch with purchase price + notes3
PORT-02User can link owned watch to saved search for market value3
PORT-03Portfolio shows purchase price, market value, P&L3
HIST-01System stores timestamped price snapshots per refresh4
HIST-02User can view price history chart for any saved search4
HIST-03Average / median sold price displayed per saved search4
ALRT-01User can enable price drop alerts on a saved search4
ALRT-02System detects drops vs. previous price snapshot4
ALRT-03In-app alert indicator appears after a drop is detected4

🗺 Roadmap — 4 Phases

1

Foundation

eBay API client (Browse API active + HTML scraper for sold) + SQLite schema with sold/active price separation baked in from day one

INGEST-01 · INGEST-02 · INGEST-03 · INGEST-04
PLANNED ✓
2

Core Loop

APScheduler in FastAPI lifespan, ingest pipeline, launchd macOS persistence, basic web UI proving end-to-end data flow

SCHED-01 · SCHED-02 · SCHED-03
Next
3

Saved Searches & Portfolio

Named persistent searches with wishlist tagging, portfolio with purchase price vs. current market value P&L

SRCH-01–05 · PORT-01–03
Later
4

Analytics & Alerts

Chart.js price history charts, avg/median sold price, configurable price drop alerts with in-app notification indicator

HIST-01–03 · ALRT-01–03
Later

📄 Phase 1 Plans (3 executable)

01-01 · Wave 1 — eBay API Verification Spike

Investigation task, not a coding task. Output is a SPIKE.md document confirming live CSS selectors for eBay's sold-listings HTML, OAuth token lifetime, and API quotas. Plans 01-02 and 01-03 depend on this output.

Produces: 01-01-SPIKE.md

01-02 · Wave 2 — DB Schema + Project Scaffold

pyproject.toml, SQLModel models (Listing with separate listing_type field), Alembic migrations, Wave 0 pytest stubs. Requires spike output to finalize nullable fields for scraped sold-listing data.

Key: render_as_batch=True required for SQLite+Alembic ALTER TABLE

01-03 · Wave 3 — eBay API Client

OAuth token manager with proactive 5-min-before-expiry refresh, Browse API client for active listings, HTML scraper for sold listings using spike-confirmed selectors, normalization layer, manual search CLI script for testing.

Requires: 01-01-SPIKE.md selectors + 01-02 models

What This Shows About Claude Code

1 · Spikes as First-Class Plans

Plan 01-01 is an investigation, not an implementation. It produces a document, not code. This is the spike pattern — a time-boxed task to resolve a critical unknown before committing to architecture. Claude structured this explicitly because the research flagged eBay's Finding API deprecation as unverified. The plan checker validated this wave ordering was correct.

2 · Research Agents Caught a Real Architecture Mistake

The initial STACK.md recommended the eBay Finding API. The phase-specific researcher went further — fetching live eBay developer docs — and discovered it was decommissioned 5 weeks ago. Without this research step, the first implementation attempt would have failed and required a full data-layer rework.

3 · The Wishlist Insight

Research surfaced something the user hadn't explicitly said: a "wishlist item" is just a saved search with extra context. Instead of building two separate data models, Claude proposed a unified model and confirmed it with the user. This kind of scope consolidation reduces code complexity without losing functionality.

4 · Schema Decisions Are Architecture

The requirement to separate sold prices from active asking prices was treated as a schema-level constraint, not a display concern. The plan checker explicitly verified that listing_type was structurally separate in the Listing model — not a single price field that gets filtered in a WHERE clause. Getting this wrong early would have required a data migration later.

5 · CLAUDE.md Auto-Triggers Workflows

The global CLAUDE.md included this instruction: "When starting Claude in an empty or nearly empty folder (no existing source code), automatically invoke /gsd:new-project." Claude detected the empty directory and triggered the full planning workflow without being asked. You can encode your own team conventions and defaults into CLAUDE.md.