@tokenomist-ai/tokenomist-cli 0.1.1 → 0.2.0

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.
@@ -1,89 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ package_default
4
+ } from "./chunk-DCGA3ANT.js";
2
5
 
3
6
  // src/update-check.ts
4
7
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
5
8
  import { join } from "path";
6
9
  import { homedir } from "os";
7
-
8
- // package.json
9
- var package_default = {
10
- name: "@tokenomist-ai/tokenomist-cli",
11
- version: "0.1.1",
12
- description: "CLI tool for the Tokenomist API \u2014 query token unlocks, emissions, fundraising, burns, and buybacks from the terminal",
13
- type: "module",
14
- main: "dist/index.js",
15
- bin: {
16
- tok: "dist/index.js"
17
- },
18
- scripts: {
19
- postinstall: "node scripts/postinstall.js",
20
- build: "tsup",
21
- dev: "tsup --watch",
22
- start: "node dist/index.js",
23
- test: "vitest run",
24
- "test:watch": "vitest",
25
- lint: "eslint src/ tests/",
26
- "lint:fix": "eslint src/ tests/ --fix",
27
- format: "prettier --write 'src/**/*.ts' 'tests/**/*.ts'",
28
- "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts'",
29
- prepublishOnly: "npm run build"
30
- },
31
- keywords: [
32
- "tokenomist",
33
- "crypto",
34
- "token",
35
- "unlock",
36
- "emission",
37
- "fundraising",
38
- "burn",
39
- "buyback",
40
- "cli",
41
- "api"
42
- ],
43
- author: {
44
- name: "tokenomist-ai",
45
- email: "support@tokenomist.ai",
46
- url: "https://tokenomist.ai"
47
- },
48
- license: "MIT",
49
- repository: {
50
- type: "git",
51
- url: "git+https://github.com/tokenomist-ai/tokenomist-cli.git"
52
- },
53
- homepage: "https://github.com/tokenomist-ai/tokenomist-cli#readme",
54
- bugs: {
55
- url: "https://github.com/tokenomist-ai/tokenomist-cli/issues"
56
- },
57
- engines: {
58
- node: ">=18.0.0"
59
- },
60
- publishConfig: {
61
- access: "public"
62
- },
63
- files: [
64
- "dist",
65
- "skills/**",
66
- "scripts/postinstall.js",
67
- "LICENSE",
68
- "README.md"
69
- ],
70
- dependencies: {
71
- "cli-table3": "^0.6.5",
72
- commander: "^12.1.0",
73
- dotenv: "^16.4.7"
74
- },
75
- devDependencies: {
76
- "@types/node": "^22.10.0",
77
- eslint: "^9.16.0",
78
- prettier: "^3.4.2",
79
- tsup: "^8.3.5",
80
- typescript: "^5.7.2",
81
- "typescript-eslint": "^8.57.0",
82
- vitest: "^3.2.4"
83
- }
84
- };
85
-
86
- // src/update-check.ts
87
10
  var CONFIG_DIR = join(homedir(), ".tokenomist");
88
11
  var CACHE_PATH = join(CONFIG_DIR, "update-check.json");
