Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Working with Claude, London: Claude Code hands-on

The afternoon session, "Claude Code, zero to expert", is three hours in six parts. Parts 3, 4 and 5 are hands on keyboard, and all three run in this repository. Everything you need is here: the set-up, the three exercises, the sample app, the tickets and the reference files.

Start here

  1. Set-up (before Part 3, five minutes): workshop/SETUP.md. Four paths: local install, GitHub Codespaces (nothing to install), Claude Code on the web, or pair up. Ends with the three "are you green" checks.
  2. Pre-work (the night before, 15 minutes): docs/PRE-WORK.md. Install, clone, run the tests, and keep the brief and the definition of done handy.

The exercises

Part Lab Minutes Badge Ticket
3 Ship TODO-231: /init, plan and push back, build to green, /code-review, open the PR 30 Shipper docs/tickets/TODO-231.md
4 Fit it to you: /usage, /security-review, a hook, /mcp on the database, the release-check skill 25 Toolmaker
5 Put more agents on it: three subagents, a nightly routine, a remote session, a swap 20 Orchestrator docs/tickets/TODO-232.md, TODO-233.md

Each lab README has the copy-ready prompts, a done-when list, what to show a mentor for the badge, and what to do if you are stuck. Stuck five minutes: hand up.

Reference files

Path Used in
docs/tickets/ The three tickets
.mcp.json Lab 4, the postgres MCP server that reads the local database
docs/data/deliveries-last-30-days.csv Lab 4, the no-MCP fallback for the same question
docs/examples/release-check.SKILL.md Lab 4, the skill template
docs/examples/settings.hooks.json, docs/examples/hooks/pom-guard.sh Lab 4, the pom.xml hook
docs/examples/agents/ Lab 5, the auditor, fixer and verifier subagents
docs/examples/routine.md Lab 5, the nightly release check
.devcontainer/ Codespaces: Java 17, Node 20, Claude Code and PostgreSQL 16, nothing to install
docs/examples/ci.workflow.yml A GitHub Actions workflow that runs both suites on every pull request. Copy it to .github/workflows/ci.yml in your copy to switch CI on

There is deliberately no CLAUDE.md and no .claude/ folder. You create them in Lab 3.

The badge game

One badge per lab. A badge is one thing you show a mentor on your screen; they stamp your card. Three stamps put your card in the draw at show-and-tell, and a full card across the morning and afternoon sessions gets you named at the close.

Mentors

Participants press Use this template on this repository to get their own copy (needed for Codespaces and Claude Code on the web). Do Lab 3 once yourself in a fresh Codespace before the day. The answer key for the database question is in docs/data/ANSWER-KEY.md.


The app: ops-dashboard

The operations dashboard at Marlowe & Finch, a coffee-equipment company. A small Spring Boot REST API over a PostgreSQL database, plus a plain-JavaScript page that lives on a wall screen in the operations office: four KPI tiles, two charts, the late deliveries of the period, and the vendor contracts coming up for renewal.

Two sentences to explain it: the Java side reads orders, deliveries, tickets, carriers and vendors with plain SQL (Spring JDBC, Flyway migrations, no JPA) and serves read-only JSON under /api; the frontend in src/main/resources/static/ calls those endpoints with fetch for a date range and draws the tiles, two inline SVG charts, the table and the list.

The data is fictional and generated by tools/make_seed.py: about 1,900 orders and deliveries over the 90 days before 21 September 2026 across four carriers, 600 support tickets, and eight vendor contracts. One carrier, Kessler Logistics, has been slipping all summer. The dashboard is meant to make that visible.

Run it with PostgreSQL (the default)

docker compose up -d db      # PostgreSQL 16 on localhost:5432, database/user/password "ops"
./mvnw spring-boot:run       # then open http://localhost:8080

Flyway creates the schema and loads the seed on first start (V1__schema.sql, V2__seed.sql). The database keeps its data between runs; docker compose down -v wipes it. Connection details can be overridden with DATABASE_URL, DATABASE_USER and DATABASE_PASSWORD.

Run it without a database (the demo profile)

SPRING_PROFILES_ACTIVE=demo ./mvnw spring-boot:run

