Skip to content

Commit f845130

Browse files
claudeduyetbot
andcommitted
feat(statusline): add z.ai GLM model support with dual quota tracking
Add comprehensive support for z.ai GLM models (glm-4, glm-4.7, glm-flash, glm-plus) with automatic provider detection based on CLAUDE_MODEL environment variable. Key features: - Dual quota display: 5-hour token rolling window + monthly tool quota - Cross-platform credential handling: macOS Keychain, env vars, config files - Tool usage breakdown: Search, Web, ZRead with individual counts - Human-readable reset times: "Xh Ym" for tokens, "Xd" for monthly Technical changes: - fetch-rate-limits.sh: Split into fetch_zai_usage() and fetch_anthropic_usage() - format-status.ts: Added ZaiDetails interface and provider-aware formatting - session-start.sh: Multi-provider parsing with z.ai-specific display logic - README.md: Complete z.ai setup documentation with platform-specific guidance Bumps version to 1.6.0 (minor: new feature with backward compatibility) Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com>
1 parent ef714b4 commit f845130

5 files changed

Lines changed: 425 additions & 55 deletions

File tree

statusline/.claude-plugin/plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "statusline",
3-
"version": "1.4.0",
4-
"description": "Configurable status bar showing context usage, API rate limits (5h/7d), git branch, and active tools. Supports 1/2/3 line layouts with smart hiding of empty values.",
3+
"version": "1.6.0",
4+
"description": "Configurable status bar showing context usage, API rate limits (5h/7d for Anthropic, detailed metrics for z.ai GLM), git branch, and active tools. Supports 1/2/3 line layouts with smart hiding of empty values.",
55
"author": {
66
"name": "duyet"
77
}

statusline/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Statusline keeps you informed about what's happening during your Claude Code ses
1414
| **Active Tools** | See which tools Claude is using right now |
1515
| **Agent Tracking** | Monitor running agents and their execution time |
1616
| **Task Progress** | Track todo completion in real-time |
17+
| **API Rate Limits** | Monitor usage across Anthropic (5h/7d) or z.ai GLM (5h) |
1718

1819
## Installation
1920

@@ -88,6 +89,71 @@ All metrics displayed in a single line with empty values hidden:
8889
- ✓ Claude Code version hidden
8990
- ✓ Context shows matching system prompts and tools
9091

92+
### API Rate Limits
93+
94+
The plugin automatically detects your model provider and shows appropriate usage metrics:
95+
96+
**Anthropic Models** (default, Claude, Opus, Sonnet, etc.):
97+
```
98+
5h: 42% | 7d: 28%
99+
```
100+
- Shows 5-hour and 7-day utilization percentages
101+
- Requires Claude Code OAuth credentials
102+
103+
**z.ai GLM Models** (glm-4, glm-4.7, glm-flash, glm-plus, etc.):
104+
```
105+
z.ai: 15%
106+
```
107+
- Shows token quota percentage (5h equivalent)
108+
- Requires z.ai API key from opencode auth file
109+
110+
#### z.ai Setup
111+
112+
For GLM models, the plugin tries multiple credential sources in order:
113+
114+
**1. macOS Keychain** (macOS only - highest priority)
115+
- Looks for keychain entries named: `z.ai`, `zai`, `opencode`, or `zai-coding-plan`
116+
- Parses JSON or uses raw value as API key
117+
118+
**2. Environment Variables** (cross-platform)
119+
- `ZAI_API_KEY` - Generic z.ai API key
120+
- `ZAI_CODING_PLAN_KEY` - Coding plan specific key
121+
122+
**3. Configuration Files** (cross-platform fallback)
123+
Tries these paths in order:
124+
```
125+
~/.local/share/opencode/auth.json # Linux/Unix XDG standard
126+
~/.config/opencode/auth.json # Alternative XDG location
127+
~/.opencode/auth.json # Legacy location
128+
~/.zai/auth.json # z.ai specific
129+
```
130+
131+
Example auth file structure:
132+
```json
133+
{
134+
"zai-coding-plan": {
135+
"key": "your-zai-api-key-here"
136+
}
137+
}
138+
```
139+
140+
Alternative JSON structures supported:
141+
```json
142+
{"zai": {"key": "..."}}
143+
{"apiKey": "..."}
144+
{"key": "..."}
145+
```
146+
147+
**Recommended Setup by Platform:**
148+
149+
| Platform | Recommended Method |
150+
|----------|-------------------|
151+
| macOS | Keychain: `security add-generic-password -s "z.ai" -w "your-key"` |
152+
| Linux | File: `~/.local/share/opencode/auth.json` |
153+
| Windows | File: `%USERPROFILE%\.local\share\opencode\auth.json` |
154+
155+
The provider is automatically detected from the `CLAUDE_MODEL` environment variable. Any model starting with `glm-` will use the z.ai API.
156+
91157
## Features
92158

