leek-box-cli 0.1.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +213 -0
  3. package/dist/cli.mjs +161 -0
  4. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ <p align="right">
2
+ <strong>English</strong> | <a href="README-zh.md">中文</a>
3
+ </p>
4
+
5
+ # leek-box-cli(韭菜盒子)
6
+
7
+ > An interactive terminal stock watchlist dashboard built with [Ink](https://github.com/vadimdemedes/ink).
8
+
9
+ ## Screenshots
10
+
11
+ ### Stock Watchlist
12
+
13
+ <p align="center">
14
+ <img src="scrennshots/stock-list.png" alt="Stock watchlist dashboard" width="100%">
15
+ </p>
16
+
17
+ ### Menu & Settings
18
+
19
+ <table>
20
+ <tr>
21
+ <td align="center" width="50%"><strong>Menu</strong></td>
22
+ <td align="center" width="50%"><strong>Settings</strong></td>
23
+ </tr>
24
+ <tr>
25
+ <td><img src="scrennshots/dialog-menu.png" alt="Menu dialog"></td>
26
+ <td><img src="scrennshots/settings.png" alt="Settings screen"></td>
27
+ </tr>
28
+ </table>
29
+
30
+ ### Manage Watchlist
31
+
32
+ <table>
33
+ <tr>
34
+ <td align="center" width="50%"><strong>Add Stock</strong></td>
35
+ <td align="center" width="50%"><strong>Remove Stock</strong></td>
36
+ </tr>
37
+ <tr>
38
+ <td><img src="scrennshots/stock-add.png" alt="Add a stock to the watchlist"></td>
39
+ <td><img src="scrennshots/stock-remove.png" alt="Remove a stock from the watchlist"></td>
40
+ </tr>
41
+ </table>
42
+
43
+ ### Stock Details
44
+
45
+ <table>
46
+ <tr>
47
+ <td align="center" width="50%"><strong>Intraday</strong></td>
48
+ <td align="center" width="50%"><strong>Five-day</strong></td>
49
+ </tr>
50
+ <tr>
51
+ <td><img src="scrennshots/dialog-stock-detail-intraday.png" alt="Intraday stock chart"></td>
52
+ <td><img src="scrennshots/dialog-stock-detail-five-day.png" alt="Five-day stock chart"></td>
53
+ </tr>
54
+ <tr>
55
+ <td align="center" width="50%"><strong>Daily</strong></td>
56
+ <td align="center" width="50%"><strong>Weekly</strong></td>
57
+ </tr>
58
+ <tr>
59
+ <td><img src="scrennshots/dialog-stock-detail-day.png" alt="Daily stock chart"></td>
60
+ <td><img src="scrennshots/dialog-stock-detail-week.png" alt="Weekly stock chart"></td>
61
+ </tr>
62
+ <tr>
63
+ <td align="center" width="50%"><strong>Monthly</strong></td>
64
+ <td align="center" width="50%"><strong>Yearly</strong></td>
65
+ </tr>
66
+ <tr>
67
+ <td><img src="scrennshots/dialog-stock-detail-month.png" alt="Monthly stock chart"></td>
68
+ <td><img src="scrennshots/dialog-stock-detail-year.png" alt="Yearly stock chart"></td>
69
+ </tr>
70
+ </table>
71
+
72
+ ## Features
73
+
74
+ - **Real-time dashboard**: Displays the latest price, percentage change, price change, open, high, low, volume, turnover, turnover rate, and total market capitalization for every stock in your watchlist. Refreshes every 5 seconds by default.
75
+ - **Row selection and details**: Use `↑`/`↓` to select a stock and `enter` to open its quote details and trend chart. Press `1`-`6` to switch between intraday, five-day, daily, weekly, monthly, and yearly views.
76
+ - **Multiple time frames**: Intraday and five-day minute charts refresh every 30 seconds. Daily, weekly, monthly, and yearly charts refresh every 5 minutes.
77
+ - **Refresh controls**: Press `r` to refresh immediately. Configure the automatic refresh interval in Settings in 500 ms increments, from 1 to 60 seconds.
78
+ - **Watchlist management**: Add or remove Shanghai, Shenzhen, and Beijing A-shares and ETFs. Stock codes can be entered as `600000`, `sh600000`, `600000.SH`, and other common formats.
79
+ - **Resilient display**: Suspended stocks, incomplete quotes, and refresh failures each have a dedicated state. The display recovers automatically after a later poll succeeds.
80
+
81
+ ## Controls
82
+
83
+ - `esc`: Open the menu. If stock details are open, close them first; if the menu is open, close it.
84
+ - In the menu, use `↑`/`↓`, `enter`, or a number key to select a page.
85
+ - In the dashboard, use `↑`/`↓`, `enter`, and `r`.
86
+ - In Settings, use `↑`/`↓` to select an item and `←`/`→` or `enter` to adjust it.
87
+ - In stock details, press `1`-`6` to switch between `Intraday`, `Five-day`, `Daily`, `Weekly`, `Monthly`, and `Yearly`.
88
+ - `q`: Exit when no menu or stock details overlay is open. It does nothing while an overlay is open to prevent accidental exits.
89
+ - The right side of the status bar displays `YYYY-MM-DD HH:MM:SS` in the Asia/Shanghai time zone.
90
+
91
+ ## Requirements
92
+
93
+ - [Node.js](https://nodejs.org/) >= 22.19.0 (or >= 24)
94
+ - [pnpm](https://pnpm.io/) >= 11.0.0
95
+
96
+ Market data is retrieved with the native Node.js `fetch` API, with no external runtime dependency such as curl.
97
+
98
+ ## Market Data Sources
99
+
100
+ - Real-time quotes: Tencent quote API at `https://qt.gtimg.cn/q=...`; GBK-encoded and requires no authentication.
101
+ - Intraday data: Tencent minute API at `https://web.ifzq.gtimg.cn/appstock/app/minute/query?code=...`.
102
+ - Five-day data: Tencent multi-day minute API at `https://web.ifzq.gtimg.cn/appstock/app/day/query?code=...`.
103
+ - Daily, weekly, and monthly data: Tencent forward-adjusted K-line API at `https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=...`.
104
+ - Yearly data: Aggregated locally by year from backward-adjusted monthly data returned by the same API.
105
+ - Data timeliness and availability depend on the upstream APIs. This project is intended for personal display purposes only.
106
+
107
+ ## Installation and Usage
108
+
109
+ ### Install globally (recommended)
110
+
111
+ ```bash
112
+ npm install -g leek-box-cli
113
+ # or
114
+ pnpm add -g leek-box-cli
115
+ # or
116
+ yarn global add leek-box-cli
117
+ ```
118
+
119
+ Then run it from anywhere:
120
+
121
+ ```bash
122
+ leek-box-cli
123
+ ```
124
+
125
+ > Requires Node.js 22.19+ (or 24+) on the machine that runs the command.
126
+
127
+ Alternatively, run it once without installing:
128
+
129
+ ```bash
130
+ npx leek-box-cli
131
+ # or
132
+ pnpm dlx leek-box-cli
133
+ ```
134
+
135
+ ### Run from source
136
+
137
+ ```bash
138
+ pnpm install
139
+
140
+ # Development mode
141
+ pnpm dev
142
+
143
+ # Build and run
144
+ pnpm build
145
+ pnpm preview
146
+ ```
147
+
148
+ You can also select the initial page with a subcommand:
149
+
150
+ ```bash
151
+ leek-box-cli # Stock watchlist dashboard
152
+ leek-box-cli stock-list # Same as above
153
+ leek-box-cli stock-add # Add a stock to the watchlist
154
+ leek-box-cli stock-remove # Remove a stock from the watchlist
155
+ leek-box-cli -v # Show version information
156
+ leek-box-cli -h # Show help
157
+ ```
158
+
159
+ ## Settings and Watchlist Storage
160
+
161
+ Settings and the watchlist are stored together at `$XDG_CONFIG_HOME/leek-box-cli/settings.json`. If `XDG_CONFIG_HOME` is not set, `~/.config/leek-box-cli/settings.json` is used.
162
+
163
+ File structure:
164
+
165
+ ```json
166
+ {
167
+ "theme": {
168
+ "preset": "classic",
169
+ "trendColorMode": "red-up",
170
+ "borderStyle": "round"
171
+ },
172
+ "request": {
173
+ "timeoutMs": 8000,
174
+ "minimumDurationMs": 0,
175
+ "quotePollIntervalMs": 5000,
176
+ "minuteChartPollIntervalMs": 30000,
177
+ "klinePollIntervalMs": 300000
178
+ },
179
+ "stocks": [
180
+ {
181
+ "code": "sh600000",
182
+ "name": "浦发银行",
183
+ "addedAt": "2026-08-20T00:00:00.000Z"
184
+ }
185
+ ]
186
+ }
187
+ ```
188
+
189
+ The application reloads the file every time it refreshes the dashboard, so valid external edits take effect on the next refresh. It validates the `theme` and `request` fields, as well as each stock's `code`, `name`, `addedAt`, and duplicate codes when reading. Writes use an inter-process lock and atomic temporary-file replacement to prevent lost concurrent updates and partial JSON files.
190
+
191
+ ## Development Scripts
192
+
193
+ | Command | Description |
194
+ | ----------------- | ---------------------------------------- |
195
+ | `pnpm dev` | Run the source code with tsx |
196
+ | `pnpm build` | Build `dist/cli.mjs` with Vite |
197
+ | `pnpm preview` | Run the build output |
198
+ | `pnpm test` | Run tests with Vitest |
199
+ | `pnpm typecheck` | Run TypeScript type checking |
200
+ | `pnpm lint` | Run the linter and apply automatic fixes |
201
+ | `pnpm lint:check` | Run the linter without modifying files |
202
+ | `pnpm fmt` | Format the code |
203
+ | `pnpm fmt:check` | Check code formatting |
204
+
205
+ ## Tech Stack
206
+
207
+ - TypeScript / ESM
208
+ - Ink 7 + React 19
209
+ - Zustand 5
210
+ - meow
211
+ - Vite
212
+ - oxlint / oxfmt
213
+ - Vitest