89
12
  var ONE_DAY = 24 * 60 * 60 * 1e3;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/update-check.ts","../package.json"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst CONFIG_DIR = join(homedir(), \".tokenomist\");\nconst CACHE_PATH = join(CONFIG_DIR, \"update-check.json\");\nconst ONE_DAY = 24 * 60 * 60 * 1000;\nconst REGISTRY_URL = \"https://registry.npmjs.org/@tokenomist-ai%2Ftokenomist-cli/latest\";\n\ninterface UpdateCache {\n latest: string;\n current: string;\n checkedAt: number;\n}\n\nasync function main() {\n // Check if cache is fresh\n try {\n const raw = readFileSync(CACHE_PATH, \"utf-8\");\n const cache = JSON.parse(raw) as UpdateCache;\n if (Date.now() - cache.checkedAt < ONE_DAY) {\n return; // Already checked recently\n }\n } catch {\n // No cache or invalid — proceed with check\n }\n\n const current: string = pkg.version;\n\n const res = await fetch(REGISTRY_URL, {\n signal: AbortSignal.timeout(5000),\n });\n\n if (!res.ok) return;\n\n const data = (await res.json()) as { version: string };\n const latest = data.version;\n\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n\n const cache: UpdateCache = { latest, current, checkedAt: Date.now() };\n writeFileSync(CACHE_PATH, JSON.stringify(cache), { encoding: \"utf-8\", mode: 0o600 });\n}\n\nmain().catch(() => {});\n","{\n \"name\": \"@tokenomist-ai/tokenomist-cli\",\n \"version\": \"0.1.1\",\n \"description\": \"CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, and buybacks from the terminal\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"tok\": \"dist/index.js\"\n },\n \"scripts\": {\n \"postinstall\": \"node scripts/postinstall.js\",\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.js\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src/ tests/\",\n \"lint:fix\": \"eslint src/ tests/ --fix\",\n \"format\": \"prettier --write 'src/**/*.ts' 'tests/**/*.ts'\",\n \"format:check\": \"prettier --check 'src/**/*.ts' 'tests/**/*.ts'\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"tokenomist\",\n \"crypto\",\n \"token\",\n \"unlock\",\n \"emission\",\n \"fundraising\",\n \"burn\",\n \"buyback\",\n \"cli\",\n \"api\"\n ],\n \"author\": {\n \"name\": \"tokenomist-ai\",\n \"email\": \"support@tokenomist.ai\",\n \"url\": \"https://tokenomist.ai\"\n },\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/tokenomist-ai/tokenomist-cli.git\"\n },\n \"homepage\": \"https://github.com/tokenomist-ai/tokenomist-cli#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/tokenomist-ai/tokenomist-cli/issues\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \"skills/**\",\n \"scripts/postinstall.js\",\n \"LICENSE\",\n \"README.md\"\n ],\n \"dependencies\": {\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^12.1.0\",\n \"dotenv\": \"^16.4.7\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.10.0\",\n \"eslint\": \"^9.16.0\",\n \"prettier\": \"^3.4.2\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"typescript-eslint\": \"^8.57.0\",\n \"vitest\": \"^3.2.4\"\n }\n}\n"],"mappings":";;;AAAA,SAAS,cAAc,eAAe,iBAAiB;AACvD,SAAS,YAAY;AACrB,SAAS,eAAe;;;ACFxB;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,IACT,aAAe;AAAA,IACf,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,cAAc;AAAA,IACd,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,QAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,gBAAkB;AAAA,EACpB;AAAA,EACA,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAU;AAAA,IACR,MAAQ;AAAA,IACR,OAAS;AAAA,IACT,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,EACX,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,MAAQ;AAAA,IACN,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,cAAc;AAAA,IACd,WAAa;AAAA,IACb,QAAU;AAAA,EACZ;AAAA,EACA,iBAAmB;AAAA,IACjB,eAAe;AAAA,IACf,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,EACZ;AACF;;;ADtEA,IAAM,aAAa,KAAK,QAAQ,GAAG,aAAa;AAChD,IAAM,aAAa,KAAK,YAAY,mBAAmB;AACvD,IAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,IAAM,eAAe;AAQrB,eAAe,OAAO;AAEpB,MAAI;AACF,UAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,UAAMA,SAAQ,KAAK,MAAM,GAAG;AAC5B,QAAI,KAAK,IAAI,IAAIA,OAAM,YAAY,SAAS;AAC1C;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,UAAkB,gBAAI;AAE5B,QAAM,MAAM,MAAM,MAAM,cAAc;AAAA,IACpC,QAAQ,YAAY,QAAQ,GAAI;AAAA,EAClC,CAAC;AAED,MAAI,CAAC,IAAI,GAAI;AAEb,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,SAAS,KAAK;AAEpB,YAAU,YAAY,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAEtD,QAAM,QAAqB,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,EAAE;AACpE,gBAAc,YAAY,KAAK,UAAU,KAAK,GAAG,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AACrF;AAEA,KAAK,EAAE,MAAM,MAAM;AAAC,CAAC;","names":["cache"]}