93159
**Real-time Updates** — Status refreshes automatically at your chosen interval

statusline/hooks/session-start.sh

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,59 @@ rate_limits=$("$PLUGIN_ROOT/scripts/fetch-rate-limits.sh" 2>/dev/null)
1010

1111
# Parse rate limit values
1212
if [ -n "$rate_limits" ]; then
13-
u5h=$(echo "$rate_limits" | jq -r '.five_hour // 0' 2>/dev/null)
14-
u7d=$(echo "$rate_limits" | jq -r '.seven_day // 0' 2>/dev/null)
13+
provider=$(echo "$rate_limits" | jq -r '.provider // "anthropic"' 2>/dev/null)
1514
error=$(echo "$rate_limits" | jq -r '.error // empty' 2>/dev/null)
1615

1716
if [ "$error" = "scope_required" ]; then
1817
rate_str="5h: re-login | 7d: needed"
1918
elif [ -n "$error" ]; then
2019
rate_str=""
20+
elif [ "$provider" = "zai" ]; then
21+
# Parse z.ai data: 5-hour tokens + monthly tools
22+
tokens_pct=$(echo "$rate_limits" | jq -r '.zai.tokens_pct // 0' 2>/dev/null)
23+
token_reset=$(echo "$rate_limits" | jq -r '.zai.token_reset // empty' 2>/dev/null)
24+
monthly_pct=$(echo "$rate_limits" | jq -r '.zai.monthly_pct // 0' 2>/dev/null)
25+
monthly_remaining=$(echo "$rate_limits" | jq -r '.zai.monthly_remaining // 0' 2>/dev/null)
26+
monthly_reset=$(echo "$rate_limits" | jq -r '.zai.monthly_reset // empty' 2>/dev/null)
27+
search=$(echo "$rate_limits" | jq -r '.zai.search // 0' 2>/dev/null)
28+
web=$(echo "$rate_limits" | jq -r '.zai.web // 0' 2>/dev/null)
29+
zread=$(echo "$rate_limits" | jq -r '.zai.zread // 0' 2>/dev/null)
30+
31+
# Build z.ai status string
32+
zai_parts=("Tokens: ${tokens_pct}%")
33+
34+
if [ -n "$token_reset" ] && [ "$token_reset" != "null" ]; then
35+
zai_parts+=("5h reset: ${token_reset}")
36+
fi
37+
38+
if [ "$monthly_remaining" -gt 0 ] 2>/dev/null; then
39+
zai_parts+=("Tools: ${monthly_pct}% (${monthly_remaining} left, ${monthly_reset})")
40+
fi
41+
42+
# Add tool usage if non-zero
43+
tool_parts=""
44+
if [ "$search" -gt 0 ] 2>/dev/null; then
45+
tool_parts="Search:${search}"
46+
fi
47+
if [ "$web" -gt 0 ] 2>/dev/null; then
48+
if [ -n "$tool_parts" ]; then tool_parts="$tool_parts "; fi
49+
tool_parts="${tool_parts}Web:${web}"
50+
fi
51+
if [ "$zread" -gt 0 ] 2>/dev/null; then
52+
if [ -n "$tool_parts" ]; then tool_parts="$tool_parts "; fi
53+
tool_parts="${tool_parts}ZRead:${zread}"
54+
fi
55+
56+
if [ -n "$tool_parts" ]; then
57+
zai_parts+=("$tool_parts")
58+
fi
59+
60+
# Join with pipe separator
61+
rate_str="z.ai $(IFS='|'; echo "${zai_parts[*]}")"
2162
else
63+
# Anthropic shows both 5h and 7d
64+
u5h=$(echo "$rate_limits" | jq -r '.five_hour // 0' 2>/dev/null)
65+
u7d=$(echo "$rate_limits" | jq -r '.seven_day // 0' 2>/dev/null)
2266
u5h_rounded=$(printf "%.0f" "$u5h" 2>/dev/null || echo "0")
2367
u7d_rounded=$(printf "%.0f" "$u7d" 2>/dev/null || echo "0")
2468
rate_str="5h: ${u5h_rounded}% | 7d: ${u7d_rounded}%"

0 commit comments

Comments
 (0)