---
name: tarot-single-card
description: "Draw a single tarot card from Alex's alexTarot deck (Rider-Waite, 78 cards) with optional reversal. Returns the card name, arcana, qualities, and image path for Telegram delivery."
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [tarot, divination, single-card, reading]
related_skills: [iching-api-reading]
---
# Tarot — Single Card Draw
## When to use
Use when Alex asks for a single-card tarot pull, daily card, quick reading, or "draw me a card." This is the first skill in the tarot bundle; multi-card spreads will be separate skills.
## Parameters
- **`context`** *(optional, string)* — what the reading is about. Examples:
- `"for my career decision tomorrow"`
- `"about my relationship with X"`
- `"about today's creative work"`
When `context` is provided, the reading MUST explicitly weave the card's meaning into that specific situation. When `context` is absent, give a general / open reading of the card and don't fabricate a focus the user didn't state. If unsure, ask — never invent.
- **`reversals`** *(optional)* — default 30% reversal rate. Override only if Alex asks (e.g. "no reversals", "50/50").
## App location
- Repo/path: `/home/avalon/apps/alexTarot`
- PM2 app: `tarot` (also `tarot2` exists, ignore)
- Local API base: `http://127.0.0.1:4033` (health: `/api/health`)
- Deck data: `/home/avalon/apps/alexTarot/public/tarot-images.json` (78 cards, Rider-Waite)
- Card images: `/home/avalon/apps/alexTarot/public/cards/
` (e.g. `m01.jpg`, `c05.jpg`)
The app does NOT expose a draw-card endpoint — it only has layout summary / interpretation endpoints. So this skill draws locally from the deck JSON.
## Card data shape
Each entry in `cards[]`:
```json
{
"name": "The Magician",
"number": "1",
"arcana": "Major Arcana", // or "Minor Arcana"
"suit": null, // or "Cups" / "Wands" / "Swords" / "Pentacles"
"img": "m01.jpg", // filename in public/cards/
"qualities": "Manifestation, skill, ..."
}
```
## Time context (required)
Before drawing, capture wall-clock time in the user's timezone so the framing is honest (morning / evening / day-of-week). Alex's TZ is `America/Los_Angeles`.
```bash
TZ=America/Los_Angeles date '+%Y-%m-%d %H:%M %Z (%A)'
```
Do NOT infer time from voice transcript artifacts. Only frame day/night if the hour supports it.
## Required workflow
Run the draw from a tool, not mentally. Use Python's `secrets` module for the RNG — this is a **real cryptographic random draw**, not seeded and not deterministic, so the pull is genuine divination rather than a narrative pick. Default reversal probability: **30%** (toggleable; Alex can ask "no reversals" or "with reversals 50/50").
Before drawing, note whether a `context` string was supplied. If yes, record it verbatim and shape the reading around it. If no, do a general reading and say so plainly.
```python
from hermes_tools import terminal
import json, secrets
deck = json.load(open('/home/avalon/apps/alexTarot/public/tarot-images.json'))['cards']
assert len(deck) == 78, f'expected 78 cards, got {len(deck)}'
card = secrets.choice(deck)
reversed_ = secrets.randbelow(100) < 30 # ~30% reversal rate
img_path = f"/home/avalon/apps/alexTarot/public/cards/{card['img']}"
print(json.dumps({'card': card, 'reversed': reversed_, 'img_path': img_path}, indent=2))
```
## Reply formatting
Lead with the card itself — image and name — so Alex sees what was drawn before any interpretation. Mirror the `iching-api-reading` structure (story first, mechanics below).
Order (strict):
1. **Card image — ABSOLUTE FIRST LINE of the reply, with NOTHING before it.** Format: `MEDIA:/home/avalon/apps/alexTarot/public/cards/
` on its own line. Do not put any prose, time stamp, italics, or framing text above this line — Telegram needs the MEDIA token at the very top for the image to render above the rest of the message. The time stamp, "no context supplied" note, and any framing belong AFTER the header and details, inside the reading section.
2. **Prominent card-name header** — on its own line, e.g.:
- `# 🎴 The Magician`
- `# 🎴 The Magician — Reversed`
3. **Compact details line** directly under the header, e.g. `Major Arcana · — · 1` or `Minor Arcana · Cups · 5` (arcana · suit · number; use `—` for suit on majors).
4. **The Reading (composite story)** — weave the card's core meaning (from `qualities` + Rider-Waite symbolism), how orientation (upright/reversed) inflects it, and — if `context` was supplied — apply it explicitly to that situation. If no context, read openly.
5. **Expanded details / qualities** — base qualities string from the deck JSON, any extra symbolism worth surfacing, time-context framing if it actually applies.
6. **One-breath summary** — single closing line distilling the message.
If reversed, frame as inversion / blockage / shadow side / inward expression of the upright meaning — not automatic "bad." Stay grounded in traditional Rider-Waite reading conventions.
### Example — with context
> Context: *"about today's creative work"*
>
> `MEDIA:/home/avalon/apps/alexTarot/public/cards/m01.jpg`
>
> `# 🎴 The Magician`
>
> Major Arcana · — · 1
>
> *(reading explicitly tied to today's creative work…)*
### Example — without context
> `MEDIA:/home/avalon/apps/alexTarot/public/cards/m01.jpg`
>
> `# 🎴 The Magician`
>
> Major Arcana · — · 1
>
> *(open / general reading of The Magician, no invented focus)*
## Pitfalls
- Don't invent cards. The deck JSON is the source of truth (78 cards, Majors `m00`–`m21`, Minors `c01`–`c56` roughly).
- **Never substitute `random.choice` for `secrets.choice`, and never hand-pick a card because it fits a narrative.** The draw must be a real cryptographic pull — that's what makes this divination instead of storytelling.
- **Never invent a context the user didn't supply.** If no `context` was given, state plainly that this is a general reading and read the card openly — don't fabricate "your career" or "your relationship" focus.
- The `public/cards/` directory has 79 files (one extra non-card asset is fine — always draw via the JSON, not by listing the directory).
- Public URL (`https://alextarot.apps.poofc.com/cards/...`) isn't reliably reachable from the VPS — use the absolute filesystem path with `MEDIA:` for Telegram delivery.
- Don't claim the alexTarot API drew the card. It didn't — this skill draws locally and only uses the deck JSON the app ships with.
## Verification
- `curl -sS http://127.0.0.1:4033/api/health` should return `{"ok":true,"app":"alexTarot",...}`.
- Deck file must have exactly 78 entries.
- The chosen `img` filename must exist under `public/cards/`.