1
+ {"version":3,"sources":["../src/update-check.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst CONFIG_DIR = join(homedir(), \".tokenomist\");\nconst CACHE_PATH = join(CONFIG_DIR, \"update-check.json\");\nconst ONE_DAY = 24 * 60 * 60 * 1000;\nconst REGISTRY_URL = \"https://registry.npmjs.org/@tokenomist-ai%2Ftokenomist-cli/latest\";\n\ninterface UpdateCache {\n latest: string;\n current: string;\n checkedAt: number;\n}\n\nasync function main() {\n // Check if cache is fresh\n try {\n const raw = readFileSync(CACHE_PATH, \"utf-8\");\n const cache = JSON.parse(raw) as UpdateCache;\n if (Date.now() - cache.checkedAt < ONE_DAY) {\n return; // Already checked recently\n }\n } catch {\n // No cache or invalid — proceed with check\n }\n\n const current: string = pkg.version;\n\n const res = await fetch(REGISTRY_URL, {\n signal: AbortSignal.timeout(5000),\n });\n\n if (!res.ok) return;\n\n const data = (await res.json()) as { version: string };\n const latest = data.version;\n\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n\n const cache: UpdateCache = { latest, current, checkedAt: Date.now() };\n writeFileSync(CACHE_PATH, JSON.stringify(cache), { encoding: \"utf-8\", mode: 0o600 });\n}\n\nmain().catch(() => {});\n"],"mappings":";;;;;;AAAA,SAAS,cAAc,eAAe,iBAAiB;AACvD,SAAS,YAAY;AACrB,SAAS,eAAe;AAGxB,IAAM,aAAa,KAAK,QAAQ,GAAG,aAAa;AAChD,IAAM,aAAa,KAAK,YAAY,mBAAmB;AACvD,IAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,IAAM,eAAe;AAQrB,eAAe,OAAO;AAEpB,MAAI;AACF,UAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,UAAMA,SAAQ,KAAK,MAAM,GAAG;AAC5B,QAAI,KAAK,IAAI,IAAIA,OAAM,YAAY,SAAS;AAC1C;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,UAAkB,gBAAI;AAE5B,QAAM,MAAM,MAAM,MAAM,cAAc;AAAA,IACpC,QAAQ,YAAY,QAAQ,GAAI;AAAA,EAClC,CAAC;AAED,MAAI,CAAC,IAAI,GAAI;AAEb,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,SAAS,KAAK;AAEpB,YAAU,YAAY,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAEtD,QAAM,QAAqB,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,EAAE;AACpE,gBAAc,YAAY,KAAK,UAAU,KAAK,GAAG,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AACrF;AAEA,KAAK,EAAE,MAAM,MAAM;AAAC,CAAC;","names":["cache"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tokenomist-ai/tokenomist-cli",
3
- "version": "0.1.1",
4
- "description": "CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, and buybacks from the terminal",
3
+ "version": "0.2.0",
4
+ "description": "CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, buybacks, and point-in-time history from the terminal",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
@@ -65,7 +65,8 @@ tok allocation detail solana --output json
65
65
 
66
66
  ## Domain Context
67
67
 
68
- - Allocations are **point-in-time analyses**. They reflect the current understanding of token distribution and may be updated as new information becomes available.
68
+ - `tok allocation detail` reflects the **current** understanding of token distribution and may be updated as new information becomes available. To see the allocation as it was published at a past date or version, use `tok pit allocation <id> --as-of <date>` (see the `tokenomist-point-in-time` skill).
69
+ - `totalLockedAmount` is the sum of the Scheduled rows' `allocationLockedAmount`; it can differ slightly from `tok token list`'s token-level figure, which is computed at a different instant.
69
70
  - `standardAllocationName` enables cross-project comparison — different projects may use different names for similar allocations (e.g., "Core Contributors" vs "Team"), but the standard name normalizes this.
70
71
  - `totalTBDLockedAmount` represents tokens that are known to be locked but have no defined unlock schedule. Their classification may change as the project releases more information.
71
72
 
@@ -96,20 +96,23 @@ tok buyback detail aave --start 2024-01-01 --end 2024-12-31 --output json
96
96
 
97
97
  **Burn list:**
98
98
  - `totalBurnAmount` — total tokens burned for this token
99
+ - `totalBurnValue` — USD value of those burns (null if no burn has a price; `0` in `burn detail` when no burn is in the range)
99
100
 
100
101
  **Burn detail:**
101
102
  - `burns[].burnDate` — when the burn happened
102
103
  - `burns[].amount` — tokens burned
104
+ - `burns[].pricePerToken` / `burns[].value` — price and USD value at the burn
103
105
  - `burns[].burnType` — type of burn event
104
106
  - `burns[].metadata.burnReasons` — why tokens were burned
105
107
 
106
108
  **Buyback list:**
107
109
  - `totalBuybackAmount` — total tokens bought back
110
+ - `totalBuybackValue` — USD value of those buybacks (null if none has a price; `0` in `buyback detail` when no buyback is in the range)
108
111
 
109
112
  **Buyback detail:**
110
113
  - `buybacks[].buybackDate` — when the buyback happened
111
114
  - `buybacks[].tokenAmount` — tokens bought back
112
- - `buybacks[].value` — USD value of buyback
115
+ - `buybacks[].pricePerToken` / `buybacks[].value` — price and USD value of the buyback
113
116
  - `buybacks[].spentAmount` / `spentUnit` — what was spent (e.g. USDC)
114
117
 
115
118
  ## Analysis workflow
@@ -123,7 +126,8 @@ tok buyback detail aave --start 2024-01-01 --end 2024-12-31 --output json
123
126
 
124
127
  - A sequential buyback + burn is a **single** deflationary event, not two. Counting both would double-count the supply reduction.
125
128
  - Burns from **locked** supply don't reduce circulating supply — they reduce future potential supply instead.
126
- - The `startDate`/`endDate` filters on burn/buyback detail commands filter by **last activity date**, not the event date range. This is an API quirk — the filters determine which tokens to include based on when they last had activity.
129
+ - `--start`/`--end` on burn/buyback detail keep events dated from `start` 00:00 UTC to `end` 00:00 UTC (an event later on the `end` day is excluded). With either set, the totals are recomputed from the kept events; without them they are all-time.
130
+ - `burn list` / `buyback list` are paginated: the page position is printed to stderr (`Page 1/7 · 125 total`). Raise `--page-size` or walk `--page` to get every token.
127
131
 
128
132
  ## Workflow
129
133
 
@@ -66,6 +66,10 @@ tok emission weekly arbitrum --start 2024-01-01 --end 2024-06-30 --output json
66
66
  tok emission weekly arbitrum --standard-allocation "founderTeam" --output json
67
67
  ```
68
68
 
69
+ ## Pagination
70
+
71
+ List and series commands return one page (20 rows by default). The page position is printed to **stderr** — e.g. `Page 1/3 · 56 total · next: --page 2` — while stdout stays the JSON/CSV data. To get everything, raise `--page-size` or call again with `--page <n>` until the page equals the total pages. A page past the last returns the last page again, so never stop on "unchanged" data.
72
+
69
73
  ## Key output fields
70
74
 
71
75
  | Field | Description |
@@ -80,6 +80,10 @@ tok investor detail andreessen-horowitz --is-lead-investor --output json
80
80
  tok investor detail andreessen-horowitz --funding-date-min 2023-01-01 --raised-amount-min 5000000 --output json
81
81
  ```
82
82
 
83
+ ## Pagination
84
+
85
+ List and series commands return one page (20 rows by default). The page position is printed to **stderr** — e.g. `Page 1/3 · 56 total · next: --page 2` — while stdout stays the JSON/CSV data. To get everything, raise `--page-size` or call again with `--page <n>` until the page equals the total pages. A page past the last returns the last page again, so never stop on "unchanged" data.
86
+
83
87
  ## Key output fields
84
88
 
85
89
  **Token fundraising:**
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: tokenomist-point-in-time
3
+ description: See a token's tokenomics as published at a past version — allocations, daily emission and cliff unlocks as known on a given date. Use for history, audits, backtests, or explaining how a token's schedule changed over time.
4
+ metadata:
5
+ openclaw:
6
+ requires:
7
+ env:
8
+ - TOKENOMIST_API_KEY
9
+ bins:
10
+ - tok
11
+ primaryEnv: TOKENOMIST_API_KEY
12
+ install:
13
+ - kind: node
14
+ package: "@tokenomist-ai/tokenomist-cli"
15
+ bins: [tok]
16
+ allowed-tools: Bash(tok:*)
17
+ ---
18
+
19
+ # Skill: Point-in-Time History
20
+
21
+ See a token's tokenomics as it was published at a past version: the versions on its timeline, and its allocations, daily emission and cliff unlock events as known at a given instant.
22
+
23
+ ## When to use
24
+
25
+ - "What did the unlock schedule look like on 2024-01-01?" (backtests must not use data published later)
26
+ - "When and how did this token's tokenomics change?"
27
+ - Comparing two versions of a token's schedule.
28
+
29
+ For the **current** data, use the regular commands (`tok allocation detail`, `tok emission daily`, `tok unlock events`) — they include USD values, which point-in-time answers do not.
30
+
31
+ ## Commands
32
+
33
+ ### List versions
34
+ ```bash
35
+ tok pit versions <tokenId> --output json
36
+ ```
37
+
38
+ | Option | Description |
39
+ |--------|-------------|
40
+ | `--start <date>` | Keep versions valid from this day (YYYY-MM-DD) |
41
+ | `--end <date>` | Keep versions valid from up to this day (YYYY-MM-DD) |
42
+ | `--page <number>` | Page number |
43
+ | `--page-size <number>` | Items per page |
44
+
45
+ Each version has `id`, `historyOrder`, `status` (`current` / `previous`), `validFrom`, `validUntil`, `previousVersionId`, `change` (`category`, `title`, `description`) and `changeReferences` (sources).
46
+
47
+ ### Data at a version
48
+ ```bash
49
+ tok pit allocation <tokenId> --as-of 2024-01-01 --output json
50
+ tok pit daily-emission <tokenId> --as-of 2024-01-01 --start 2024-03-01 --end 2024-03-31 --output json
51
+ tok pit unlock-events <tokenId> --version-id <id> --output json
52
+ ```
53
+
54
+ | Option | Description |
55
+ |--------|-------------|
56
+ | `--as-of <instant>` | Answer as known at this instant: `YYYY-MM-DD` or RFC 3339 (`2024-07-01T12:00:00Z`) |
57
+ | `--version-id <id>` | Answer from this version (an `id` from `pit versions`) |
58
+ | `--start <date>` / `--end <date>` | Date window (daily-emission, unlock-events) |
59
+ | `--standard-allocation <names>` | `community`, `founderTeam`, `privateInvestors`, `publicInvestors`, `others`, `reserve` (comma-separated; daily-emission, unlock-events) |
60
+ | `--page <number>` / `--page-size <number>` | Pagination (daily-emission, unlock-events) |
61
+
62
+ Use `--as-of` **or** `--version-id`, never both. With neither, the current version answers.
63
+
64
+ ## Output (`--output json`)
65
+
66
+ `pit allocation`, `pit daily-emission` and `pit unlock-events`:
67
+
68
+ ```json
69
+ {
70
+ "asOf": "2024-01-01T00:00:00Z",
71
+ "version": { "id": "arbitrum-p-…", "historyOrder": 2, "validFrom": "…", "validUntil": "…", "status": "previous" },
72
+ "data": { },
73
+ "pagination": { "page": 1, "totalPages": 3, "pageSize": 20, "total": 45 }
74
+ }
75
+ ```
76
+
77
+ `pagination` is present on paginated commands only. `pit versions` returns `{ "data", "pagination" }` (no `asOf`/`version`). Walk `--page` until `page` equals `totalPages`.
78
+
79
+ ## Domain Context
80
+
81
+ - **No USD fields**: point-in-time answers carry amounts only (no `unlockValue`, `cliffValue`, `referencePrice`, `valueToMarketCap`).
82
+ - `pit daily-emission` is the **complete supply inflow** per day (cliff + linear) and keeps `totalCumulativeUnlockedAmount` as a running total. `pit unlock-events` is **cliff events only**. Never add the two over the same window (double-counts every cliff).
83
+ - Never sum or mix figures across versions; each answer is one version's view.
84
+ - Committed claims are kept only when timestamped at or before `asOf`.
85
+
86
+ ## Errors
87
+
88
+ | Message | Meaning |
89
+ |---------|---------|
90
+ | `FORBIDDEN: Forbidden` | The plan has no point-in-time access (API, ELITE or TEAM required). |
91
+ | `FORBIDDEN (PLAN_NOT_ELIGIBLE)` | `--as-of` is earlier than the plan allows; the message names the plan's range. `Earliest valid date:` (when present) is the first instant inside that range with a version. |
92
+ | `… (NO_VERSION_AT_AS_OF)` | The token had no version yet at `--as-of`. `Earliest valid date:` names the first instant with one. |
93
+ | `… (VERSION_NOT_FOUND)` | Unknown `--version-id` for this token. |
94
+ | `… (INVALID_AS_OF)` | Malformed or future `--as-of`. |
95
+ | `… (TOKEN_NOT_FOUND)` | Unknown token ID — resolve it with `tok token search <name>`. |
@@ -91,6 +91,10 @@ Options:
91
91
  tok unlock events solana --start 2025-01-01 --end 2025-12-31 --output json
92
92
  ```
93
93
 
94
+ ## Pagination
95
+
96
+ List and series commands return one page (20 rows by default). The page position is printed to **stderr** — e.g. `Page 1/3 · 56 total · next: --page 2` — while stdout stays the JSON/CSV data. To get everything, raise `--page-size` or call again with `--page <n>` until the page equals the total pages. A page past the last returns the last page again, so never stop on "unchanged" data.
97
+
94
98
  ## Key output fields
95
99
 
96
100
  **unlock list / upcoming:**