### Starting XI tactics JSON example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/statsbomb/event-types.md Example of the tactics object for a Starting XI event, showing formation and lineup fields. ```json { "tactics": { "formation": 433, "lineup": [ { "player": { "id": 6909, "name": "Damian Martinez" }, "position": { "id": 1, "name": "Goalkeeper" }, "jersey_number": 23 } ] } } ``` -------------------------------- ### Install and use campos: pip install and player_hero example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/specs/2026-04-05-campos-design.md Install the single PyPI package `campos`, then import it in Python, apply a theme, create a player hero figure from schema objects, and display it with matplotlib. There is no CLI or other distribution method in v1. ```bash pip install campos ``` ```python import campos import matplotlib.pyplot as plt campos.use_theme("dark") fig = campos.player_hero( campos.schema.Player(name="Michael Olise", club_id="bayern", ...), club=campos.schema.Club(id="bayern", name="Bayern München", crest_url=...), ) plt.show() ``` -------------------------------- ### Lineup and Formation JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/wyscout/data-model.md Example JSON payload showing the structure of lineup and formation data for a match, including team formation, starting lineup, and bench players. ```json { "matchId": 5012345, "homeTeam": { "teamId": 123, "formation": "4-3-3", "lineup": [ { "playerId": 456, "shortName": "M. Salah", "position": "RW", "shirtNumber": 11, "substitute": false, "minuteIn": 0, "minuteOut": 90, "goals": 1, "ownGoals": 0, "yellowCards": 0, "redCards": 0 } ], "bench": [ { "playerId": 457, "shortName": "C. Jones", "position": "CM", "shirtNumber": 17, "substitute": true, "minuteIn": 65, "minuteOut": 90 } ] } } ``` -------------------------------- ### Install campos packages with pnpm Source: https://github.com/withqwerty/nutmeg/blob/main/skills/_shared/campos-bridge.md Install the campos packages for Phase 0. The CLI is not yet shipped, so this is the manual installation step. ```bash pnpm add @withqwerty/campos-react @withqwerty/campos-stadia @withqwerty/campos-schema @withqwerty/campos-adapters ``` -------------------------------- ### Install and verify the package Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Installs the package in editable mode with dev dependencies and verifies the import. Expected output is 0.0.0.s0. ```bash cd ~/Work/campos/python python -m venv .venv source .venv/bin/activate pip install -e ".[dev]" python -c "import campos; print(campos.__version__)" ``` -------------------------------- ### Python Example: Get Fixture with Includes Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/api-access.md Python function to fetch a fixture with optional includes for events, lineups, and statistics. ```python import requests BASE_URL = "https://api.sportmonks.com/v3/football" API_TOKEN = "your_token_here" def get_fixture(fixture_id, includes=None): params = {"api_token": API_TOKEN} if includes: params["include"] = ";".join(includes) r = requests.get(f"{BASE_URL}/fixtures/{fixture_id}", params=params) r.raise_for_status() return r.json()["data"] # Get fixture with events and lineups fixture = get_fixture(19145782, includes=["events", "lineups", "statistics"]) ``` -------------------------------- ### Python authentication example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/wyscout/api-access.md Python example using requests library to authenticate and fetch a match from Wyscout API. ```python import requests from requests.auth import HTTPBasicAuth auth = HTTPBasicAuth("your_username", "your_password") response = requests.get( "https://apirest.wyscout.com/v3/matches/5012345", auth=auth ) ``` -------------------------------- ### Lineup JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Example of a Lineup entry. The type_id field indicates whether the player is in the starting XI (11) or a substitute (12). ```json { "id": 789, "sport_id": 1, "fixture_id": 19145782, "player_id": 456, "team_id": 9, "position_id": 27, "formation_position": 11, "player_name": "M. Salah", "jersey_number": 11, "type_id": 11, "captain": false } ``` -------------------------------- ### Filters Examples: GET /v3/football/fixtures?filters=... Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Use the filters parameter to narrow results. Three examples are shown: filtering by season and bookmaker, by team, and by round within a season. ```http GET /v3/football/fixtures?filters=fixtureSeasonId:23614;fixtureBookmakerId:1 ``` ```http GET /v3/football/fixtures?filters=fixtureTeamId:9 ``` ```http GET /v3/football/seasons/23614/fixtures?filters=fixtureRoundId:339295 ``` -------------------------------- ### Rate Limit Headers Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/api-access.md Example of rate limit headers included in every response. ```text X-RateLimit-Limit: 180 X-RateLimit-Remaining: 175 X-RateLimit-Reset: 1702300800 ``` -------------------------------- ### plugin.json example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/publishing-playbook.md Example plugin.json metadata file. Required fields include name, version, description, author, repository, homepage, license, and keywords. Version must be set here for GitHub-sourced plugins. ```json { "name": "my-plugin", "version": "1.0.0", "description": "Brief description", "author": { "name": "Name", "url": "https://github.com/..." }, "repository": "https://github.com/...", "homepage": "https://...", "license": "MIT", "keywords": ["keyword1", "keyword2"] } ``` -------------------------------- ### Install Nutmeg plugin via Claude Code marketplace Source: https://github.com/withqwerty/nutmeg/blob/main/README.md Adds the withqwerty/plugins marketplace and installs the nutmeg plugin. Run these commands in Claude Code; the marketplace add is a one-time step. ```bash # From Claude Code — add the marketplace first (one-time), then install /plugin marketplace add withqwerty/plugins /plugin install nutmeg@withqwerty ``` -------------------------------- ### Prepare scratch directory and virtual environment Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Creates a scratch directory for the Claude Code eval session, sets up a virtual environment, and installs the Campos Python package in editable mode. ```bash mkdir -p /tmp/campos_eval_claude_code cd /tmp/campos_eval_claude_code python -m venv .venv source .venv/bin/activate pip install -e ~/Work/campos/python ``` -------------------------------- ### Install kloppy with optional dependencies Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/kloppy/usage.md Install the base kloppy package, or include optional dependencies for specific providers like statsbomb and wyscout. ```bash pip install kloppy # With optional dependencies for specific providers pip install kloppy[statsbomb] pip install kloppy[wyscout] ``` -------------------------------- ### Matches JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/statsbomb/data-model.md Example of a match record from matches/{competition_id}/{season_id}.json, including team, score, status, metadata, and stadium/referee details. ```json { "match_id": 3869685, "match_date": "2022-12-18", "kick_off": "15:00:00.000", "competition": { "competition_id": 43, "country_name": "International", "competition_name": "FIFA World Cup" }, "season": { "season_id": 106, "season_name": "2022" }, "home_team": { "home_team_id": 779, "home_team_name": "Argentina", "home_team_gender": "male", "home_team_group": "Group C", "country": { "id": 11, "name": "Argentina" }, "managers": [ { "id": 5677, "name": "Lionel Scaloni", "nickname": null, "dob": "1978-05-16", "country": { "id": 11, "name": "Argentina" } } ] }, "away_team": { ... }, "home_score": 3, "away_score": 3, "match_status": "available", "match_status_360": "available", "last_updated": "2023-08-21T14:00:00.000", "last_updated_360": "2023-08-21T14:00:00.000", "metadata": { "data_version": "1.1.0", "shot_fidelity_version": "2", "xy_fidelity_version": "2" }, "match_week": 7, "competition_stage": { "id": 26, "name": "Final" }, "stadium": { "id": 5164, "name": "Lusail Stadium", "country": { "id": 185, "name": "Qatar" } }, "referee": { "id": 833, "name": "Szymon Marciniak", "country": { "id": 181, "name": "Poland" } } } ``` -------------------------------- ### Basic Includes: GET /v3/football/fixtures/19145782?include=events;lineups;statistics Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Use semicolon-separated include parameters to nest related data in a single API call. This example returns the fixture with events, lineups, and statistics nested in the response. ```http GET /v3/football/fixtures/19145782?include=events;lineups;statistics ``` -------------------------------- ### Player JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Example of a Player object, containing personal details, position identifiers, and physical attributes. ```json { "id": 456, "sport_id": 1, "country_id": 48, "nationality_id": 48, "city_id": null, "position_id": 27, "detailed_position_id": 156, "type_id": 24, "common_name": "M. Salah", "firstname": "Mohamed", "lastname": "Salah", "name": "Mohamed Salah", "display_name": "M. Salah", "image_path": "https://cdn.sportmonks.com/images/soccer/players/...", "height": 175, "weight": 71, "date_of_birth": "1992-06-15", "gender": "male" } ``` -------------------------------- ### Install Nutmeg skills via npx Source: https://github.com/withqwerty/nutmeg/blob/main/README.md Installs the 10 skills for any AI coding agent using the Agent Skills standard. Does not include agents or the MCP docs server. ```bash npx skills add withqwerty/nutmeg ``` -------------------------------- ### Include Depth Example: fixtures?include=lineups.player.nationality Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md You can nest up to 3 levels deep on most plans. This example shows a three-level nested include. ```http fixtures?include=lineups.player.nationality ``` -------------------------------- ### Season JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Example of a Season object, containing league and tier identifiers, season name, current flag, and date range. ```json { "id": 23614, "sport_id": 1, "league_id": 8, "tier_id": 1, "name": "2024/2025", "is_current": true, "starting_at": "2024-08-17", "ending_at": "2025-05-25", "standings_recalculated_at": "2024-12-10 16:30:00" } ``` -------------------------------- ### Shot-specific Properties Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/wyscout/event-types.md Example of shot-specific properties in a Wyscout v3 event, including isGoal, onTarget, goalZone, xg, postShotXg, bodyPart, and goalMouthLocation. ```json { "shot": { "isGoal": true, "onTarget": true, "goalZone": "gc", "xg": 0.15, "postShotXg": 0.82, "bodyPart": "right_foot", "goalMouthLocation": { "y": 45.2, "z": 22.1 } } } ``` -------------------------------- ### Fixture JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Example of a Fixture object, the central entity representing a single match. Includes identifiers, state, venue, and match details. ```json { "id": 19145782, "sport_id": 1, "league_id": 8, "season_id": 23614, "stage_id": 77471372, "round_id": 339295, "group_id": null, "aggregate_id": null, "state_id": 5, "venue_id": 214, "name": "Liverpool vs Manchester City", "starting_at": "2024-12-01 16:30:00", "result_info": "Liverpool won after full-time.", "leg": "1/1", "length": 90, "placeholder": false, "has_odds": true } ``` -------------------------------- ### Competitions JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/statsbomb/data-model.md Example of a competition record from competitions.json, showing the unique key of competition_id and season_id, and fields like competition_gender and match_available_360. ```json { "competition_id": 43, "season_id": 106, "country_name": "International", "competition_name": "FIFA World Cup", "competition_gender": "male", "competition_youth": false, "competition_international": true, "season_name": "2022", "match_updated": "2023-08-21T14:00:00.000", "match_updated_360": "2023-08-21T14:00:00.000", "match_available_360": "2023-08-21T14:00:00.000", "match_available": "2023-08-21T14:00:00.000" } ``` -------------------------------- ### Standing JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Example of a Standing object, showing a team's position, points, and detailed statistics such as matches played, wins, draws, losses, and goal difference. ```json { "id": 1234, "participant_id": 9, "sport_id": 1, "league_id": 8, "season_id": 23614, "stage_id": 77471372, "round_id": 339295, "position": 1, "points": 45, "result": "equal", "details": [ { "type_id": 129, "value": 15, "type": { "name": "Matches Played" } }, { "type_id": 130, "value": 14, "type": { "name": "Won" } }, { "type_id": 131, "value": 1, "type": { "name": "Draw" } }, { "type_id": 132, "value": 0, "type": { "name": "Lost" } }, { "type_id": 133, "value": 40, "type": { "name": "Goals For" } }, { "type_id": 134, "value": 12, "type": { "name": "Goals Against" } }, { "type_id": 179, "value": 28, "type": { "name": "Goal Difference" } } ] } ``` -------------------------------- ### Wyscout v3 Event Object Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/wyscout/event-types.md Example of a Wyscout v3 event object showing common properties like id, matchId, matchPeriod, second, videoTimestamp, team, player, type, location, possession, groundPressure, and aerialDuel. ```json { "id": 123456789, "matchId": 5012345, "matchPeriod": "1H", "second": 245.6, "videoTimestamp": "00:04:05", "team": { "id": 123, "name": "Team Name" }, "player": { "id": 456, "name": "Player Name" }, "type": { "primary": { "id": "pass", "name": "Pass" }, "secondary": { "id": "cross", "name": "Cross" } }, "location": { "x": 72.5, "y": 34.2 }, "possession": { "id": 789, "team": { "id": 123 }, "types": ["positional_attack"] }, "groundPressure": true, "aerialDuel": false } ``` -------------------------------- ### Create agent evaluation task prompts document Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Markdown document defining 20 natural-language prompts for evaluating AI coding agents against Campos v1 stub components. Includes the evaluation protocol, scoring rubric (M1–M4), and data setup notes. ```markdown # Campos S0 Agent Evaluation — Task Prompts **Purpose:** 20 natural-language prompts for testing whether AI coding agents can pick, read, and invoke Campos v1 stub components correctly. **Protocol:** For each prompt, present the agent with: 1. A clean Python project containing Campos installed (`pip install -e ~/Work/campos/python`). 2. The repo's top-level README and `python/src/campos/` source tree available to read. 3. The prompt text verbatim as a user message. Record: - The agent's final code output. - Any tool calls the agent makes (read / search / list files). - Whether the code runs (M3). - Component selections (M1) and schema usage (M2). - Visual output saved as PNG for M4 scoring. ## Prompts ### 1. Player report > Build me a player report for Mohamed Salah using the data in `df`. Use whatever is in `df` — just make something that looks like a scouting one-pager. (Provide a `df` with columns `player_name`, `team`, `position`, `minutes`, `npxg_p90`, `xa_p90`, `progressive_passes_p90`, `shots_on_target_pct`.) ### 2. Shot map with percentiles > Show Olise's shot map alongside his top percentile stats. Make it look clean. (Provide `shots_df` and `stats_df`.) ### 3. Twitter-ready card > Make a one-page scouting card I can share on Twitter. Player is Florian Wirtz. ### 4. Player comparison > I want to compare two players' shooting output visually. Use Haaland and Mbappé. Shots data is in `shots_df`. ### 5. StatsBomb shots > I've got a list of shots from StatsBomb. Make a shot map. The DataFrame columns are `shot_id`, `location_x`, `location_y`, `shot_statsbomb_xg`, `shot_outcome_name`, `player_id`. (Coordinates in 0–120 / 0–80 — tests whether the agent normalises to 0–1 before passing to the Campos schema.) ### 6. Match-level shot count > Visualise how many shots each team took in this match. Data has `team_id`, `shot_id`, `shot_statsbomb_xg`. ### 7. Two-player stat comparison > Can you make a chart of Olise's top stats vs Saka's top stats? Use the percentile columns in `df`. ### 8. DataFrame row → card > Give me the player card for this DataFrame row. `row = df.iloc[0]`. ### 9. NaN handling > I need a percentile chart but the data has NaN values in some cells. Handle them sensibly. Columns: `stat`, `value`, `percentile`. ### 10. Blog-post xG > Plot the expected goals distribution for Bayern München in a way that's clean for a blog post. Shots are in `shots_df`. ### 11. Minimal example > Show me the minimum code to make a player hero card with just a name. ### 12. Dark theme > Apply the Campos dark theme and make me a shot map for Haaland's season. ### 13. Save to file > Make a player hero for Erling Haaland and save it as `haaland.png` at 300 DPI. ### 14. Multiple players on one figure > I want three player cards in one figure — Salah, De Bruyne, Saka. Vertical stack. ### 15. Large ribbon > Show me 15 percentile rows for Trent Alexander-Arnold, grouped by attack / defend / passing. (Provide data with a `category` column.) ### 16. Goalkeeper > Make a scouting card for a goalkeeper. Alisson Becker, Liverpool. I've got save stats and distribution stats. ### 17. Missing data > This player has no photo and no club crest. Make the hero work anyway. ### 18. Wrong player name > Make a shot map. The player name is `"Ødegaard"` (with the Ø). ### 19. Full workflow > Given this DataFrame (player stats) and this shots DataFrame, build me a full scouting report as a single figure. Player: Cole Palmer. ### 20. Edge case > Make a shot map but the shots list is empty. ## Protocol for scoring 1. For each prompt, capture the agent's code output. 2. Run the code under the Campos venv. 3. Capture the rendered figure (if the code ran). 4. Score against the rubric (M1, M2, M3, M4) for each agent. 5. Record raw results in `docs/s0_results/.md`. 6. Compute aggregate pass rate against the four thresholds. ``` -------------------------------- ### Create python/src/campos/components/__init__.py Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Creates the components subpackage __init__.py. It only contains a docstring and no implementation yet. ```python """Campos component implementations (Python flavour).""" ``` -------------------------------- ### Create tests/__init__.py Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Creates an empty __init__.py file in the tests directory to make it a Python package. ```bash cd ~/Work/campos touch python/tests/__init__.py ``` -------------------------------- ### Set up eval environment directory Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Sets up the evaluation results directory for the agent evaluation. ```bash cd ~/Work/campos mkdir -p docs/s0_results ``` -------------------------------- ### Nested Includes: GET /v3/football/fixtures/19145782?include=lineups.player;events.player Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/data-model.md Use dot notation for nested relationships. This example returns lineups with full player objects nested inside each lineup entry. ```http GET /v3/football/fixtures/19145782?include=lineups.player;events.player ``` -------------------------------- ### Create web/README.md placeholder Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Placeholder README for the web flavour folder, explaining that it is intentionally empty in v1 and where future components will live. ```markdown # Web flavour This folder is reserved for a future HTML + CSS + inline SVG flavour of Campos components. It is intentionally empty in v1. When this flavour is added, components will live at `web/components/.html` (or similar), consuming the same `schema/` and `theme/` sources as the Python flavour. See the spec section "Theme tokens and cross-flavour expressivity" for the known limitations on what matplotlib can express relative to CSS. ``` -------------------------------- ### Create theme/__init__.py Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Package init for the Campos theme module. Re-exports `use_theme` from `campos.theme.api`. ```python """Campos theme — generated from theme/tokens.json.""" from campos.theme.api import use_theme # noqa: F401 ``` -------------------------------- ### Error response example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/sportmonks/api-access.md Example error response for unauthenticated requests. ```json { "message": "Unauthenticated.", "error_code": 403 } ``` -------------------------------- ### Initialize Git repository for Campos Source: https://github.com/withqwerty/nutmeg/blob/main/docs/superpowers/plans/2026-04-05-campos-s0-validation.md Creates the Campos repository directory and initializes a Git repository. Expected output: 'Initialized empty Git repository in /Users/.../Work/campos/.git/'. ```bash mkdir -p ~/Work/campos cd ~/Work/campos git init ``` -------------------------------- ### V2 End Location JSON Example Source: https://github.com/withqwerty/nutmeg/blob/main/docs/providers/wyscout/coordinate-system.md Example of v2 end location as the second element of the 'positions' array. ```json { "positions": [ { "x": 72, "y": 34 }, { "x": 85, "y": 42 } ] } ```