Same migrations, same seed, in an in-memory H2 database in PostgreSQL mode. Use this on a laptop without Docker and in Claude Code on the web. The tests always run on it.

Today is 2026-09-21

The app's clock is pinned to 21 September 2026 (property ops.today, bean in ClockConfig.java) so the default date range, the "days until renewal" figures and the tests all agree with the seed data whatever the real date is. Every default range is "the last 30 days ending today".

Test it

./mvnw test                 # Java: 25 tests (JUnit 5, H2, MockMvc)
npm install                 # once
npm test                    # Frontend: 45 tests (Jest + jsdom)

The data connection (Lab 4)

.mcp.json at the root registers a postgres MCP server that Claude Code starts on demand with npx -y @modelcontextprotocol/server-postgres. It is read-only (every query runs in a READ ONLY transaction) and points at the local compose database, postgresql://ops:ops@localhost:5432/ops. In Codespaces the dev container shares the database's network, so the same address works there. /mcp inside claude shows it as postgres. Without Docker, the same question can be answered from docs/data/deliveries-last-30-days.csv.

Stack

  • Java 17, Spring Boot 3.2, Spring JDBC, Flyway, PostgreSQL driver, H2 for the demo profile and tests; Maven (wrapper included, no local Maven needed)
  • Vanilla JavaScript, HTML and CSS; no build step, no framework; charts are inline SVG
  • Jest with jsdom for the frontend tests; the harness lives in src/test/javascript/setup/loadApp.js

Tree

ops-dashboard/
├── pom.xml                        Java build (dependencies are frozen, see comment at the top)
├── package.json                   Jest config and scripts
├── docker-compose.yml             The PostgreSQL 16 service
├── .mcp.json                      The postgres MCP server for Lab 4
├── mvnw, mvnw.cmd, .mvn/          Maven wrapper
├── tools/make_seed.py             Generates V2__seed.sql, the CSV and the answer key
├── src/main/java/com/marlowefinch/ops/
│   ├── OpsApplication.java        Spring Boot entry point
│   ├── ClockConfig.java           "Today" pinned to 2026-09-21
│   ├── DateRange.java             from/to defaults (no validation yet, see TODO-232)
│   ├── DashboardRepository.java   KPIs, on-time rate, late deliveries, tickets (SQL)
│   ├── VendorRepository.java      Vendors with days until contract end
│   ├── KpiController.java         /api/kpis
│   ├── DeliveryController.java    /api/deliveries/on-time, /api/deliveries/late
│   ├── TicketController.java      /api/tickets/by-category
│   ├── VendorController.java      /api/vendors
│   ├── HealthController.java      /api/health
│   └── Kpis, CarrierOnTime, LateDelivery, TicketCategoryCount, Vendor   Response records
├── src/main/resources/
│   ├── application*.properties    postgres (default) and demo profiles
│   ├── db/migration/              V1__schema.sql, V2__seed.sql (Flyway)
│   └── static/                    index.html, app.js, style.css
├── src/test/java/...              JUnit tests (migrations, repositories, controllers)
├── src/test/javascript/           Jest tests and the harness
├── docs/                          Workshop material, tickets, data, examples
├── workshop/                      Set-up and the three labs
├── .devcontainer/                 GitHub Codespaces setup with PostgreSQL (no local install needed)
└── docs/examples/ci.workflow.yml  CI workflow to copy into .github/workflows/

API

All endpoints are GET, return JSON and are read-only. from and to are ISO dates (2026-09-14) and default to the last 30 days ending today. limit defaults to 20.

Path Returns
/api/health {"status":"UP","today":"2026-09-21"}
/api/kpis?from&to On-time delivery rate, open tickets, revenue and order count for the range
/api/deliveries/on-time?from&to Delivered, on-time and rate per carrier (deliveries that arrived in the range)
/api/deliveries/late?from&to&limit Late deliveries, worst first: order, carrier, promised and delivered dates, days late
/api/tickets/by-category?from&to Tickets opened in the range per category: still open, and total
/api/vendors Every vendor with annual spend, contract end, notice days, owner, days until contract end and whether that is inside the notice window

There is no validation of from, to or limit: a malformed date is a 500, from after to is an empty result, and limit can be anything. That is ticket TODO-232.

Workshop material is in workshop/ and docs/.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages