thoth-cli 0.2.20 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -12,27 +12,37 @@ import {
12
12
  formatEphemerisRange,
13
13
  formatHorary,
14
14
  formatLunarReturn,
15
+ formatMoon,
15
16
  formatMoonExtended,
16
17
  formatProgressions,
17
18
  formatScore,
18
19
  formatSolarArc,
19
20
  formatSolarReturn,
20
21
  formatSynastry,
22
+ formatTarotCard,
23
+ formatTarotDeck,
24
+ formatTarotDraw,
25
+ formatTarotSpreads,
21
26
  formatTransitScan,
22
27
  formatTransits,
23
28
  horary,
24
29
  isError,
25
30
  lunarReturn,
31
+ moon,
26
32
  moonExtended,
27
33
  progressions,
28
34
  score,
29
35
  solarArc,
30
36
  solarReturn,
31
37
  synastry,
38
+ tarotCard,
39
+ tarotDeck,
40
+ tarotDraw,
41
+ tarotSpreads,
32
42
  transit,
33
43
  transitScan,
34
44
  version
35
- } from "./chunk-QND56LGZ.js";
45
+ } from "./chunk-X7IGMJUH.js";
36
46
 
37
47
  // src/bin.ts
38
48
  import { Command } from "commander";
@@ -94,7 +104,7 @@ EPHEMERIS & MOON
94
104
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
95
105
  REFERENCE
96
106
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
97
- thoth key # full symbol reference`).version("0.2.20");
107
+ thoth key # full symbol reference`).version("0.2.21");
98
108
  program.command("chart").description("Calculate a natal chart").requiredOption("--date <date>", "Birth date (YYYY-MM-DD)").requiredOption("--time <time>", "Birth time (HH:MM)").option("--lat <lat>", "Latitude", parseFloat).option("--lng <lng>", "Longitude", parseFloat).option("--city <city>", "City name").option("--nation <nation>", "Country code", "US").option("--name <name>", "Name", "Subject").option("--json", "Output raw JSON").option("--svg", "Output SVG chart").option("--svg-file <path>", "Save SVG to file").action(async (options) => {
99
109
  if (!options.city && (!options.lat || !options.lng)) {
100
110
  console.error(chalk.red("Error: Must provide either --city or both --lat and --lng"));
@@ -479,19 +489,40 @@ program.command("horary").description("Cast a horary chart for divination (like
479
489
  console.log(formatHorary(result));
480
490
  }
481
491
  });
482
- program.command("moon").description("Get moon phase, eclipses, sunrise/sunset").option("--date <date>", "Date (YYYY-MM-DD, default: today)").option("--lat <lat>", "Latitude", parseFloat, 40.7128).option("--lng <lng>", "Longitude", parseFloat, -74.006).option("--tz <tz>", "Timezone", "America/New_York").option("--json", "Output raw JSON").action(async (options) => {
492
+ program.command("moon").description("Get moon phase and position").option("--date <date>", "Date (YYYY-MM-DD, default: today)").option("--lat <lat>", "Latitude", parseFloat, 40.7128).option("--lng <lng>", "Longitude", parseFloat, -74.006).option("--tz <tz>", "Timezone (for --extended)", "America/New_York").option("-e, --extended", "Show eclipses, sunrise/sunset, upcoming phases").option("--json", "Output raw JSON").action(async (options) => {
483
493
  let year, month, day;
484
494
  if (options.date) {
485
495
  [year, month, day] = options.date.split("-").map(Number);
486
496
  }
487
- const spinner = ora("Getting moon data...").start();
488
- const result = await moonExtended({
497
+ if (options.extended) {
498
+ const spinner2 = ora("Getting moon details...").start();
499
+ const result2 = await moonExtended({
500
+ year,
501
+ month,
502
+ day,
503
+ lat: options.lat,
504
+ lng: options.lng,
505
+ tz: options.tz
506
+ });
507
+ spinner2.stop();
508
+ if (isError(result2)) {
509
+ console.error(chalk.red(`Error: ${result2.error}`));
510
+ process.exit(1);
511
+ }
512
+ if (options.json) {
513
+ console.log(JSON.stringify(result2, null, 2));
514
+ } else {
515
+ console.log(formatMoonExtended(result2));
516
+ }
517
+ return;
518
+ }
519
+ const spinner = ora("Getting moon phase...").start();
520
+ const result = await moon({
489
521
  year,
490
522
  month,
491
523
  day,
492
524
  lat: options.lat,
493
- lng: options.lng,
494
- tz: options.tz
525
+ lng: options.lng
495
526
  });
496
527
  spinner.stop();
497
528
  if (isError(result)) {
@@ -501,7 +532,7 @@ program.command("moon").description("Get moon phase, eclipses, sunrise/sunset").
501
532
  if (options.json) {
502
533
  console.log(JSON.stringify(result, null, 2));
503
534
  } else {
504
- console.log(formatMoonExtended(result));
535
+ console.log(formatMoon(result));
505
536
  }
506
537
  });
507
538
  program.command("ephemeris").description("Get ephemeris position for a celestial body").requiredOption("--body <body>", "Celestial body (sun, moon, mars, etc.)").option("--date <date>", "Date (YYYY-MM-DD, default: today)").option("--json", "Output raw JSON").action(async (options) => {
@@ -537,7 +568,7 @@ program.command("core-version").description("Show thoth-core version").action(as
537
568
  });
538
569
  program.command("key").description("Symbol reference guide").action(() => {
539
570
  const sun = chalk.hex("#FFD700");
540
- const moon = chalk.hex("#C0C0C0");
571
+ const moon2 = chalk.hex("#C0C0C0");
541
572
  const mercury = chalk.hex("#FF8C00");
542
573
  const venus = chalk.hex("#00FF7F");
543
574
  const mars = chalk.hex("#FF0000");
@@ -554,8 +585,8 @@ program.command("key").description("Symbol reference guide").action(() => {
554
585
  console.log(chalk.bold.cyan("\u2550\u2550 PLANETS \u2550\u2550"));
555
586
  console.log(` ${sun("\u2609 Sun")} Identity, vitality, ego, life force`);
556
587
  console.log(` ${chalk.dim("Rules:")} ${sun("Leo")} ${chalk.dim("Sephira:")} Tiphareth`);
557
- console.log(` ${moon("\u263D Moon")} Emotions, instincts, the unconscious, mother`);
558
- console.log(` ${chalk.dim("Rules:")} ${moon("Cancer")} ${chalk.dim("Sephira:")} Yesod`);
588
+ console.log(` ${moon2("\u263D Moon")} Emotions, instincts, the unconscious, mother`);
589
+ console.log(` ${chalk.dim("Rules:")} ${moon2("Cancer")} ${chalk.dim("Sephira:")} Yesod`);
559
590
  console.log(` ${mercury("\u263F Mercury")} Mind, communication, learning, commerce`);
560
591
  console.log(` ${chalk.dim("Rules:")} ${mercury("Gemini, Virgo")} ${chalk.dim("Sephira:")} Hod`);
561
592
  console.log(` ${venus("\u2640 Venus")} Love, beauty, values, attraction, harmony`);
@@ -586,8 +617,8 @@ program.command("key").description("Symbol reference guide").action(() => {
586
617
  console.log(` ${chalk.dim("Ruler:")} ${venus("Venus")} ${chalk.dim('"I HAVE"')}`);
587
618
  console.log(` ${mercury("\u264A Gemini")} ${chalk.dim("Mutable Air")} Curiosity, duality, scattered`);
588
619
  console.log(` ${chalk.dim("Ruler:")} ${mercury("Mercury")} ${chalk.dim('"I THINK"')}`);
589
- console.log(` ${moon("\u264B Cancer")} ${chalk.dim("Cardinal Water")} Nurturing, protective, moody`);
590
- console.log(` ${chalk.dim("Ruler:")} ${moon("Moon")} ${chalk.dim('"I FEEL"')}`);
620
+ console.log(` ${moon2("\u264B Cancer")} ${chalk.dim("Cardinal Water")} Nurturing, protective, moody`);
621
+ console.log(` ${chalk.dim("Ruler:")} ${moon2("Moon")} ${chalk.dim('"I FEEL"')}`);
591
622
  console.log(` ${sun("\u264C Leo")} ${chalk.dim("Fixed Fire")} Creative, proud, dramatic`);
592
623
  console.log(` ${chalk.dim("Ruler:")} ${sun("Sun")} ${chalk.dim('"I WILL"')}`);
593
624
  console.log(` ${mercury("\u264D Virgo")} ${chalk.dim("Mutable Earth")} Analytical, service, critical`);
@@ -622,7 +653,7 @@ program.command("key").description("Symbol reference guide").action(() => {
622
653
  console.log(chalk.bold.cyan("\u2550\u2550 ASPECTS \u2550\u2550"));
623
654
  console.log(` ${sun("\u260C Conjunction")} 0\xB0 Fusion, intensification, new cycle`);
624
655
  console.log(` ${chalk.dim("Sephira: Tiphareth (Sun) \u2014 creative union")}`);
625
- console.log(` ${moon("\u260D Opposition")} 180\xB0 Awareness, tension, projection`);
656
+ console.log(` ${moon2("\u260D Opposition")} 180\xB0 Awareness, tension, projection`);
626
657
  console.log(` ${chalk.dim("Sephira: Yesod (Moon) \u2014 polarity, reflection")}`);
627
658
  console.log(` ${jupiter("\u25B3 Trine")} 120\xB0 Harmony, ease, natural talent`);
628
659
  console.log(` ${chalk.dim("Sephira: Chesed (Jupiter) \u2014 grace, flow")}`);
@@ -644,12 +675,12 @@ program.command("key").description("Symbol reference guide").action(() => {
644
675
  console.log(` ${mercury("\u{1F701} Air")} ${mercury("Gemini, Libra, Aquarius")}`);
645
676
  console.log(` Mind, communication, connection, ideas`);
646
677
  console.log(` ${chalk.dim("Hot & Wet \u2014 Sanguine \u2014 Thinking function")}`);
647
- console.log(` ${jupiter("\u{1F704} Water")} ${moon("Cancer, Scorpio, Pisces")}`);
678
+ console.log(` ${jupiter("\u{1F704} Water")} ${moon2("Cancer, Scorpio, Pisces")}`);
648
679
  console.log(` Emotion, intuition, the unconscious, soul`);
649
680
  console.log(` ${chalk.dim("Cold & Wet \u2014 Phlegmatic \u2014 Feeling function")}`);
650
681
  console.log("");
651
682
  console.log(chalk.bold.cyan("\u2550\u2550 MODALITIES \u2550\u2550"));
652
- console.log(` ${chalk.bold("Cardinal")} ${mars("Aries")}, ${moon("Cancer")}, ${venus("Libra")}, ${saturn("Capricorn")}`);
683
+ console.log(` ${chalk.bold("Cardinal")} ${mars("Aries")}, ${moon2("Cancer")}, ${venus("Libra")}, ${saturn("Capricorn")}`);
653
684
  console.log(` Initiating, leadership, action`);
654
685
  console.log(` ${chalk.dim('The spark. Begins seasons. "I start."')}`);
655
686
  console.log(` ${chalk.bold("Fixed")} ${venus("Taurus")}, ${sun("Leo")}, ${pluto("Scorpio")}, ${uranus("Aquarius")}`);
@@ -773,7 +804,62 @@ program.command("ephemeris-multi").description("Get ephemeris for multiple bodie
773
804
  console.log(formatEphemerisMulti(result));
774
805
  }
775
806
  });
807
+ program.command("tarot").alias("draw").description("Draw tarot cards (cryptographic randomness)").option("-s, --spread <spread>", "Spread: single, 3-card, celtic, horseshoe, relationship, decision", "single").option("-q, --question <question>", "Question for the reading").option("-n, --count <count>", "Number of cards (for custom spread)", parseInt).option("--no-reversals", "Disable reversed cards").option("--json", "Output raw JSON").action(async (options) => {
808
+ const spinner = ora("Shuffling the deck...").start();
809
+ const result = await tarotDraw({
810
+ spread: options.spread,
811
+ question: options.question,
812
+ count: options.count,
813
+ reversals: options.reversals
814
+ });
815
+ spinner.stop();
816
+ if (isError(result)) {
817
+ console.error(chalk.red("Error: " + result.error));
818
+ process.exit(1);
819
+ }
820
+ if (options.json) {
821
+ console.log(JSON.stringify(result, null, 2));
822
+ } else {
823
+ console.log(formatTarotDraw(result));
824
+ }
825
+ });
826
+ program.command("tarot-card <card>").alias("card").description("Look up a tarot card by name or number").option("--json", "Output raw JSON").action(async (card, options) => {
827
+ const result = await tarotCard(card);
828
+ if (isError(result)) {
829
+ console.error(chalk.red("Error: " + result.error));
830
+ process.exit(1);
831
+ }
832
+ if (options.json) {
833
+ console.log(JSON.stringify(result, null, 2));
834
+ } else {
835
+ console.log(formatTarotCard(result));
836
+ }
837
+ });
838
+ program.command("tarot-deck").alias("deck").description("List tarot cards").option("-f, --filter <filter>", "Filter: major, minor, wands, cups, swords, pentacles").option("--json", "Output raw JSON").action(async (options) => {
839
+ const result = await tarotDeck(options.filter);
840
+ if (isError(result)) {
841
+ console.error(chalk.red("Error: " + result.error));
842
+ process.exit(1);
843
+ }
844
+ if (options.json) {
845
+ console.log(JSON.stringify(result, null, 2));
846
+ } else {
847
+ console.log(formatTarotDeck(result));
848
+ }
849
+ });
850
+ program.command("tarot-spreads").alias("spreads").description("List available tarot spreads").option("--json", "Output raw JSON").action(async (options) => {
851
+ const result = await tarotSpreads();
852
+ if (isError(result)) {
853
+ console.error(chalk.red("Error: " + result.error));
854
+ process.exit(1);
855
+ }
856
+ if (options.json) {
857
+ console.log(JSON.stringify(result, null, 2));
858
+ } else {
859
+ console.log(formatTarotSpreads(result));
860
+ }
861
+ });
776
862
  console.log(chalk.dim(""));
777
- console.log(chalk.yellow(" \u{1315D}") + chalk.dim(" thoth-cli v0.2.20"));
863
+ console.log(chalk.yellow(" \u{1315D}") + chalk.dim(" thoth-cli v0.2.22"));
778
864
  console.log(chalk.dim(""));
779
865
  program.parse();
@@ -514,6 +514,25 @@ async function ephemerisMulti(options) {
514
514
  if (options.lng !== void 0) args.push("--lng", String(options.lng));
515
515
  return execute("ephemeris-multi", args);
516
516
  }
517
+ async function tarotDraw(options) {
518
+ const args = [];
519
+ if (options.count) args.push("--count", String(options.count));
520
+ if (options.spread) args.push("--spread", options.spread);
521
+ if (options.question) args.push("--question", options.question);
522
+ if (options.reversals === false) args.push("--no-reversals");
523
+ return execute("tarot-draw", args);
524
+ }
525
+ async function tarotCard(identifier) {
526
+ return execute("tarot-card", [identifier]);
527
+ }
528
+ async function tarotDeck(filter) {
529
+ const args = [];
530
+ if (filter) args.push("--filter", filter);
531
+ return execute("tarot-deck", args);
532
+ }
533
+ async function tarotSpreads() {
534
+ return execute("tarot-spreads", []);
535
+ }
517
536
 
518
537
  // src/lib/format.ts
519
538
  import chalk from "chalk";
@@ -1434,6 +1453,159 @@ function formatEphemerisMulti(result) {
1434
1453
  lines.push("");
1435
1454
  return lines.join("\n");
1436
1455
  }
1456
+ var TAROT_COLORS = {
1457
+ major: chalk.hex("#FFD700"),
1458
+ // Gold for Major Arcana
1459
+ wands: chalk.hex("#FF4500"),
1460
+ // Fire - Orange Red
1461
+ cups: chalk.hex("#4169E1"),
1462
+ // Water - Royal Blue
1463
+ swords: chalk.hex("#E0E0E0"),
1464
+ // Air - Silver
1465
+ pentacles: chalk.hex("#228B22")
1466
+ // Earth - Forest Green
1467
+ };
1468
+ function getTarotColor(card) {
1469
+ if (card.arcana === "major") return TAROT_COLORS.major;
1470
+ return TAROT_COLORS[card.suit] || chalk.white;
1471
+ }
1472
+ function getSuitSymbol(suit) {
1473
+ const symbols = {
1474
+ wands: "\u{1F702}",
1475
+ // Fire alchemical symbol
1476
+ cups: "\u{1F704}",
1477
+ // Water alchemical symbol
1478
+ swords: "\u{1F701}",
1479
+ // Air alchemical symbol
1480
+ pentacles: "\u{1F703}"
1481
+ // Earth alchemical symbol
1482
+ };
1483
+ return symbols[suit] || "";
1484
+ }
1485
+ function formatTarotDraw(result) {
1486
+ const lines = [];
1487
+ lines.push("");
1488
+ lines.push(chalk.bold.hex("#9932CC")("\u{1F3B4} TAROT READING"));
1489
+ lines.push(` ${chalk.dim("Spread:")} ${result.spread_name}`);
1490
+ if (result.question) {
1491
+ lines.push(` ${chalk.dim("Question:")} "${result.question}"`);
1492
+ }
1493
+ lines.push(` ${chalk.dim("Entropy:")} ${result.entropy_source}`);
1494
+ lines.push(` ${chalk.dim("Time:")} ${result.timestamp}`);
1495
+ lines.push("");
1496
+ lines.push(chalk.bold.cyan("\u2500\u2500 THE CARDS \u2500\u2500"));
1497
+ lines.push("");
1498
+ for (const card of result.cards) {
1499
+ const color = getTarotColor(card);
1500
+ const reversed = card.reversed ? chalk.red(" \u211E REVERSED") : "";
1501
+ const suitSymbol = card.suit ? ` ${getSuitSymbol(card.suit)}` : "";
1502
+ lines.push(` ${chalk.bold.white(`[${card.position}] ${card.position_name}`)}`);
1503
+ lines.push(` ${color(card.name)}${suitSymbol}${reversed}`);
1504
+ if (card.arcana === "major") {
1505
+ const details = [];
1506
+ if (card.hebrew) details.push(card.hebrew);
1507
+ if (card.planet) details.push(`\u2609 ${card.planet}`);
1508
+ if (card.zodiac) details.push(`\u2648 ${card.zodiac}`);
1509
+ if (card.element) details.push(`\u25B3 ${card.element}`);
1510
+ if (details.length > 0) {
1511
+ lines.push(` ${chalk.dim(details.join(" | "))}`);
1512
+ }
1513
+ } else {
1514
+ const details = [];
1515
+ if (card.element) details.push(`${card.element}`);
1516
+ if (card.sephira) details.push(card.sephira);
1517
+ if (card.theme) details.push(card.theme);
1518
+ if (details.length > 0) {
1519
+ lines.push(` ${chalk.dim(details.join(" | "))}`);
1520
+ }
1521
+ }
1522
+ const keywords = card.reversed ? card.keywords_reversed : card.keywords_upright;
1523
+ if (keywords && keywords.length > 0) {
1524
+ const keywordStr = keywords.slice(0, 5).join(", ");
1525
+ lines.push(` ${chalk.italic(keywordStr)}`);
1526
+ }
1527
+ lines.push("");
1528
+ }
1529
+ lines.push(chalk.dim("\u2500".repeat(60)));
1530
+ lines.push(chalk.dim(" The cards are cast. The interpretation is yours."));
1531
+ lines.push("");
1532
+ return lines.join("\n");
1533
+ }
1534
+ function formatTarotCard(card) {
1535
+ const lines = [];
1536
+ const color = getTarotColor(card);
1537
+ lines.push("");
1538
+ lines.push(color(`\u{1F3B4} ${card.name}`));
1539
+ lines.push(` ${chalk.dim("Number:")} ${card.number} | ${chalk.dim("Arcana:")} ${card.arcana}`);
1540
+ if (card.arcana === "major") {
1541
+ if (card.hebrew) lines.push(` ${chalk.dim("Hebrew:")} ${card.hebrew} | ${chalk.dim("Path:")} ${card.path}`);
1542
+ if (card.planet) lines.push(` ${chalk.dim("Planet:")} ${card.planet}`);
1543
+ if (card.zodiac) lines.push(` ${chalk.dim("Zodiac:")} ${card.zodiac}`);
1544
+ if (card.element) lines.push(` ${chalk.dim("Element:")} ${card.element}`);
1545
+ } else {
1546
+ lines.push(` ${chalk.dim("Suit:")} ${card.suit} (${card.element})`);
1547
+ lines.push(` ${chalk.dim("Rank:")} ${card.rank} | ${chalk.dim("Sephira:")} ${card.sephira}`);
1548
+ lines.push(` ${chalk.dim("Theme:")} ${card.theme}`);
1549
+ }
1550
+ lines.push("");
1551
+ lines.push(chalk.bold.green(" Upright:"));
1552
+ lines.push(` ${card.keywords_upright.join(", ")}`);
1553
+ lines.push("");
1554
+ lines.push(chalk.bold.red(" Reversed:"));
1555
+ lines.push(` ${card.keywords_reversed.join(", ")}`);
1556
+ lines.push("");
1557
+ return lines.join("\n");
1558
+ }
1559
+ function formatTarotDeck(result) {
1560
+ const lines = [];
1561
+ lines.push("");
1562
+ lines.push(chalk.bold.hex("#9932CC")(`\u{1F3B4} TAROT DECK (${result.count} cards)`));
1563
+ if (result.filter) {
1564
+ lines.push(` Filter: ${result.filter}`);
1565
+ }
1566
+ lines.push("");
1567
+ const majors = result.cards.filter((c) => c.arcana === "major");
1568
+ const wands = result.cards.filter((c) => c.suit === "wands");
1569
+ const cups = result.cards.filter((c) => c.suit === "cups");
1570
+ const swords = result.cards.filter((c) => c.suit === "swords");
1571
+ const pentacles = result.cards.filter((c) => c.suit === "pentacles");
1572
+ if (majors.length > 0) {
1573
+ lines.push(TAROT_COLORS.major("\u2500\u2500 MAJOR ARCANA \u2500\u2500"));
1574
+ for (const card of majors) {
1575
+ lines.push(` ${String(card.number).padStart(2)}. ${card.name}`);
1576
+ }
1577
+ lines.push("");
1578
+ }
1579
+ const suits = [
1580
+ { name: "WANDS", cards: wands, color: TAROT_COLORS.wands, symbol: "\u{1F702}" },
1581
+ { name: "CUPS", cards: cups, color: TAROT_COLORS.cups, symbol: "\u{1F704}" },
1582
+ { name: "SWORDS", cards: swords, color: TAROT_COLORS.swords, symbol: "\u{1F701}" },
1583
+ { name: "PENTACLES", cards: pentacles, color: TAROT_COLORS.pentacles, symbol: "\u{1F703}" }
1584
+ ];
1585
+ for (const suit of suits) {
1586
+ if (suit.cards.length > 0) {
1587
+ lines.push(suit.color(`\u2500\u2500 ${suit.symbol} ${suit.name} \u2500\u2500`));
1588
+ for (const card of suit.cards) {
1589
+ lines.push(` ${String(card.number).padStart(2)}. ${card.name}`);
1590
+ }
1591
+ lines.push("");
1592
+ }
1593
+ }
1594
+ return lines.join("\n");
1595
+ }
1596
+ function formatTarotSpreads(result) {
1597
+ const lines = [];
1598
+ lines.push("");
1599
+ lines.push(chalk.bold.hex("#9932CC")("\u{1F3B4} AVAILABLE SPREADS"));
1600
+ lines.push("");
1601
+ for (const spread of result.spreads) {
1602
+ lines.push(chalk.bold(` ${spread.name} (${spread.id})`));
1603
+ lines.push(` ${chalk.dim(spread.description)}`);
1604
+ lines.push(` Cards: ${spread.count} \u2014 ${spread.positions.join(" \u2192 ")}`);
1605
+ lines.push("");
1606
+ }
1607
+ return lines.join("\n");
1608
+ }
1437
1609
 
1438
1610
  // src/types.ts
1439
1611
  function isError(result) {
@@ -1458,6 +1630,10 @@ export {
1458
1630
  moonExtended,
1459
1631
  transitScan,
1460
1632
  ephemerisMulti,
1633
+ tarotDraw,
1634
+ tarotCard,
1635
+ tarotDeck,
1636
+ tarotSpreads,
1461
1637
  getZodiacSymbol,
1462
1638
  getPlanetSymbol,
1463
1639
  getAspectSymbol,
@@ -1478,5 +1654,9 @@ export {
1478
1654
  formatMoonExtended,
1479
1655
  formatTransitScan,
1480
1656
  formatEphemerisMulti,
1657
+ formatTarotDraw,
1658
+ formatTarotCard,
1659
+ formatTarotDeck,
1660
+ formatTarotSpreads,
1481
1661
  isError
1482
1662
  };
package/dist/index.d.ts CHANGED
@@ -498,6 +498,59 @@ interface ThothError {
498
498
  }
499
499
  type ThothResult<T> = T | ThothError;
500
500
  declare function isError<T extends object>(result: ThothResult<T>): result is ThothError;
501
+ interface TarotCard {
502
+ number: number;
503
+ name: string;
504
+ arcana: 'major' | 'minor';
505
+ suit?: string;
506
+ rank?: string;
507
+ hebrew?: string;
508
+ path?: number;
509
+ element?: string;
510
+ planet?: string;
511
+ zodiac?: string;
512
+ domain?: string;
513
+ sephira?: string;
514
+ theme?: string;
515
+ keywords_upright: string[];
516
+ keywords_reversed: string[];
517
+ reversed?: boolean;
518
+ position?: number;
519
+ position_name?: string;
520
+ }
521
+ interface TarotDrawResult {
522
+ type: string;
523
+ timestamp: string;
524
+ entropy_source: string;
525
+ question?: string;
526
+ spread: string;
527
+ spread_name: string;
528
+ cards: TarotCard[];
529
+ total_cards: number;
530
+ }
531
+ interface TarotDrawOptions {
532
+ count?: number;
533
+ spread?: string;
534
+ question?: string;
535
+ reversals?: boolean;
536
+ }
537
+ interface TarotDeckResult {
538
+ type: string;
539
+ filter?: string;
540
+ count: number;
541
+ cards: TarotCard[];
542
+ }
543
+ interface TarotSpread {
544
+ id: string;
545
+ name: string;
546
+ count: number;
547
+ positions: string[];
548
+ description: string;
549
+ }
550
+ interface TarotSpreadsResult {
551
+ type: string;
552
+ spreads: TarotSpread[];
553
+ }
501
554
  interface ScoreOptions {
502
555
  year1: number;
503
556
  month1: number;
@@ -747,6 +800,22 @@ declare function transitScan(options: TransitScanOptions): Promise<ThothResult<T
747
800
  * Get multi-body ephemeris over a date range
748
801
  */
749
802
  declare function ephemerisMulti(options: EphemerisMultiOptions): Promise<ThothResult<EphemerisMultiResult>>;
803
+ /**
804
+ * Draw tarot cards with cryptographic randomness
805
+ */
806
+ declare function tarotDraw(options: TarotDrawOptions): Promise<ThothResult<TarotDrawResult>>;
807
+ /**
808
+ * Look up a specific tarot card
809
+ */
810
+ declare function tarotCard(identifier: string): Promise<ThothResult<TarotCard>>;
811
+ /**
812
+ * Get tarot deck (optionally filtered)
813
+ */
814
+ declare function tarotDeck(filter?: string): Promise<ThothResult<TarotDeckResult>>;
815
+ /**
816
+ * List available tarot spreads
817
+ */
818
+ declare function tarotSpreads(): Promise<ThothResult<TarotSpreadsResult>>;
750
819
 
751
820
  /**
752
821
  * Output formatting utilities
@@ -833,5 +902,21 @@ declare function formatTransitScan(result: any): string;
833
902
  * Format multi-body ephemeris
834
903
  */
835
904
  declare function formatEphemerisMulti(result: any): string;
905
+ /**
906
+ * Format a tarot draw result
907
+ */
908
+ declare function formatTarotDraw(result: any): string;
909
+ /**
910
+ * Format a single tarot card lookup
911
+ */
912
+ declare function formatTarotCard(card: any): string;
913
+ /**
914
+ * Format tarot deck listing
915
+ */
916
+ declare function formatTarotDeck(result: any): string;
917
+ /**
918
+ * Format available spreads
919
+ */
920
+ declare function formatTarotSpreads(result: any): string;
836
921
 
837
- export { type Aspect, type ChartOptions, type ChartResult, type CompositeOptions, type CompositeResult, type DirectedPlanet, type EphemerisMultiOptions, type EphemerisMultiResult, type EphemerisOptions, type EphemerisPosition, type EphemerisRangeOptions, type EphemerisRangeResult, type EphemerisResult, type HoraryHouse, type HoraryOptions, type HoraryResult, type House, type LunarPhase, type LunarReturnOptions, type LunarReturnResult, type MoonAspect, type MoonExtendedOptions, type MoonExtendedResult, type MoonOptions, type MoonResult, type Planet, type ProgressionsOptions, type ProgressionsResult, type RetrogradeStation, type ScoreOptions, type ScoreResult, type SignChange, type SolarArcOptions, type SolarArcResult, type SolarReturnOptions, type SolarReturnResult, type SynastryOptions, type SynastryResult, type ThothError, type ThothResult, type TransitOptions, type TransitResult, type TransitScanOptions, type TransitScanResult, chart, composite, ephemeris, ephemerisMulti, ephemerisRange, formatChart, formatComposite, formatDegrees, formatEphemeris, formatEphemerisMulti, formatEphemerisRange, formatHorary, formatLunarReturn, formatMoon, formatMoonExtended, formatProgressions, formatScore, formatSolarArc, formatSolarReturn, formatSynastry, formatTransitScan, formatTransits, getAspectSymbol, getPlanetSymbol, getZodiacSymbol, horary, isError, lunarReturn, moon, moonExtended, progressions, score, solarArc, solarReturn, synastry, transit, transitScan, version };
922
+ export { type Aspect, type ChartOptions, type ChartResult, type CompositeOptions, type CompositeResult, type DirectedPlanet, type EphemerisMultiOptions, type EphemerisMultiResult, type EphemerisOptions, type EphemerisPosition, type EphemerisRangeOptions, type EphemerisRangeResult, type EphemerisResult, type HoraryHouse, type HoraryOptions, type HoraryResult, type House, type LunarPhase, type LunarReturnOptions, type LunarReturnResult, type MoonAspect, type MoonExtendedOptions, type MoonExtendedResult, type MoonOptions, type MoonResult, type Planet, type ProgressionsOptions, type ProgressionsResult, type RetrogradeStation, type ScoreOptions, type ScoreResult, type SignChange, type SolarArcOptions, type SolarArcResult, type SolarReturnOptions, type SolarReturnResult, type SynastryOptions, type SynastryResult, type TarotCard, type TarotDeckResult, type TarotDrawOptions, type TarotDrawResult, type TarotSpread, type TarotSpreadsResult, type ThothError, type ThothResult, type TransitOptions, type TransitResult, type TransitScanOptions, type TransitScanResult, chart, composite, ephemeris, ephemerisMulti, ephemerisRange, formatChart, formatComposite, formatDegrees, formatEphemeris, formatEphemerisMulti, formatEphemerisRange, formatHorary, formatLunarReturn, formatMoon, formatMoonExtended, formatProgressions, formatScore, formatSolarArc, formatSolarReturn, formatSynastry, formatTarotCard, formatTarotDeck, formatTarotDraw, formatTarotSpreads, formatTransitScan, formatTransits, getAspectSymbol, getPlanetSymbol, getZodiacSymbol, horary, isError, lunarReturn, moon, moonExtended, progressions, score, solarArc, solarReturn, synastry, tarotCard, tarotDeck, tarotDraw, tarotSpreads, transit, transitScan, version };
package/dist/index.js CHANGED
@@ -19,6 +19,10 @@ import {
19
19
  formatSolarArc,
20
20
  formatSolarReturn,
21
21
  formatSynastry,
22
+ formatTarotCard,
23
+ formatTarotDeck,
24
+ formatTarotDraw,
25
+ formatTarotSpreads,
22
26
  formatTransitScan,
23
27
  formatTransits,
24
28
  getAspectSymbol,
@@ -34,10 +38,14 @@ import {
34
38
  solarArc,
35
39
  solarReturn,
36
40
  synastry,
41
+ tarotCard,
42
+ tarotDeck,
43
+ tarotDraw,
44
+ tarotSpreads,
37
45
  transit,
38
46
  transitScan,
39
47
  version
40
- } from "./chunk-QND56LGZ.js";
48
+ } from "./chunk-X7IGMJUH.js";
41
49
  export {
42
50
  chart,
43
51
  composite,
@@ -59,6 +67,10 @@ export {
59
67
  formatSolarArc,
60
68
  formatSolarReturn,
61
69
  formatSynastry,
70
+ formatTarotCard,
71
+ formatTarotDeck,
72
+ formatTarotDraw,
73
+ formatTarotSpreads,
62
74
  formatTransitScan,
63
75
  formatTransits,
64
76
  getAspectSymbol,
@@ -74,6 +86,10 @@ export {
74
86
  solarArc,
75
87
  solarReturn,
76
88
  synastry,
89
+ tarotCard,
90
+ tarotDeck,
91
+ tarotDraw,
92
+ tarotSpreads,
77
93
  transit,
78
94
  transitScan,
79
95
  version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thoth-cli",
3
- "version": "0.2.20",
3
+ "version": "0.2.22",
4
4
  "description": "𓅝 Astrological calculations from the command line. Swiss Ephemeris precision. Built for humans and agents.",
5
5
  "author": "AKLO <aklo@aklolabs.com>",
6
6
  "license": "MIT",