cc-peak-hours 1.0.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/pull_request_template.md +19 -0
- package/.github/workflows/ci.yml +58 -0
- package/CHANGELOG.md +19 -0
- package/CODE_OF_CONDUCT.md +41 -0
- package/CONTRIBUTING.md +9 -0
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/SECURITY.md +33 -0
- package/assets/full-en.svg +7 -0
- package/assets/full-fr.svg +7 -0
- package/assets/gen-svg.sh +94 -0
- package/assets/minimal-offpeak-en.svg +4 -0
- package/assets/minimal-offpeak-fr.svg +4 -0
- package/bin/install.js +159 -0
- package/bin/statusline.sh +557 -0
- package/docs/superpowers/plans/2026-03-31-claude-peak-hours.md +1115 -0
- package/docs/superpowers/specs/2026-03-31-claude-peak-hours-design.md +232 -0
- package/package.json +21 -0
- package/peak-hours.json +6 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report something that isn't working
|
|
4
|
+
title: ''
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Describe the bug
|
|
10
|
+
|
|
11
|
+
<!-- A clear description of what's wrong -->
|
|
12
|
+
|
|
13
|
+
## Expected behavior
|
|
14
|
+
|
|
15
|
+
<!-- What should happen -->
|
|
16
|
+
|
|
17
|
+
## Environment
|
|
18
|
+
|
|
19
|
+
- **OS**: <!-- macOS / Linux distro -->
|
|
20
|
+
- **Shell**: <!-- bash version (`bash --version`) -->
|
|
21
|
+
- **Mode**: <!-- minimal / full -->
|
|
22
|
+
- **Flags**: <!-- e.g. --24h --lang fr -->
|
|
23
|
+
- **jq version**: <!-- `jq --version` -->
|
|
24
|
+
|
|
25
|
+
## Steps to reproduce
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Paste the command you ran
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Output
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
# Paste the output or screenshot
|
|
35
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an improvement
|
|
4
|
+
title: ''
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
<!-- What problem does this solve? -->
|
|
12
|
+
|
|
13
|
+
## Proposed solution
|
|
14
|
+
|
|
15
|
+
<!-- How would you like it to work? -->
|
|
16
|
+
|
|
17
|
+
## Alternatives considered
|
|
18
|
+
|
|
19
|
+
<!-- Any other approaches you thought of? -->
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? -->
|
|
4
|
+
|
|
5
|
+
## Type of change
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fix
|
|
8
|
+
- [ ] New feature
|
|
9
|
+
- [ ] Peak hours config update (`peak-hours.json`)
|
|
10
|
+
- [ ] Documentation
|
|
11
|
+
- [ ] Other
|
|
12
|
+
|
|
13
|
+
## Test plan
|
|
14
|
+
|
|
15
|
+
- [ ] Tested minimal mode
|
|
16
|
+
- [ ] Tested full mode
|
|
17
|
+
- [ ] Tested both languages (en/fr)
|
|
18
|
+
- [ ] Tested both time formats (12h/24h)
|
|
19
|
+
- [ ] Tested with empty stdin (`echo '{}' | bash bin/statusline.sh`)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: ShellCheck statusline.sh
|
|
17
|
+
uses: ludeeus/action-shellcheck@2.0.0
|
|
18
|
+
with:
|
|
19
|
+
scandir: bin
|
|
20
|
+
severity: warning
|
|
21
|
+
|
|
22
|
+
- name: Validate peak-hours.json
|
|
23
|
+
run: jq empty peak-hours.json
|
|
24
|
+
|
|
25
|
+
- name: Validate package.json
|
|
26
|
+
run: node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))"
|
|
27
|
+
|
|
28
|
+
- name: Check install.js syntax
|
|
29
|
+
run: node --check bin/install.js
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
name: Integration test
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Install jq
|
|
38
|
+
run: sudo apt-get install -y jq
|
|
39
|
+
|
|
40
|
+
- name: Test minimal mode (EN, 12h)
|
|
41
|
+
run: |
|
|
42
|
+
output=$(echo '{"model":{"display_name":"Opus 4.6"},"context_window":{"context_window_size":200000,"current_usage":{"input_tokens":78000,"cache_creation_input_tokens":0,"cache_read_input_tokens":0}}}' | bash bin/statusline.sh --lang en --12h)
|
|
43
|
+
[ -n "$output" ] && echo "PASS: minimal EN" || (echo "FAIL: no output" && exit 1)
|
|
44
|
+
|
|
45
|
+
- name: Test minimal mode (FR, 24h)
|
|
46
|
+
run: |
|
|
47
|
+
output=$(echo '{}' | bash bin/statusline.sh --lang fr --24h)
|
|
48
|
+
[ -n "$output" ] && echo "PASS: minimal FR" || (echo "FAIL: no output" && exit 1)
|
|
49
|
+
|
|
50
|
+
- name: Test full mode
|
|
51
|
+
run: |
|
|
52
|
+
output=$(echo '{}' | bash bin/statusline.sh --full --lang en --24h)
|
|
53
|
+
[ -n "$output" ] && echo "PASS: full mode" || (echo "FAIL: no output" && exit 1)
|
|
54
|
+
|
|
55
|
+
- name: Test empty stdin
|
|
56
|
+
run: |
|
|
57
|
+
output=$(echo '{}' | bash bin/statusline.sh)
|
|
58
|
+
[ -n "$output" ] && echo "PASS: empty stdin" || (echo "FAIL: no output" && exit 1)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-03-31
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Minimal mode: single-line statusline with model, context %, peak status, and countdown
|
|
13
|
+
- Full mode (`--full`): dashboard with visual timeline bar and real-time rate limits via OAuth API
|
|
14
|
+
- Remote config (`peak-hours.json`): peak hours loaded from GitHub, cached 1h, hardcoded fallback
|
|
15
|
+
- Multi-window support: multiple peak windows per day, midnight-crossing windows
|
|
16
|
+
- Localization: English (default) and French (`--lang fr`), auto-detected from locale
|
|
17
|
+
- Time format: 12h/24h (`--12h`/`--24h`), auto-detected from locale
|
|
18
|
+
- Node installer (`npx claude-peak-hours`): backup, install, uninstall, flag forwarding
|
|
19
|
+
- macOS and Linux support (GNU coreutils + BSD date)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Using welcoming and inclusive language
|
|
17
|
+
- Being respectful of differing viewpoints and experiences
|
|
18
|
+
- Gracefully accepting constructive criticism
|
|
19
|
+
- Focusing on what is best for the community
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behavior:
|
|
22
|
+
|
|
23
|
+
- The use of sexualized language or imagery and unwelcome sexual attention
|
|
24
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
25
|
+
- Public or private harassment
|
|
26
|
+
- Publishing others' private information without explicit permission
|
|
27
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
28
|
+
|
|
29
|
+
## Enforcement
|
|
30
|
+
|
|
31
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
32
|
+
reported by opening a [private security advisory](https://github.com/nickywan/claude-peak-hours/security/advisories/new)
|
|
33
|
+
or contacting the project maintainer directly.
|
|
34
|
+
|
|
35
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
36
|
+
|
|
37
|
+
## Attribution
|
|
38
|
+
|
|
39
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/),
|
|
40
|
+
version 2.1, available at
|
|
41
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
This project is **not open to external contributions**. Issues and pull requests from outside contributors will be closed.
|
|
4
|
+
|
|
5
|
+
If you've found a bug, you're welcome to [open an issue](https://github.com/nickywan/claude-peak-hours/issues) to report it — but fixes are handled internally.
|
|
6
|
+
|
|
7
|
+
If you've noticed that Anthropic changed their peak hours, please [open an issue](https://github.com/nickywan/claude-peak-hours/issues) with the source and we'll update the config.
|
|
8
|
+
|
|
9
|
+
For security issues, see [SECURITY.md](SECURITY.md).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nickywan
|
|
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,124 @@
|
|
|
1
|
+
# claude-peak-hours
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[]()
|
|
5
|
+
[](https://github.com/nickywan/claude-peak-hours/actions)
|
|
6
|
+
|
|
7
|
+
A [Claude Code](https://claude.ai/code) statusline plugin that shows whether you're in **peak** or **off-peak** hours, with a countdown to the next transition.
|
|
8
|
+
|
|
9
|
+
During peak hours (12:00-18:00 UTC / 8AM-2PM ET on weekdays), Anthropic applies stricter session limits and tokens are consumed faster. This statusline shows you exactly when you're in peak, when it changes, and helps you plan your usage.
|
|
10
|
+
|
|
11
|
+
Inspired by [isclaude-2x](https://github.com/Adiazgallici/isclaude-2x).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx cc-peak-hours
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Restart Claude Code after installing.
|
|
20
|
+
|
|
21
|
+
### Options
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx cc-peak-hours # minimal (default)
|
|
25
|
+
npx cc-peak-hours --full # dashboard with timeline + rate limits
|
|
26
|
+
npx cc-peak-hours --24h # force 24h time format
|
|
27
|
+
npx cc-peak-hours --12h # force 12h time format
|
|
28
|
+
npx cc-peak-hours --lang fr # French labels
|
|
29
|
+
npx cc-peak-hours --full --24h --lang fr # combined
|
|
30
|
+
npx cc-peak-hours --uninstall # restore previous statusline
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Modes
|
|
34
|
+
|
|
35
|
+
### Minimal (default)
|
|
36
|
+
|
|
37
|
+
One line. Everything you need at a glance.
|
|
38
|
+
|
|
39
|
+
**Off-peak (French, 24h):**
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
**Off-peak (English, 12h):**
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
Shows: model name, current directory, context remaining %, peak status with countdown.
|
|
48
|
+
|
|
49
|
+
### Full (`--full`)
|
|
50
|
+
|
|
51
|
+
Dashboard with visual timeline and real-time rate limits.
|
|
52
|
+
|
|
53
|
+
**Full mode (French, 24h):**
|
|
54
|
+
|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
**Full mode (English, 12h):**
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
The timeline bar shows your full day in local time -- green for off-peak hours, yellow for peak hours, and a white dot for where you are now.
|
|
62
|
+
|
|
63
|
+
Rate limits (session 5h + weekly) are read directly from Claude Code -- no extra API calls, zero latency.
|
|
64
|
+
|
|
65
|
+
## Localization
|
|
66
|
+
|
|
67
|
+
Supports English (default) and French. Auto-detected from your locale, or forced with `--lang`.
|
|
68
|
+
|
|
69
|
+
## Time format
|
|
70
|
+
|
|
71
|
+
Auto-detected from locale (French -> 24h, English -> 12h), or forced with `--24h` / `--12h`.
|
|
72
|
+
|
|
73
|
+
## Remote config
|
|
74
|
+
|
|
75
|
+
Peak hours are loaded from a [remote config file](peak-hours.json) on this repo, cached locally for 1 hour. If Anthropic changes peak hours, updating this file updates all users automatically -- no plugin update needed.
|
|
76
|
+
|
|
77
|
+
Falls back to hardcoded defaults (Mon-Fri 12:00-18:00 UTC) if the fetch fails.
|
|
78
|
+
|
|
79
|
+
### Config format
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"version": 2,
|
|
84
|
+
"peak_windows": [
|
|
85
|
+
{ "days": [1, 2, 3, 4, 5], "start_utc": 12, "end_utc": 18 }
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
All times are in UTC. Multiple windows supported. `end_utc` < `start_utc` means the window crosses midnight.
|
|
91
|
+
|
|
92
|
+
## How it works
|
|
93
|
+
|
|
94
|
+
- Loads peak hours config from GitHub (cached 1h, hardcoded fallback)
|
|
95
|
+
- All peak calculations done in **UTC** -- no DST ambiguity
|
|
96
|
+
- Converts to your local timezone for display
|
|
97
|
+
- Rate limits read directly from Claude Code stdin (no network calls)
|
|
98
|
+
- Supports multiple peak windows and midnight-crossing windows
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
- **macOS or Linux**
|
|
103
|
+
- **Node.js** -- for the installer only
|
|
104
|
+
- **jq** -- `brew install jq` or `sudo apt install jq`
|
|
105
|
+
- **curl** -- pre-installed on most systems
|
|
106
|
+
|
|
107
|
+
## Contributing
|
|
108
|
+
|
|
109
|
+
This project is not open to external contributions. See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
110
|
+
|
|
111
|
+
If you notice Anthropic changed their peak hours, please [open an issue](https://github.com/nickywan/claude-peak-hours/issues) and we'll update the config.
|
|
112
|
+
|
|
113
|
+
## Security
|
|
114
|
+
|
|
115
|
+
This is a read-only statusline plugin. It does **not**:
|
|
116
|
+
- Send your data anywhere (except fetching the public config from this repo)
|
|
117
|
+
- Store credentials (it reads existing Claude Code data from stdin)
|
|
118
|
+
- Modify your code or files (except `~/.claude/settings.json` and `~/.claude/statusline.sh` during install)
|
|
119
|
+
|
|
120
|
+
If you find a security issue, please open a [private security advisory](https://github.com/nickywan/claude-peak-hours/security/advisories/new) instead of a public issue.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
[MIT](LICENSE)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This is a read-only Claude Code statusline plugin. It:
|
|
6
|
+
|
|
7
|
+
- Reads Claude Code's stdin JSON (model info, context window)
|
|
8
|
+
- Fetches a public JSON config from this GitHub repo
|
|
9
|
+
- Fetches usage data from Anthropic's official OAuth API using your existing Claude Code tokens
|
|
10
|
+
- Writes cached data to `/tmp/claude/`
|
|
11
|
+
|
|
12
|
+
It does **not** store credentials, transmit your data to third parties, or modify your code.
|
|
13
|
+
|
|
14
|
+
## Supported Versions
|
|
15
|
+
|
|
16
|
+
| Version | Supported |
|
|
17
|
+
|---------|-----------|
|
|
18
|
+
| 1.x | Yes |
|
|
19
|
+
|
|
20
|
+
## Reporting a Vulnerability
|
|
21
|
+
|
|
22
|
+
If you discover a security issue, **do not open a public issue**.
|
|
23
|
+
|
|
24
|
+
Instead, please use [GitHub's private security advisory feature](https://github.com/nickywan/claude-peak-hours/security/advisories/new) to report it confidentially.
|
|
25
|
+
|
|
26
|
+
You can expect an initial response within 48 hours.
|
|
27
|
+
|
|
28
|
+
## What Counts as a Security Issue
|
|
29
|
+
|
|
30
|
+
- The plugin sending data to unexpected endpoints
|
|
31
|
+
- Credential leakage (OAuth tokens exposed in logs, cache files with wrong permissions, etc.)
|
|
32
|
+
- Code injection via the remote `peak-hours.json` config
|
|
33
|
+
- Any behavior that could compromise the user's system or Claude Code session
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="950" height="108">
|
|
2
|
+
<rect width="100%" height="100%" rx="8" fill="#1e1e1e"/>
|
|
3
|
+
<text x="14" y="30" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(0,153,255)" font-weight="normal" opacity="1">Opus 4.6 (1M context)</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(86,182,194)" font-weight="normal" opacity="1">~/.../claude/plugin/claude-peak-hours</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">87% free</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="bold" opacity="1">⚡ Off-peak</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">~</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(255,85,85)" font-weight="normal" opacity="1">Peak 2:00pm</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">(12h30m)</tspan></text>
|
|
4
|
+
<text x="14" y="50" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"></text>
|
|
5
|
+
<text x="14" y="70" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">today</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(220,220,220)" font-weight="bold" opacity="1">●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> Off-peak</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> Peak 2pm-8pm</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="bold" opacity="1">●</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> now</tspan></text>
|
|
6
|
+
<text x="14" y="90" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">current</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">●●●●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="0.55">○○○○○○</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1"> 42%</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">⟳</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">10:00am</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">weekly</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">●●●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="0.55">○○○○○○○</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1"> 31%</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">⟳</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">apr 3, 5:00pm</tspan></text>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="950" height="108">
|
|
2
|
+
<rect width="100%" height="100%" rx="8" fill="#1e1e1e"/>
|
|
3
|
+
<text x="14" y="30" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(0,153,255)" font-weight="normal" opacity="1">Opus 4.6 (1M context)</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(86,182,194)" font-weight="normal" opacity="1">~/.../claude/plugin/claude-peak-hours</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">87% free</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="bold" opacity="1">⚡ Hors pointe</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">~</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(255,85,85)" font-weight="normal" opacity="1">Pointe 14:00</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">(12h30m)</tspan></text>
|
|
4
|
+
<text x="14" y="50" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"></text>
|
|
5
|
+
<text x="14" y="70" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">auj.</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(220,220,220)" font-weight="bold" opacity="1">●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> Hors pointe</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(230,200,0)" font-weight="normal" opacity="1">━</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> Pointe 14:00-20:00</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="bold" opacity="1">●</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55"> maint.</tspan></text>
|
|
6
|
+
<text x="14" y="90" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">session</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">●●●●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="0.55">○○○○○○</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1"> 42%</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">⟳</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">10:00</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">hebdo</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">●●●</tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="0.55">○○○○○○○</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1"> 31%</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">⟳</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(220,220,220)" font-weight="normal" opacity="1">avr 3, 17:00</tspan></text>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Generate SVG screenshots from statusline ANSI output
|
|
3
|
+
# Usage: bash assets/gen-svg.sh
|
|
4
|
+
|
|
5
|
+
cd "$(dirname "$0")/.."
|
|
6
|
+
|
|
7
|
+
MOCK_INPUT='{"model":{"display_name":"Opus 4.6 (1M context)"},"cwd":"/home/nickywan/dev/projects/claude/plugin/claude-peak-hours","context_window":{"remaining_percentage":87},"rate_limits":{"five_hour":{"used_percentage":42,"resets_at":1774944000},"seven_day":{"used_percentage":31,"resets_at":1775228400}}}'
|
|
8
|
+
|
|
9
|
+
ansi_to_svg() {
|
|
10
|
+
local output_file="$1"
|
|
11
|
+
local width="${2:-950}"
|
|
12
|
+
shift 2
|
|
13
|
+
# Remaining args are lines of ANSI text
|
|
14
|
+
local lines=("$@")
|
|
15
|
+
|
|
16
|
+
node -e '
|
|
17
|
+
const lines = JSON.parse(process.argv[1]);
|
|
18
|
+
const width = parseInt(process.argv[2]);
|
|
19
|
+
const outFile = process.argv[3];
|
|
20
|
+
|
|
21
|
+
const lineHeight = 20;
|
|
22
|
+
const padY = 14;
|
|
23
|
+
const padX = 14;
|
|
24
|
+
const totalHeight = padY * 2 + lines.length * lineHeight;
|
|
25
|
+
|
|
26
|
+
function parseAnsi(text) {
|
|
27
|
+
let spans = "";
|
|
28
|
+
let color = "#d4d4d4";
|
|
29
|
+
let isBold = false;
|
|
30
|
+
let isDim = false;
|
|
31
|
+
|
|
32
|
+
const parts = text.split(/(\x1b\[[0-9;]*m)/);
|
|
33
|
+
for (const part of parts) {
|
|
34
|
+
if (part.startsWith("\x1b[")) {
|
|
35
|
+
const code = part.slice(2, -1);
|
|
36
|
+
if (code === "0") { color = "#d4d4d4"; isBold = false; isDim = false; continue; }
|
|
37
|
+
if (code === "1") { isBold = true; continue; }
|
|
38
|
+
if (code === "2") { isDim = true; continue; }
|
|
39
|
+
const m = code.match(/^38;2;(\d+);(\d+);(\d+)$/);
|
|
40
|
+
if (m) { color = `rgb(${m[1]},${m[2]},${m[3]})`; continue; }
|
|
41
|
+
} else if (part.length > 0) {
|
|
42
|
+
const esc = part.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
|
43
|
+
const op = isDim ? "0.55" : "1";
|
|
44
|
+
const fw = isBold ? "bold" : "normal";
|
|
45
|
+
spans += `<tspan fill="${color}" font-weight="${fw}" opacity="${op}">${esc}</tspan>`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return spans;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let textEls = "";
|
|
52
|
+
for (let i = 0; i < lines.length; i++) {
|
|
53
|
+
const y = padY + (i + 1) * lineHeight - 4;
|
|
54
|
+
textEls += `<text x="${padX}" y="${y}" font-family="Menlo,Monaco,Consolas,\x27Courier New\x27,monospace" font-size="13" fill="#d4d4d4">${parseAnsi(lines[i])}</text>\n`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${totalHeight}">
|
|
58
|
+
<rect width="100%" height="100%" rx="8" fill="#1e1e1e"/>
|
|
59
|
+
${textEls}</svg>`;
|
|
60
|
+
|
|
61
|
+
require("fs").writeFileSync(outFile, svg);
|
|
62
|
+
console.log("Generated:", outFile, `(${lines.length} lines, ${width}x${totalHeight})`);
|
|
63
|
+
' "$(printf '%s\n' "${lines[@]}" | jq -R . | jq -s .)" "$width" "$output_file"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
echo "=== Generating SVG screenshots ==="
|
|
67
|
+
|
|
68
|
+
# Minimal off-peak FR 24h
|
|
69
|
+
echo "1/4: minimal off-peak (FR, 24h)"
|
|
70
|
+
output=$(echo "$MOCK_INPUT" | bash bin/statusline.sh --24h --lang fr 2>/dev/null)
|
|
71
|
+
ansi_to_svg "assets/minimal-offpeak-fr.svg" 950 "$output"
|
|
72
|
+
|
|
73
|
+
# Minimal off-peak EN 12h
|
|
74
|
+
echo "2/4: minimal off-peak (EN, 12h)"
|
|
75
|
+
output=$(echo "$MOCK_INPUT" | bash bin/statusline.sh --12h --lang en 2>/dev/null)
|
|
76
|
+
ansi_to_svg "assets/minimal-offpeak-en.svg" 950 "$output"
|
|
77
|
+
|
|
78
|
+
# Full mode FR 24h
|
|
79
|
+
echo "3/4: full mode (FR, 24h)"
|
|
80
|
+
full_output=$(echo "$MOCK_INPUT" | bash bin/statusline.sh --full --24h --lang fr 2>/dev/null)
|
|
81
|
+
line1=$(echo "$full_output" | sed -n '1p')
|
|
82
|
+
line2=$(echo "$full_output" | sed -n '3p')
|
|
83
|
+
line3=$(echo "$full_output" | sed -n '4p')
|
|
84
|
+
ansi_to_svg "assets/full-fr.svg" 950 "$line1" "" "$line2" "$line3"
|
|
85
|
+
|
|
86
|
+
# Full mode EN 12h
|
|
87
|
+
echo "4/4: full mode (EN, 12h)"
|
|
88
|
+
full_output=$(echo "$MOCK_INPUT" | bash bin/statusline.sh --full --12h --lang en 2>/dev/null)
|
|
89
|
+
line1=$(echo "$full_output" | sed -n '1p')
|
|
90
|
+
line2=$(echo "$full_output" | sed -n '3p')
|
|
91
|
+
line3=$(echo "$full_output" | sed -n '4p')
|
|
92
|
+
ansi_to_svg "assets/full-en.svg" 950 "$line1" "" "$line2" "$line3"
|
|
93
|
+
|
|
94
|
+
echo "=== Done ==="
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="950" height="48">
|
|
2
|
+
<rect width="100%" height="100%" rx="8" fill="#1e1e1e"/>
|
|
3
|
+
<text x="14" y="30" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(0,153,255)" font-weight="normal" opacity="1">Opus 4.6 (1M context)</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(86,182,194)" font-weight="normal" opacity="1">~/.../claude/plugin/claude-peak-hours</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">87% free</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="bold" opacity="1">⚡ Off-peak</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">~</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(255,85,85)" font-weight="normal" opacity="1">Peak 2:00pm</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">(12h30m)</tspan></text>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="950" height="48">
|
|
2
|
+
<rect width="100%" height="100%" rx="8" fill="#1e1e1e"/>
|
|
3
|
+
<text x="14" y="30" font-family="Menlo,Monaco,Consolas,'Courier New',monospace" font-size="13" fill="#d4d4d4"><tspan fill="rgb(0,153,255)" font-weight="normal" opacity="1">Opus 4.6 (1M context)</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(86,182,194)" font-weight="normal" opacity="1">~/.../claude/plugin/claude-peak-hours</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="normal" opacity="1">87% free</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">│</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(0,175,80)" font-weight="bold" opacity="1">⚡ Hors pointe</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">~</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="rgb(255,85,85)" font-weight="normal" opacity="1">Pointe 14:00</tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="1"> </tspan><tspan fill="#d4d4d4" font-weight="normal" opacity="0.55">(12h30m)</tspan></text>
|
|
4
|
+
</svg>
|