.claude/skills/destroy-ship/SKILL.md
# Destroy Ship Destroys a corporation ship for testing. Performs the full end-to-end flow: database soft-delete, pseudo-character cleanup, and `ship.destroyed` event emission so connected clients update in real-time. Uses the Supabase REST API and existing `record_event_with_recipients` RPC — no new edge functions required. ## Parameters Ask the user for: - **ship_id**: UUID of the ship to destroy (required) ## Steps ### 1. Source environment variables ```bash set -a && source .env.supaba
npx skillsauth add pipecat-ai/gradient-bang .claude/skills/destroy-shipInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Destroys a corporation ship for testing. Performs the full end-to-end flow: database soft-delete, pseudo-character cleanup, and ship.destroyed event emission so connected clients update in real-time.
Uses the Supabase REST API and existing record_event_with_recipients RPC — no new edge functions required.
Ask the user for:
set -a && source .env.supabase && set +a
Fetch the ship from ship_instances via the REST API. It must exist and not already be destroyed.
curl -s "${SUPABASE_URL}/rest/v1/ship_instances?ship_id=eq.<ship_id>&destroyed_at=is.null&select=ship_id,ship_type,ship_name,current_sector,owner_type,owner_character_id,owner_corporation_id" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
If the result is an empty array, the ship either doesn't exist or is already destroyed. Report this and stop.
Save the ship details for subsequent steps: ship_type, ship_name, current_sector, owner_type, owner_corporation_id.
For corporation ships, the pseudo-character has character_id = ship_id. For personal ships, use owner_character_id.
curl -s "${SUPABASE_URL}/rest/v1/characters?character_id=eq.<character_id>&select=character_id,name" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
Save the character name as player_name for the event payload.
Query sector occupants and corporation members to build the recipient list.
Sector occupants — all non-destroyed ships in the same sector:
curl -s "${SUPABASE_URL}/rest/v1/ship_instances?current_sector=eq.<sector>&destroyed_at=is.null&select=owner_character_id" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
Corporation members (if the ship is corporation-owned):
curl -s "${SUPABASE_URL}/rest/v1/corporation_members?corporation_id=eq.<corp_id>&select=character_id" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
Combine all character IDs, deduplicate, and filter out nulls. Build two parallel arrays:
p_recipients: array of character UUIDsp_reasons: array of reason strings ("sector_observer" for sector occupants, "corp_member" for corp members)ship.destroyed eventCall the existing record_event_with_recipients RPC. This must happen BEFORE the destruction steps so the event references valid data.
The payload shape must match what combat_finalization.ts emits (lines 383-394):
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
curl -s -X POST "${SUPABASE_URL}/rest/v1/rpc/record_event_with_recipients" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Content-Type: application/json" \
-d '{
"p_event_type": "ship.destroyed",
"p_direction": "event_out",
"p_scope": "sector",
"p_sector_id": <current_sector>,
"p_ship_id": "<ship_id>",
"p_actor_character_id": null,
"p_payload": {
"source": {
"type": "rpc",
"method": "ship.destroyed",
"request_id": "admin-destroy",
"timestamp": "<TIMESTAMP>"
},
"timestamp": "<TIMESTAMP>",
"ship_id": "<ship_id>",
"ship_type": "<ship_type>",
"ship_name": "<ship_name>",
"player_type": "corporation_ship",
"player_name": "<player_name>",
"sector": { "id": <current_sector> },
"combat_id": "admin-destroy",
"salvage_created": false
},
"p_recipients": ["<uuid1>", "<uuid2>"],
"p_reasons": ["sector_observer", "corp_member"],
"p_is_broadcast": false
}'
For personal (non-corp) ships, set "player_type": "human" instead.
Perform database cleanup in this exact order (matches combat_finalization.ts lines 435-481). Use the REST API with the service role key.
a. Unlink character's current_ship_id:
curl -s -X PATCH "${SUPABASE_URL}/rest/v1/characters?character_id=eq.<character_id>" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Content-Type: application/json" \
-d '{"current_ship_id": null}'
b. Delete pseudo-character record (corporation ships only — the pseudo-character has character_id = ship_id):
curl -s -X DELETE "${SUPABASE_URL}/rest/v1/characters?character_id=eq.<ship_id>" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
c. Soft-delete ship instance (set destroyed_at):
curl -s -X PATCH "${SUPABASE_URL}/rest/v1/ship_instances?ship_id=eq.<ship_id>" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Content-Type: application/json" \
-d '{"destroyed_at": "<TIMESTAMP>"}'
d. Remove from corporation_ships (corporation ships only):
curl -s -X DELETE "${SUPABASE_URL}/rest/v1/corporation_ships?ship_id=eq.<ship_id>" \
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
Show the user:
ship.destroyed event was emitted (and how many recipients)corporation_shipscombat_id is set to "admin-destroy" to distinguish from real combatsalvage_created is always false — no salvage is generateddestroyed_at IS NOT NULL) are rejected in step 2deployment/supabase/functions/_shared/combat_finalization.ts lines 383-394deployment/supabase/functions/_shared/combat_finalization.ts lines 435-481deployment/supabase/functions/_shared/events.ts lines 80-97client/app/src/utils/combat.ts applyShipDestroyedState()testing
# Restore Ship Restores a ship to a healthy state for testing. Clears the `destroyed_at` flag, restocks fighters/shields/warp power to max values from the ship definition, re-adds corporation ships to `corporation_ships` if missing, and recreates the pseudo-character record for corp ships so tasks can be issued. No events are emitted — this is a database-only operation. ## Parameters Ask the user for: - **ship_id**: UUID of the ship to restore (required) ## Steps ### 1. Source environment
development
# Reset World Resets the game database, generates a fresh universe, loads quest definitions, and seeds combat cron config. ## Parameters The user specifies the environment as an argument: `/reset-world local`, `/reset-world dev`, or `/reset-world prod`. If not provided, ask which environment. - `local` → env file: `.env.supabase` - `dev` → env file: `.env.cloud.dev` - `prod` → env file: `.env.cloud` Additional optional parameters (ask if not provided, or use defaults): - **Sector count**: n
devops
# NPC Runs an autonomous AI task agent as a game character. Resolves a character name to its UUID, then launches the `npc-run` script which connects to the game server and executes the given task using a Pipecat + Gemini LLM pipeline. ## Parameters - **character_name** (required): The character's display name (e.g. `JOETRADER`). Passed as the argument to `/npc`. - **task** (required): A natural language description of what the character should do (e.g. "Explore and find 5 new sectors"). If `
data-ai
# Run Database Migration Applies pending Supabase migrations to the local or production database. This skill is strictly additive — it only applies new migrations and NEVER resets, truncates, or drops existing data. ## Safety rules — READ BEFORE PROCEEDING **You MUST follow every rule below. No exceptions.** 1. **NEVER** run `supabase db reset`, `supabase db reset --linked`, or any command that drops/recreates the database. 2. **NEVER** run `DROP TABLE`, `DROP SCHEMA`, `TRUNCATE`, or `DELETE