diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 66c586e..bda8173 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,9 +5,11 @@ on:
branches: [ master, main ]
pull_request:
branches: [ master, main ]
+ workflow_dispatch:
env:
CARGO_TERM_COLOR: always
+ CARGO_INCREMENTAL: 0
jobs:
test:
@@ -40,18 +42,194 @@ jobs:
- name: Run clippy
run: cargo clippy -- -D warnings
- build:
- name: Build Check
+ build-nightly:
+ name: Build Nightly (${{ matrix.target }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
+ include:
+ - target: x86_64-unknown-linux-gnu
+ os: ubuntu-22.04
+ name: ccline-88cc-nightly-linux-x64
+ - target: x86_64-unknown-linux-musl
+ os: ubuntu-latest
+ name: ccline-88cc-nightly-linux-x64-static
+ - target: x86_64-pc-windows-msvc
+ os: windows-latest
+ name: ccline-88cc-nightly-windows-x64
+ - target: x86_64-apple-darwin
+ os: macos-latest
+ name: ccline-88cc-nightly-macos-x64
+ - target: aarch64-apple-darwin
+ os: macos-latest
+ name: ccline-88cc-nightly-macos-arm64
+
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
+ with:
+ targets: ${{ matrix.target }}
+
+ - name: Cache cargo registry
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ target
+ key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Install musl tools
+ if: matrix.target == 'x86_64-unknown-linux-musl'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y musl-tools
+
+ - name: Build binary
+ run: cargo build --release --target ${{ matrix.target }}
+
+ - name: Package Linux/macOS
+ if: matrix.os != 'windows-latest'
+ run: |
+ mkdir -p dist
+ cp target/${{ matrix.target }}/release/ccline-88cc dist/ccline-88cc
+ cd dist
+ tar czf ../${{ matrix.name }}-${{ github.sha }}.tar.gz ccline-88cc
+
+ - name: Package Windows
+ if: matrix.os == 'windows-latest'
+ run: |
+ mkdir dist
+ copy "target\${{ matrix.target }}\release\ccline-88cc.exe" "dist\ccline-88cc.exe"
+ cd dist
+ 7z a "..\${{ matrix.name }}-${{ github.sha }}.zip" ccline-88cc.exe
+
+ - name: Upload nightly build artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ matrix.name }}-${{ github.sha }}
+ path: |
+ ${{ matrix.name }}-${{ github.sha }}.tar.gz
+ ${{ matrix.name }}-${{ github.sha }}.zip
+ retention-days: 30
+
+ build-summary:
+ name: Build Summary
+ runs-on: ubuntu-latest
+ needs: [test, build-nightly]
+ if: always()
+ steps:
+ - name: Print build summary
+ run: |
+ echo "## 🚀 Build Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "**Branch:** \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "${{ needs.test.result }}" == "success" ]]; then
+ echo "✅ **Tests:** Passed" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Tests:** Failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [[ "${{ needs.build-nightly.result }}" == "success" ]]; then
+ echo "✅ **Build:** All platforms built successfully" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### 📦 Nightly Builds Available:" >> $GITHUB_STEP_SUMMARY
+ echo "- Linux x64 (GNU libc)" >> $GITHUB_STEP_SUMMARY
+ echo "- Linux x64 (static/musl)" >> $GITHUB_STEP_SUMMARY
+ echo "- Windows x64" >> $GITHUB_STEP_SUMMARY
+ echo "- macOS x64 (Intel)" >> $GITHUB_STEP_SUMMARY
+ echo "- macOS ARM64 (Apple Silicon)" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "🔗 Download artifacts from the [Actions tab](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "❌ **Build:** Some platforms failed" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ nightly-release:
+ name: Create Nightly Release
+ runs-on: ubuntu-latest
+ needs: [test, build-nightly]
+ if: github.ref == 'refs/heads/master' && needs.test.result == 'success' && needs.build-nightly.result == 'success'
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Download all artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: nightly-artifacts
+
+ - name: Generate release date
+ id: date
+ run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+
+ - name: Generate nightly tag
+ id: tag
+ run: echo "tag=nightly-${{ steps.date.outputs.date }}-${{ github.sha }}" >> $GITHUB_OUTPUT
+
+ - name: Delete existing nightly releases
+ run: |
+ # Delete previous nightly releases (keep only the latest)
+ gh release list --json tagName,isDraft | jq -r '.[] | select(.tagName | startswith("nightly-")) | select(.isDraft == false) | .tagName' | head -n 5 | while read tag; do
+ echo "Deleting old nightly release: $tag"
+ gh release delete "$tag" --yes || true
+ done
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Create nightly release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ steps.tag.outputs.tag }}
+ name: "Nightly Build (${{ steps.date.outputs.date }})"
+ body: |
+ 🌙 **Nightly Build** - ${{ steps.date.outputs.date }}
+
+ **Commit:** ${{ github.sha }}
+ **Branch:** ${{ github.ref_name }}
+ **Build Time:** ${{ steps.date.outputs.date }}
+
+ ## 📦 Available Downloads
+
+ ### Linux
+ - **ccline-88cc-nightly-linux-x64**: Standard Linux x64 build (Ubuntu 22.04+)
+ - **ccline-88cc-nightly-linux-x64-static**: Static Linux x64 build (Universal compatibility)
+
+ ### macOS
+ - **ccline-88cc-nightly-macos-x64**: Intel Mac build
+ - **ccline-88cc-nightly-macos-arm64**: Apple Silicon Mac build
+
+ ### Windows
+ - **ccline-88cc-nightly-windows-x64**: Windows x64 build
+
+ ## ⚠️ Important Notes
+
+ - This is a **development build** from the latest `master` branch
+ - Use at your own risk - may contain bugs or incomplete features
+ - For stable releases, see the [Releases](https://github.com/${{ github.repository }}/releases) page
+ - Install via NPM: `npm install -g @byebyecode/ccline-88cc` (stable)
+
+ ## 🚀 What's New
+
+ Recent commits in this build:
+
+ ```
+ ${{ github.event.head_commit.message }}
+ ```
- - name: Build
- run: cargo build --release
\ No newline at end of file
+ ---
+ *Generated automatically from commit ${{ github.sha }}*
+ files: nightly-artifacts/*/*
+ draft: false
+ prerelease: true
+ make_latest: false
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c8f517a..d12ef48 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,19 +18,19 @@ jobs:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-22.04
- name: ccline-linux-x64.tar.gz
+ name: ccline-88cc-linux-x64.tar.gz
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
- name: ccline-linux-x64-static.tar.gz
+ name: ccline-88cc-linux-x64-static.tar.gz
- target: x86_64-pc-windows-gnu
os: ubuntu-latest
- name: ccline-windows-x64.zip
+ name: ccline-88cc-windows-x64.zip
- target: x86_64-apple-darwin
os: macos-latest
- name: ccline-macos-x64.tar.gz
+ name: ccline-88cc-macos-x64.tar.gz
- target: aarch64-apple-darwin
os: macos-latest
- name: ccline-macos-arm64.tar.gz
+ name: ccline-88cc-macos-arm64.tar.gz
steps:
- name: Checkout
@@ -60,17 +60,17 @@ jobs:
if: matrix.os != 'windows-latest' && matrix.target != 'x86_64-pc-windows-gnu'
run: |
mkdir -p dist
- cp target/${{ matrix.target }}/release/ccometixline dist/ccline
+ cp target/${{ matrix.target }}/release/ccline-88cc dist/ccline-88cc
cd dist
- tar czf ../${{ matrix.name }} ccline
+ tar czf ../${{ matrix.name }} ccline-88cc
- name: Package Windows
if: matrix.target == 'x86_64-pc-windows-gnu'
run: |
mkdir -p dist
- cp target/${{ matrix.target }}/release/ccometixline.exe dist/ccline.exe
+ cp target/${{ matrix.target }}/release/ccline-88cc.exe dist/ccline-88cc.exe
cd dist
- zip ../${{ matrix.name }} ccline.exe
+ zip ../${{ matrix.name }} ccline-88cc.exe
- name: Upload artifact
uses: actions/upload-artifact@v4
@@ -111,24 +111,24 @@ jobs:
mkdir -p extracted
# macOS x64
- tar -xzf artifacts/ccline-macos-x64.tar.gz/ccline-macos-x64.tar.gz -C extracted
- mv extracted/ccline extracted/ccline-darwin-x64
+ tar -xzf artifacts/ccline-88cc-macos-x64.tar.gz/ccline-88cc-macos-x64.tar.gz -C extracted
+ mv extracted/ccline-88cc extracted/ccline-88cc-darwin-x64
# macOS ARM64
- tar -xzf artifacts/ccline-macos-arm64.tar.gz/ccline-macos-arm64.tar.gz -C extracted
- mv extracted/ccline extracted/ccline-darwin-arm64
+ tar -xzf artifacts/ccline-88cc-macos-arm64.tar.gz/ccline-88cc-macos-arm64.tar.gz -C extracted
+ mv extracted/ccline-88cc extracted/ccline-88cc-darwin-arm64
# Linux x64
- tar -xzf artifacts/ccline-linux-x64.tar.gz/ccline-linux-x64.tar.gz -C extracted
- mv extracted/ccline extracted/ccline-linux-x64
+ tar -xzf artifacts/ccline-88cc-linux-x64.tar.gz/ccline-88cc-linux-x64.tar.gz -C extracted
+ mv extracted/ccline-88cc extracted/ccline-88cc-linux-x64
# Linux musl (static)
- tar -xzf artifacts/ccline-linux-x64-static.tar.gz/ccline-linux-x64-static.tar.gz -C extracted
- mv extracted/ccline extracted/ccline-linux-x64-musl
+ tar -xzf artifacts/ccline-88cc-linux-x64-static.tar.gz/ccline-88cc-linux-x64-static.tar.gz -C extracted
+ mv extracted/ccline-88cc extracted/ccline-88cc-linux-x64-musl
# Windows
- unzip artifacts/ccline-windows-x64.zip/ccline-windows-x64.zip -d extracted
- mv extracted/ccline.exe extracted/ccline-win32-x64.exe
+ unzip artifacts/ccline-88cc-windows-x64.zip/ccline-88cc-windows-x64.zip -d extracted
+ mv extracted/ccline-88cc.exe extracted/ccline-88cc-win32-x64.exe
# List extracted files
ls -la extracted/
@@ -137,20 +137,20 @@ jobs:
run: |
# Prepare packages with version management
node npm/scripts/prepare-packages.js
-
+
# Copy binaries to platform directories
- cp extracted/ccline-darwin-x64 npm-publish/darwin-x64/ccline
- cp extracted/ccline-darwin-arm64 npm-publish/darwin-arm64/ccline
- cp extracted/ccline-linux-x64 npm-publish/linux-x64/ccline
- cp extracted/ccline-linux-x64-musl npm-publish/linux-x64-musl/ccline
- cp extracted/ccline-win32-x64.exe npm-publish/win32-x64/ccline.exe
-
+ cp extracted/ccline-88cc-darwin-x64 npm-publish/darwin-x64/ccline-88cc
+ cp extracted/ccline-88cc-darwin-arm64 npm-publish/darwin-arm64/ccline-88cc
+ cp extracted/ccline-88cc-linux-x64 npm-publish/linux-x64/ccline-88cc
+ cp extracted/ccline-88cc-linux-x64-musl npm-publish/linux-x64-musl/ccline-88cc
+ cp extracted/ccline-88cc-win32-x64.exe npm-publish/win32-x64/ccline-88cc.exe
+
# Set executable permissions for Unix binaries
- chmod +x npm-publish/darwin-x64/ccline
- chmod +x npm-publish/darwin-arm64/ccline
- chmod +x npm-publish/linux-x64/ccline
- chmod +x npm-publish/linux-x64-musl/ccline
-
+ chmod +x npm-publish/darwin-x64/ccline-88cc
+ chmod +x npm-publish/darwin-arm64/ccline-88cc
+ chmod +x npm-publish/linux-x64/ccline-88cc
+ chmod +x npm-publish/linux-x64-musl/ccline-88cc
+
# Verify packages
echo "Package structure:"
find npm-publish -name "package.json" -exec echo "=== {} ===" \; -exec head -5 {} \;
@@ -161,11 +161,11 @@ jobs:
run: |
# Publish platform packages first
for platform in darwin-x64 darwin-arm64 linux-x64 linux-x64-musl win32-x64; do
- echo "📦 Publishing @cometix/ccline-$platform"
+ echo "📦 Publishing @byebyecode/ccline-88cc-$platform"
cd npm-publish/$platform
npm publish --access public
cd ../..
- echo "✅ Published @cometix/ccline-$platform"
+ echo "✅ Published @byebyecode/ccline-88cc-$platform"
done
- name: Wait for NPM registry
@@ -178,9 +178,9 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
cd npm-publish/main
- echo "📦 Publishing @cometix/ccline"
+ echo "📦 Publishing @byebyecode/ccline-88cc"
npm publish --access public
- echo "✅ Published @cometix/ccline"
+ echo "✅ Published @byebyecode/ccline-88cc"
echo ""
echo "🎉 NPM packages published successfully!"
- echo "Install with: npm install -g @cometix/ccline"
\ No newline at end of file
+ echo "Install with: npm install -g @byebyecode/ccline-88cc"
diff --git a/Cargo.lock b/Cargo.lock
index ade23d8..f681f13 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -159,8 +159,8 @@ dependencies = [
]
[[package]]
-name = "ccometixline"
-version = "1.0.7"
+name = "ccometixline-88cc"
+version = "1.0.13"
dependencies = [
"ansi-to-tui",
"ansi_term",
diff --git a/Cargo.toml b/Cargo.toml
index dd8e655..bf4c8dd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,11 +1,11 @@
[package]
-name = "ccometixline"
-version = "1.0.7"
+name = "ccometixline-88cc"
+version = "1.0.13"
edition = "2021"
-description = "CCometixLine (ccline) - High-performance Claude Code StatusLine tool written in Rust"
-authors = ["Haleclipse"]
+description = "CCometixLine (ccline) - High-performance Claude Code StatusLine tool written in Rust (88Code version)"
+authors = ["Hobee Liu"]
license = "MIT"
-repository = "https://github.com/username/CCometixLine"
+repository = "https://github.com/byebye-code/ccline-88cc"
readme = "README.md"
keywords = ["claude", "statusline", "powerline", "rust", "claude-code"]
categories = ["command-line-utilities", "development-tools"]
@@ -28,9 +28,12 @@ chrono = { version = "0.4", features = ["serde"], optional = true }
dirs = { version = "5.0", optional = true }
regex = "1.0"
-
+[[bin]]
+name = "ccline-88cc"
+path = "src/main.rs"
[features]
-default = ["tui", "self-update", "dirs"]
+default = ["tui", "self-update", "dirs", "quota"]
tui = ["ratatui", "crossterm", "ansi_term", "ansi-to-tui", "chrono"]
self-update = ["ureq", "semver", "chrono", "dirs"]
+quota = ["ureq", "dirs", "chrono"]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..66d46c9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+MIT License
+
+Copyright (c) 2024 Hobee Liu
+Copyright (c) 2024 CCometixLine contributors (https://github.com/Haleclipse/CCometixLine)
+Copyright (c) 2024 ccline-packycc contributors (https://github.com/ding113/ccline-packycc)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index 91512b7..ef287ae 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,24 @@
-# CCometixLine
+# CCometixLine-88CC
[English](README.md) | [中文](README.zh.md)
-A high-performance Claude Code statusline tool written in Rust with Git integration, usage tracking, interactive TUI configuration, and Claude Code enhancement utilities.
+A high-performance Claude Code statusline tool written in Rust with Git integration, usage tracking, interactive TUI configuration, API quota monitoring and Claude Code enhancement utilities.
+
+> **Maintained by [HoBeedzc](https://github.com/HoBeedzc)** - This is a specially adapted version of CCometixLine for 88Code service. The original CCometixLine was created by [Haleclipse](https://github.com/Haleclipse/CCometixLine) under MIT License. This project is also released under MIT License.
+>
+> This project also incorporates code from another MIT-licensed project, [ccline-packycc](https://github.com/ding113/ccline-packycc), with attribution retained.
+>
+> 88Code is a third-party Claude Code proxy service. This project is a voluntary third-party adaptation and is not affiliated with Anthropic or 88Code. 88Code websites: [88code](https://www.88code.org/). This project implements automatic adaptation for both endpoints.


+[](https://github.com/byebye-code/ccline-88cc/actions/workflows/ci.yml)
## Screenshots

-The statusline shows: Model | Directory | Git Branch Status | Context Window Information
+The statusline shows: Model | Directory | Git Branch Status | Context Window | API Quota
## Features
@@ -20,6 +27,7 @@ The statusline shows: Model | Directory | Git Branch Status | Context Window Inf
- **Model display** with simplified Claude model names
- **Usage tracking** based on transcript analysis
- **Directory display** showing current workspace
+- **API Quota display** showing current API quota
- **Minimal design** using Nerd Font icons
### Interactive TUI Features
@@ -43,24 +51,24 @@ Install via npm (works on all platforms):
```bash
# Install globally
-npm install -g @cometix/ccline
+npm install -g @byebyecode/ccline-88cc
# Or using yarn
-yarn global add @cometix/ccline
+yarn global add @byebyecode/ccline-88cc
# Or using pnpm
-pnpm add -g @cometix/ccline
+pnpm add -g @byebyecode/ccline-88cc
```
Use npm mirror for faster download:
```bash
-npm install -g @cometix/ccline --registry https://registry.npmmirror.com
+npm install -g @byebyecode/ccline-88cc --registry https://registry.npmmirror.com
```
After installation:
-- ✅ Global command `ccline` is available everywhere
+- ✅ Global command `ccline-88cc` is available everywhere
- ⚙️ Follow the configuration steps below to integrate with Claude Code
-- 🎨 Run `ccline -c` to open configuration panel for theme selection
+- 🎨 Run `ccline-88cc -c` to open configuration panel for theme selection
### Claude Code Configuration
@@ -71,7 +79,7 @@ Add to your Claude Code `settings.json`:
{
"statusLine": {
"type": "command",
- "command": "~/.claude/ccline/ccline",
+ "command": "~/.claude/ccline/ccline-88cc",
"padding": 0
}
}
@@ -82,7 +90,7 @@ Add to your Claude Code `settings.json`:
{
"statusLine": {
"type": "command",
- "command": "%USERPROFILE%\\.claude\\ccline\\ccline.exe",
+ "command": "%USERPROFILE%\\.claude\\ccline\\ccline-88cc.exe",
"padding": 0
}
}
@@ -93,7 +101,7 @@ Add to your Claude Code `settings.json`:
{
"statusLine": {
"type": "command",
- "command": "ccline",
+ "command": "ccline-88cc",
"padding": 0
}
}
@@ -103,33 +111,33 @@ Add to your Claude Code `settings.json`:
### Update
```bash
-npm update -g @cometix/ccline
+npm update -g @byebyecode/ccline-88cc
```
Manual Installation (Click to expand)
-Alternatively, download from [Releases](https://github.com/Haleclipse/CCometixLine/releases):
+Alternatively, download from [Releases](https://github.com/byebye-code/ccline-88cc/releases):
#### Linux
#### Option 1: Dynamic Binary (Recommended)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-linux-x64.tar.gz
-tar -xzf ccline-linux-x64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-linux-x64.tar.gz
+tar -xzf ccline-88cc-linux-x64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
*Requires: Ubuntu 22.04+, CentOS 9+, Debian 11+, RHEL 9+ (glibc 2.35+)*
#### Option 2: Static Binary (Universal Compatibility)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-linux-x64-static.tar.gz
-tar -xzf ccline-linux-x64-static.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-linux-x64-static.tar.gz
+tar -xzf ccline-88cc-linux-x64-static.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
*Works on any Linux distribution (static, no dependencies)*
@@ -137,30 +145,30 @@ chmod +x ~/.claude/ccline/ccline
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-macos-x64.tar.gz
-tar -xzf ccline-macos-x64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-macos-x64.tar.gz
+tar -xzf ccline-88cc-macos-x64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
#### macOS (Apple Silicon)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-macos-arm64.tar.gz
-tar -xzf ccline-macos-arm64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-macos-arm64.tar.gz
+tar -xzf ccline-88cc-macos-arm64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
#### Windows
```powershell
# Create directory and download
-New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline"
-Invoke-WebRequest -Uri "https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-windows-x64.zip" -OutFile "ccline-windows-x64.zip"
-Expand-Archive -Path "ccline-windows-x64.zip" -DestinationPath "."
-Move-Item "ccline.exe" "$env:USERPROFILE\.claude\ccline\"
+New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline-88cc"
+Invoke-WebRequest -Uri "https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-windows-x64.zip" -OutFile "ccline-88cc-windows-x64.zip"
+Expand-Archive -Path "ccline-88cc-windows-x64.zip" -DestinationPath "."
+Move-Item "ccline-88cc.exe" "$env:USERPROFILE\.claude\ccline-88cc\"
```
@@ -168,18 +176,18 @@ Move-Item "ccline.exe" "$env:USERPROFILE\.claude\ccline\"
### Build from Source
```bash
-git clone https://github.com/Haleclipse/CCometixLine.git
-cd CCometixLine
+git clone https://github.com/byebye-code/ccline-88cc.git
+cd ccline-88cc
cargo build --release
# Linux/macOS
mkdir -p ~/.claude/ccline
-cp target/release/ccometixline ~/.claude/ccline/ccline
-chmod +x ~/.claude/ccline/ccline
+cp target/release/ccometixline ~/.claude/ccline-88cc/ccline-88cc
+chmod +x ~/.claude/ccline/ccline-88cc
# Windows (PowerShell)
-New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline"
-copy target\release\ccometixline.exe "$env:USERPROFILE\.claude\ccline\ccline.exe"
+New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline-88cc"
+copy target\release\ccometixline.exe "$env:USERPROFILE\.claude\ccline-88cc\ccline-88cc.exe"
```
## Usage
@@ -188,45 +196,45 @@ copy target\release\ccometixline.exe "$env:USERPROFILE\.claude\ccline\ccline.exe
```bash
# Initialize configuration file
-ccline --init
+ccline-88cc --init
# Check configuration validity
-ccline --check
+ccline-88cc --check
# Print current configuration
-ccline --print
+ccline-88cc --print
# Enter TUI configuration mode
-ccline --config
+ccline-88cc --config
```
### Theme Override
```bash
# Temporarily use specific theme (overrides config file)
-ccline --theme cometix
-ccline --theme minimal
-ccline --theme gruvbox
-ccline --theme nord
-ccline --theme powerline-dark
-
-# Or use custom theme files from ~/.claude/ccline/themes/
-ccline --theme my-custom-theme
+ccline-88cc --theme cometix
+ccline-88cc --theme minimal
+ccline-88cc --theme gruvbox
+ccline-88cc --theme nord
+ccline-88cc --theme powerline-dark
+
+# Or use custom theme files from ~/.claude/ccline-88cc/themes/
+ccline-88cc --theme my-custom-theme
```
### Claude Code Enhancement
```bash
# Disable context warnings and enable verbose mode
-ccline --patch /path/to/claude-code/cli.js
+ccline-88cc --patch /path/to/claude-code/cli.js
# Example for common installation
-ccline --patch ~/.local/share/fnm/node-versions/v24.4.1/installation/lib/node_modules/@anthropic-ai/claude-code/cli.js
+ccline-88cc --patch ~/.local/share/fnm/node-versions/v24.4.1/installation/lib/node_modules/@anthropic-ai/claude-code/cli.js
```
## Default Segments
-Displays: `Directory | Git Branch Status | Model | Context Window`
+Displays: `Directory | Git Branch Status | Model | Context Window | API Quota`
### Git Status Indicators
@@ -244,14 +252,27 @@ Shows simplified Claude model names:
Token usage percentage based on transcript analysis with context limit tracking.
+### API Quota Display
+Smart monitoring of API usage:
+
+- **Usage display**: Shows subscription name and used/total credits (e.g., `Pro $0.06/$20.25`)
+- **Auto-detection**: Automatically detects the correct API endpoint
+- **Zero configuration**: Just provide your API key, everything else is automatic
+
+Supports multiple API key sources:
+
+- Environment variables: `C88_API_KEY`, `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`
+- Claude Code settings.json
+- Local API key file: `~/.claude/api_key`
+
## Configuration
CCometixLine supports full configuration via TOML files and interactive TUI:
-- **Configuration file**: `~/.claude/ccline/config.toml`
-- **Interactive TUI**: `ccline --config` for real-time editing with preview
-- **Theme files**: `~/.claude/ccline/themes/*.toml` for custom themes
-- **Automatic initialization**: `ccline --init` creates default configuration
+- **Configuration file**: `~/.claude/ccline-88cc/config.toml`
+- **Interactive TUI**: `ccline-88cc --config` for real-time editing with preview
+- **Theme files**: `~/.claude/ccline-88cc/themes/*.toml` for custom themes
+- **Automatic initialization**: `ccline-88cc --init` creates default configuration
### Available Segments
@@ -300,6 +321,8 @@ Contributions are welcome! Please feel free to submit issues or pull requests.
## Related Projects
- [tweakcc](https://github.com/Piebald-AI/tweakcc) - Command-line tool to customize your Claude Code themes, thinking verbs, and more.
+- [CCometixLine](https://github.com/Haleclipse/CCometixLine) - Original high-performance Claude Code status line tool written in Rust (upstream project).
+- [ccline-packycc](https://github.com/ding113/ccline-packycc) - Another high-performance Claude Code status line tool written in Rust.
## License
@@ -307,4 +330,4 @@ This project is licensed under the [MIT License](LICENSE).
## Star History
-[](https://star-history.com/#Haleclipse/CCometixLine&Date)
+[](https://star-history.com/#byebye-code/ccline-88cc&Date)
diff --git a/README.zh.md b/README.zh.md
index 88656db..7684bd3 100644
--- a/README.zh.md
+++ b/README.zh.md
@@ -1,25 +1,33 @@
-# CCometixLine
+# CCometixLine-88CC
[English](README.md) | [中文](README.zh.md)
-基于 Rust 的高性能 Claude Code 状态栏工具,集成 Git 信息、使用量跟踪、交互式 TUI 配置和 Claude Code 补丁工具。
+基于 Rust 的高性能 Claude Code 状态栏工具,集成 Git 信息、使用量跟踪、交互式 TUI 配置、API 配额监控和 Claude Code 增强工具。
+
+> **由 [HoBeedzc](https://github.com/HoBeedzc) 维护** - 这是专为 88Code 服务特别适配的 CCometixLine 版本。原始 CCometixLine 由 [Haleclipse](https://github.com/Haleclipse/CCometixLine) 在 MIT 许可证下创建。本项目同样在 MIT 许可证下发布。
+>
+> 本项目还整合了另一个 MIT 许可证项目 [ccline-packycc](https://github.com/ding113/ccline-packycc) 的代码,并保留了相应归属。
+>
+> 88Code 是第三方 Claude Code 代理服务。本项目是自发的第三方适配,与 Anthropic 或 88Code 无关。88Code 网站:[88code](https://www.88code.org/)。本项目实现了对两个端点的自动适配。


+[](https://github.com/byebye-code/ccline-88cc/actions/workflows/ci.yml)
## 截图

-状态栏显示:模型 | 目录 | Git 分支状态 | 上下文窗口信息
+状态栏显示:模型 | 目录 | Git 分支状态 | 上下文窗口 | API 配额
## 特性
### 核心功能
- **Git 集成** 显示分支、状态和跟踪信息
- **模型显示** 简化的 Claude 模型名称
-- **使用量跟踪** 基于转录文件分析
+- **使用量跟踪** 基于转录文件分析
- **目录显示** 显示当前工作空间
+- **API 配额显示** 显示当前 API 配额
- **简洁设计** 使用 Nerd Font 图标
### 交互式 TUI 功能
@@ -43,24 +51,24 @@
```bash
# 全局安装
-npm install -g @cometix/ccline
+npm install -g @byebyecode/ccline-88cc
# 或使用 yarn
-yarn global add @cometix/ccline
+yarn global add @byebyecode/ccline-88cc
# 或使用 pnpm
-pnpm add -g @cometix/ccline
+pnpm add -g @byebyecode/ccline-88cc
```
使用镜像源加速下载:
```bash
-npm install -g @cometix/ccline --registry https://registry.npmmirror.com
+npm install -g @byebyecode/ccline-88cc --registry https://registry.npmmirror.com
```
安装后:
-- ✅ 全局命令 `ccline` 可在任何地方使用
+- ✅ 全局命令 `ccline-88cc` 可在任何地方使用
- ⚙️ 按照下方提示进行配置以集成到 Claude Code
-- 🎨 运行 `ccline -c` 打开配置面板进行主题选择
+- 🎨 运行 `ccline-88cc -c` 打开配置面板进行主题选择
### Claude Code 配置
@@ -71,7 +79,7 @@ npm install -g @cometix/ccline --registry https://registry.npmmirror.com
{
"statusLine": {
"type": "command",
- "command": "~/.claude/ccline/ccline",
+ "command": "~/.claude/ccline/ccline-88cc",
"padding": 0
}
}
@@ -82,7 +90,7 @@ npm install -g @cometix/ccline --registry https://registry.npmmirror.com
{
"statusLine": {
"type": "command",
- "command": "%USERPROFILE%\\.claude\\ccline\\ccline.exe",
+ "command": "%USERPROFILE%\\.claude\\ccline\\ccline-88cc.exe",
"padding": 0
}
}
@@ -93,7 +101,7 @@ npm install -g @cometix/ccline --registry https://registry.npmmirror.com
{
"statusLine": {
"type": "command",
- "command": "ccline",
+ "command": "ccline-88cc",
"padding": 0
}
}
@@ -103,33 +111,33 @@ npm install -g @cometix/ccline --registry https://registry.npmmirror.com
### 更新
```bash
-npm update -g @cometix/ccline
+npm update -g @byebyecode/ccline-88cc
```
手动安装(点击展开)
-或者从 [Releases](https://github.com/Haleclipse/CCometixLine/releases) 手动下载:
+或者从 [Releases](https://github.com/byebye-code/ccline-88cc/releases) 手动下载:
#### Linux
#### 选项 1: 动态链接版本(推荐)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-linux-x64.tar.gz
-tar -xzf ccline-linux-x64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-linux-x64.tar.gz
+tar -xzf ccline-88cc-linux-x64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
*系统要求: Ubuntu 22.04+, CentOS 9+, Debian 11+, RHEL 9+ (glibc 2.35+)*
#### 选项 2: 静态链接版本(通用兼容)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-linux-x64-static.tar.gz
-tar -xzf ccline-linux-x64-static.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-linux-x64-static.tar.gz
+tar -xzf ccline-88cc-linux-x64-static.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
*适用于任何 Linux 发行版(静态链接,无依赖)*
@@ -137,30 +145,30 @@ chmod +x ~/.claude/ccline/ccline
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-macos-x64.tar.gz
-tar -xzf ccline-macos-x64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-macos-x64.tar.gz
+tar -xzf ccline-88cc-macos-x64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
#### macOS (Apple Silicon)
```bash
mkdir -p ~/.claude/ccline
-wget https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-macos-arm64.tar.gz
-tar -xzf ccline-macos-arm64.tar.gz
-cp ccline ~/.claude/ccline/
-chmod +x ~/.claude/ccline/ccline
+wget https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-macos-arm64.tar.gz
+tar -xzf ccline-88cc-macos-arm64.tar.gz
+cp ccline-88cc ~/.claude/ccline/
+chmod +x ~/.claude/ccline/ccline-88cc
```
#### Windows
```powershell
# 创建目录并下载
-New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline"
-Invoke-WebRequest -Uri "https://github.com/Haleclipse/CCometixLine/releases/latest/download/ccline-windows-x64.zip" -OutFile "ccline-windows-x64.zip"
-Expand-Archive -Path "ccline-windows-x64.zip" -DestinationPath "."
-Move-Item "ccline.exe" "$env:USERPROFILE\.claude\ccline\"
+New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline-88cc"
+Invoke-WebRequest -Uri "https://github.com/byebye-code/ccline-88cc/releases/latest/download/ccline-88cc-windows-x64.zip" -OutFile "ccline-88cc-windows-x64.zip"
+Expand-Archive -Path "ccline-88cc-windows-x64.zip" -DestinationPath "."
+Move-Item "ccline-88cc.exe" "$env:USERPROFILE\.claude\ccline-88cc\"
```
@@ -168,10 +176,18 @@ Move-Item "ccline.exe" "$env:USERPROFILE\.claude\ccline\"
### 从源码构建
```bash
-git clone https://github.com/Haleclipse/CCometixLine.git
-cd CCometixLine
+git clone https://github.com/byebye-code/ccline-88cc.git
+cd ccline-88cc
cargo build --release
-cp target/release/ccometixline ~/.claude/ccline/ccline
+
+# Linux/macOS
+mkdir -p ~/.claude/ccline
+cp target/release/ccometixline ~/.claude/ccline-88cc/ccline-88cc
+chmod +x ~/.claude/ccline/ccline-88cc
+
+# Windows (PowerShell)
+New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\ccline-88cc"
+copy target\release\ccometixline.exe "$env:USERPROFILE\.claude\ccline-88cc\ccline-88cc.exe"
```
## 使用
@@ -180,45 +196,45 @@ cp target/release/ccometixline ~/.claude/ccline/ccline
```bash
# 初始化配置文件
-ccline --init
+ccline-88cc --init
# 检查配置有效性
-ccline --check
+ccline-88cc --check
# 打印当前配置
-ccline --print
+ccline-88cc --print
# 进入 TUI 配置模式
-ccline --config
+ccline-88cc --config
```
### 主题覆盖
```bash
# 临时使用指定主题(覆盖配置文件设置)
-ccline --theme cometix
-ccline --theme minimal
-ccline --theme gruvbox
-ccline --theme nord
-ccline --theme powerline-dark
-
-# 或使用 ~/.claude/ccline/themes/ 目录下的自定义主题
-ccline --theme my-custom-theme
+ccline-88cc --theme cometix
+ccline-88cc --theme minimal
+ccline-88cc --theme gruvbox
+ccline-88cc --theme nord
+ccline-88cc --theme powerline-dark
+
+# 或使用 ~/.claude/ccline-88cc/themes/ 目录下的自定义主题
+ccline-88cc --theme my-custom-theme
```
### Claude Code 增强
```bash
# 禁用上下文警告并启用详细模式
-ccline --patch /path/to/claude-code/cli.js
+ccline-88cc --patch /path/to/claude-code/cli.js
# 常见安装路径示例
-ccline --patch ~/.local/share/fnm/node-versions/v24.4.1/installation/lib/node_modules/@anthropic-ai/claude-code/cli.js
+ccline-88cc --patch ~/.local/share/fnm/node-versions/v24.4.1/installation/lib/node_modules/@anthropic-ai/claude-code/cli.js
```
## 默认段落
-显示:`目录 | Git 分支状态 | 模型 | 上下文窗口`
+显示:`目录 | Git 分支状态 | 模型 | 上下文窗口 | API 配额`
### Git 状态指示器
@@ -236,14 +252,27 @@ ccline --patch ~/.local/share/fnm/node-versions/v24.4.1/installation/lib/node_mo
基于转录文件分析的令牌使用百分比,包含上下文限制跟踪。
+### API 配额显示
+智能监控 API 使用情况:
+
+- **额度显示**: 显示套餐名称和已用/总额度 (例如 `Pro $0.06/$20.25`)
+- **自动检测**: 自动检测正确的 API 端点
+- **零配置**: 只需提供 API 密钥,其他都是自动的
+
+支持多种 API 密钥来源:
+
+- 环境变量: `C88_API_KEY`, `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`
+- Claude Code settings.json
+- 本地 API 密钥文件: `~/.claude/api_key`
+
## 配置
CCometixLine 支持通过 TOML 文件和交互式 TUI 进行完整配置:
-- **配置文件**: `~/.claude/ccline/config.toml`
-- **交互式 TUI**: `ccline --config` 实时编辑配置并预览效果
-- **主题文件**: `~/.claude/ccline/themes/*.toml` 自定义主题文件
-- **自动初始化**: `ccline --init` 创建默认配置
+- **配置文件**: `~/.claude/ccline-88cc/config.toml`
+- **交互式 TUI**: `ccline-88cc --config` 实时编辑配置并预览效果
+- **主题文件**: `~/.claude/ccline-88cc/themes/*.toml` 自定义主题文件
+- **自动初始化**: `ccline-88cc --init` 创建默认配置
### 可用段落
@@ -290,10 +319,16 @@ cargo build --release
欢迎贡献!请随时提交 issue 或 pull request。
+## 相关项目
+
+- [tweakcc](https://github.com/Piebald-AI/tweakcc) - 自定义 Claude Code 主题、思考动词等的命令行工具。
+- [CCometixLine](https://github.com/Haleclipse/CCometixLine) - 原始基于 Rust 的高性能 Claude Code 状态栏工具(上游项目)。
+- [ccline-packycc](https://github.com/ding113/ccline-packycc) - 另一个基于 Rust 的高性能 Claude Code 状态栏工具。
+
## 许可证
本项目采用 [MIT 许可证](LICENSE)。
## Star History
-[](https://star-history.com/#Haleclipse/CCometixLine&Date)
\ No newline at end of file
+[](https://star-history.com/#byebye-code/ccline-88cc&Date)
\ No newline at end of file
diff --git a/assets/img1.png b/assets/img1.png
index 8887d92..375e657 100644
Binary files a/assets/img1.png and b/assets/img1.png differ
diff --git a/npm/main/README.md b/npm/main/README.md
index 49db2a7..7f9161d 100644
--- a/npm/main/README.md
+++ b/npm/main/README.md
@@ -1,11 +1,11 @@
-# @cometix/ccline
+# @byebyecode/ccline-88cc
-CCometixLine - High-performance Claude Code StatusLine tool
+ccline-88cc - High-performance Claude Code StatusLine tool
## Installation
```bash
-npm install -g @cometix/ccline
+npm install -g @byebyecode/ccline-88cc
```
## Features
@@ -14,17 +14,18 @@ npm install -g @cometix/ccline
- 🌍 **Cross-platform**: Works on Windows, macOS, and Linux
- 📦 **Easy installation**: One command via npm
- 🔄 **Auto-update**: Built-in update notifications
+- 📊 **API quota monitoring**: Monitor your API quota usage
- 🎨 **Beautiful**: Nerd Font icons and colors
## Usage
-After installation, ccline is automatically configured for Claude Code at `~/.claude/ccline/ccline`.
+After installation, ccline-88cc is automatically configured for Claude Code at `~/.claude/ccline/ccline-88cc`.
You can also use it directly:
```bash
-ccline --help
-ccline --version
+ccline-88cc --help
+ccline-88cc --version
```
## For Users in China
@@ -32,11 +33,11 @@ ccline --version
Use npm mirror for faster installation:
```bash
-npm install -g @cometix/ccline --registry https://registry.npmmirror.com
+npm install -g @hobeeliu/ccline-88cc --registry https://registry.npmmirror.com
```
## More Information
-- GitHub: https://github.com/Haleclipse/CCometixLine
-- Issues: https://github.com/Haleclipse/CCometixLine/issues
+- GitHub: https://github.com/byebye-code/ccline-88cc
+- Issues: https://github.com/byebye-code/ccline-88cc/issues
- License: MIT
\ No newline at end of file
diff --git a/npm/main/bin/ccline.js b/npm/main/bin/ccline-88cc.js
similarity index 74%
rename from npm/main/bin/ccline.js
rename to npm/main/bin/ccline-88cc.js
index 2fb4089..893e755 100755
--- a/npm/main/bin/ccline.js
+++ b/npm/main/bin/ccline-88cc.js
@@ -4,12 +4,12 @@ const path = require('path');
const fs = require('fs');
const os = require('os');
-// 1. Priority: Use ~/.claude/ccline/ccline if exists
+// 1. Priority: Use ~/.claude/ccline/ccline-88cc if exists
const claudePath = path.join(
os.homedir(),
'.claude',
'ccline',
- process.platform === 'win32' ? 'ccline.exe' : 'ccline'
+ process.platform === 'win32' ? 'ccline-88cc.exe' : 'ccline-88cc'
);
if (fs.existsSync(claudePath)) {
@@ -58,29 +58,29 @@ if (platform === 'linux') {
}
const packageMap = {
- 'darwin-x64': '@cometix/ccline-darwin-x64',
- 'darwin-arm64': '@cometix/ccline-darwin-arm64',
- 'linux-x64': '@cometix/ccline-linux-x64',
- 'linux-x64-musl': '@cometix/ccline-linux-x64-musl',
- 'win32-x64': '@cometix/ccline-win32-x64',
- 'win32-ia32': '@cometix/ccline-win32-x64', // Use 64-bit for 32-bit systems
+ 'darwin-x64': '@byebyecode/ccline-88cc-darwin-x64',
+ 'darwin-arm64': '@byebyecode/ccline-88cc-darwin-arm64',
+ 'linux-x64': '@byebyecode/ccline-88cc-linux-x64',
+ 'linux-x64-musl': '@byebyecode/ccline-88cc-linux-x64-musl',
+ 'win32-x64': '@byebyecode/ccline-88cc-win32-x64',
+ 'win32-ia32': '@byebyecode/ccline-88cc-win32-x64', // Use 64-bit for 32-bit systems
};
const packageName = packageMap[platformKey];
if (!packageName) {
console.error(`Error: Unsupported platform ${platformKey}`);
console.error('Supported platforms: darwin (x64/arm64), linux (x64), win32 (x64)');
- console.error('Please visit https://github.com/Haleclipse/CCometixLine for manual installation');
+ console.error('Please visit https://github.com/byebye-code/ccline-88cc for manual installation');
process.exit(1);
}
-const binaryName = platform === 'win32' ? 'ccline.exe' : 'ccline';
+const binaryName = platform === 'win32' ? 'ccline-88cc.exe' : 'ccline-88cc';
const binaryPath = path.join(__dirname, '..', 'node_modules', packageName, binaryName);
if (!fs.existsSync(binaryPath)) {
console.error(`Error: Binary not found at ${binaryPath}`);
console.error('This might indicate a failed installation or unsupported platform.');
- console.error('Please try reinstalling: npm install -g @cometix/ccline');
+ console.error('Please try reinstalling: npm install -g @byebyecode/ccline-88cc');
console.error(`Expected package: ${packageName}`);
process.exit(1);
}
diff --git a/npm/main/package.json b/npm/main/package.json
index 3bc7d61..731887c 100644
--- a/npm/main/package.json
+++ b/npm/main/package.json
@@ -1,26 +1,26 @@
{
- "name": "@cometix/ccline",
+ "name": "@byebyecode/ccline-88cc",
"version": "0.0.0",
- "description": "CCometixLine - High-performance Claude Code StatusLine tool",
+ "description": "ccline-88cc - High-performance Claude Code StatusLine tool with API quota monitoring",
"bin": {
- "ccline": "./bin/ccline.js"
+ "ccline-88cc": "./bin/ccline-88cc.js"
},
"scripts": {
"postinstall": "node scripts/postinstall.js"
},
"optionalDependencies": {
- "@cometix/ccline-darwin-x64": "0.0.0",
- "@cometix/ccline-darwin-arm64": "0.0.0",
- "@cometix/ccline-linux-x64": "0.0.0",
- "@cometix/ccline-linux-x64-musl": "0.0.0",
- "@cometix/ccline-win32-x64": "0.0.0"
+ "@byebyecode/ccline-88cc-darwin-x64": "0.0.0",
+ "@byebyecode/ccline-88cc-darwin-arm64": "0.0.0",
+ "@byebyecode/ccline-88cc-linux-x64": "0.0.0",
+ "@byebyecode/ccline-88cc-linux-x64-musl": "0.0.0",
+ "@byebyecode/ccline-88cc-win32-x64": "0.0.0"
},
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
"keywords": ["claude", "statusline", "claude-code", "rust", "cli"],
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
diff --git a/npm/main/scripts/postinstall.js b/npm/main/scripts/postinstall.js
index 639058b..1784ee0 100644
--- a/npm/main/scripts/postinstall.js
+++ b/npm/main/scripts/postinstall.js
@@ -53,12 +53,12 @@ try {
}
const packageMap = {
- 'darwin-x64': '@cometix/ccline-darwin-x64',
- 'darwin-arm64': '@cometix/ccline-darwin-arm64',
- 'linux-x64': '@cometix/ccline-linux-x64',
- 'linux-x64-musl': '@cometix/ccline-linux-x64-musl',
- 'win32-x64': '@cometix/ccline-win32-x64',
- 'win32-ia32': '@cometix/ccline-win32-x64', // Use 64-bit for 32-bit
+ 'darwin-x64': '@byebyecode/ccline-88cc-darwin-x64',
+ 'darwin-arm64': '@byebyecode/ccline-88cc-darwin-arm64',
+ 'linux-x64': '@byebyecode/ccline-88cc-linux-x64',
+ 'linux-x64-musl': '@byebyecode/ccline-88cc-linux-x64-musl',
+ 'win32-x64': '@byebyecode/ccline-88cc-win32-x64',
+ 'win32-ia32': '@byebyecode/ccline-88cc-win32-x64', // Use 64-bit for 32-bit
};
const packageName = packageMap[platformKey];
@@ -69,7 +69,7 @@ try {
process.exit(0);
}
- const binaryName = platform === 'win32' ? 'ccline.exe' : 'ccline';
+ const binaryName = platform === 'win32' ? 'ccline-88cc.exe' : 'ccline-88cc';
const targetPath = path.join(claudeDir, binaryName);
// Multiple path search strategies for different package managers
@@ -123,7 +123,7 @@ try {
if (!sourcePath) {
if (!silent) {
console.log('Binary package not installed, skipping Claude Code setup');
- console.log('The global ccline command will still work via npm');
+ console.log('The global ccline-88cc command will still work via npm');
}
process.exit(0);
}
@@ -148,13 +148,13 @@ try {
if (!silent) {
console.log('✨ CCometixLine is ready for Claude Code!');
console.log(`📍 Location: ${targetPath}`);
- console.log('🎉 You can now use: ccline --help');
+ console.log('🎉 You can now use: ccline-88cc --help');
}
} catch (error) {
// Silent failure - don't break installation
if (!silent) {
console.log('Note: Could not auto-configure for Claude Code');
- console.log('The global ccline command will still work.');
- console.log('You can manually copy ccline to ~/.claude/ccline/ if needed');
+ console.log('The global ccline-88cc command will still work.');
+ console.log('You can manually copy ccline-88cc to ~/.claude/ccline/ if needed');
}
}
\ No newline at end of file
diff --git a/npm/platforms/darwin-arm64/package.json b/npm/platforms/darwin-arm64/package.json
index e6ca5ef..f934b2c 100644
--- a/npm/platforms/darwin-arm64/package.json
+++ b/npm/platforms/darwin-arm64/package.json
@@ -1,14 +1,14 @@
{
- "name": "@cometix/ccline-darwin-arm64",
+ "name": "@byebyecode/ccline-88cc-darwin-arm64",
"version": "0.0.0",
- "description": "macOS ARM64 binary for CCometixLine",
- "files": ["ccline"],
+ "description": "macOS ARM64 binary for ccline-88cc",
+ "files": ["ccline-88cc"],
"os": ["darwin"],
"cpu": ["arm64"],
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT"
}
\ No newline at end of file
diff --git a/npm/platforms/darwin-x64/package.json b/npm/platforms/darwin-x64/package.json
index df166fa..8a287bd 100644
--- a/npm/platforms/darwin-x64/package.json
+++ b/npm/platforms/darwin-x64/package.json
@@ -1,14 +1,14 @@
{
- "name": "@cometix/ccline-darwin-x64",
+ "name": "@byebyecode/ccline-88cc-darwin-x64",
"version": "0.0.0",
- "description": "macOS x64 binary for CCometixLine",
- "files": ["ccline"],
+ "description": "macOS x64 binary for ccline-88cc",
+ "files": ["ccline-88cc"],
"os": ["darwin"],
"cpu": ["x64"],
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT"
}
\ No newline at end of file
diff --git a/npm/platforms/linux-x64-musl/package.json b/npm/platforms/linux-x64-musl/package.json
index 17bc698..f8a657e 100644
--- a/npm/platforms/linux-x64-musl/package.json
+++ b/npm/platforms/linux-x64-musl/package.json
@@ -1,14 +1,14 @@
{
- "name": "@cometix/ccline-linux-x64-musl",
+ "name": "@byebyecode/ccline-88cc-linux-x64-musl",
"version": "0.0.0",
- "description": "Linux x64 static binary for CCometixLine (musl libc)",
- "files": ["ccline"],
+ "description": "Linux x64 static binary for ccline-88cc (musl libc)",
+ "files": ["ccline-88cc"],
"os": ["linux"],
"cpu": ["x64"],
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT"
}
\ No newline at end of file
diff --git a/npm/platforms/linux-x64/package.json b/npm/platforms/linux-x64/package.json
index 578e9c8..415b9b7 100644
--- a/npm/platforms/linux-x64/package.json
+++ b/npm/platforms/linux-x64/package.json
@@ -1,14 +1,14 @@
{
- "name": "@cometix/ccline-linux-x64",
+ "name": "@byebyecode/ccline-88cc-linux-x64",
"version": "0.0.0",
- "description": "Linux x64 binary for CCometixLine",
- "files": ["ccline"],
+ "description": "Linux x64 binary for ccline-88cc",
+ "files": ["ccline-88cc"],
"os": ["linux"],
"cpu": ["x64"],
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT"
}
\ No newline at end of file
diff --git a/npm/platforms/win32-x64/package.json b/npm/platforms/win32-x64/package.json
index 91568de..e268bbe 100644
--- a/npm/platforms/win32-x64/package.json
+++ b/npm/platforms/win32-x64/package.json
@@ -1,14 +1,14 @@
{
- "name": "@cometix/ccline-win32-x64",
+ "name": "@byebyecode/ccline-88cc-win32-x64",
"version": "0.0.0",
- "description": "Windows x64 binary for CCometixLine",
- "files": ["ccline.exe"],
+ "description": "Windows x64 binary for ccline-88cc",
+ "files": ["ccline-88cc.exe"],
"os": ["win32"],
"cpu": ["x64"],
"repository": {
"type": "git",
- "url": "https://github.com/Haleclipse/CCometixLine"
+ "url": "https://github.com/byebye-code/ccline-88cc"
},
- "author": "Haleclipse",
+ "author": "Hobee Liu",
"license": "MIT"
}
\ No newline at end of file
diff --git a/npm/scripts/prepare-packages.js b/npm/scripts/prepare-packages.js
index 591bdf6..f15e38f 100755
--- a/npm/scripts/prepare-packages.js
+++ b/npm/scripts/prepare-packages.js
@@ -2,7 +2,7 @@
const fs = require('fs');
const path = require('path');
-const version = process.env.GITHUB_REF?.replace('refs/tags/v', '') || process.argv[2];
+let version = process.env.GITHUB_REF?.replace('refs/tags/v', '') || process.argv[2];
if (!version) {
console.error('Error: Version not provided');
console.error('Usage: GITHUB_REF=refs/tags/v1.0.0 node prepare-packages.js');
@@ -10,6 +10,14 @@ if (!version) {
process.exit(1);
}
+// Remove -88code or -yescode suffix if present (for branch-specific tags)
+// Keep other suffixes like -beta, -alpha, -rc for pre-release versions
+const originalVersion = version;
+version = version.replace(/-(88code|yescode)$/, '');
+if (originalVersion !== version) {
+ console.log(`📝 Tag suffix removed: ${originalVersion} → ${version}`);
+}
+
console.log(`🚀 Preparing packages for version ${version}`);
// Define platform structures
@@ -42,7 +50,7 @@ platforms.forEach(platform => {
JSON.stringify(packageJson, null, 2) + '\n'
);
- console.log(`✓ Prepared @cometix/ccline-${platform} v${version}`);
+ console.log(`✓ Prepared @byebyecode/ccline-88cc-${platform} v${version}`);
});
// Prepare main package
@@ -61,7 +69,7 @@ mainPackageJson.version = version;
// Update optionalDependencies versions
if (mainPackageJson.optionalDependencies) {
Object.keys(mainPackageJson.optionalDependencies).forEach(dep => {
- if (dep.startsWith('@cometix/ccline-')) {
+ if (dep.startsWith('@byebyecode/ccline-88cc-')) {
mainPackageJson.optionalDependencies[dep] = version;
}
});
@@ -72,7 +80,7 @@ fs.writeFileSync(
JSON.stringify(mainPackageJson, null, 2) + '\n'
);
-console.log(`✓ Prepared @cometix/ccline v${version}`);
+console.log(`✓ Prepared @byebyecode/ccline-88cc v${version}`);
console.log(`\n🎉 All packages prepared for version ${version}`);
console.log('\nNext steps:');
console.log('1. Copy binaries to platform directories');
diff --git a/src/config/types.rs b/src/config/types.rs
index e5a78dc..2c038e4 100644
--- a/src/config/types.rs
+++ b/src/config/types.rs
@@ -73,6 +73,7 @@ pub enum SegmentId {
Session,
OutputStyle,
Update,
+ Quota,
}
// Legacy compatibility structure
diff --git a/src/core/segments/git.rs b/src/core/segments/git.rs
index 9e7b73b..6bc9c84 100644
--- a/src/core/segments/git.rs
+++ b/src/core/segments/git.rs
@@ -66,7 +66,7 @@ impl GitSegment {
fn is_git_repository(&self, working_dir: &str) -> bool {
Command::new("git")
- .args(["rev-parse", "--git-dir"])
+ .args(["--no-optional-locks", "rev-parse", "--git-dir"])
.current_dir(working_dir)
.output()
.map(|output| output.status.success())
@@ -75,7 +75,7 @@ impl GitSegment {
fn get_branch(&self, working_dir: &str) -> Option {
if let Ok(output) = Command::new("git")
- .args(["branch", "--show-current"])
+ .args(["--no-optional-locks", "branch", "--show-current"])
.current_dir(working_dir)
.output()
{
@@ -88,7 +88,7 @@ impl GitSegment {
}
if let Ok(output) = Command::new("git")
- .args(["symbolic-ref", "--short", "HEAD"])
+ .args(["--no-optional-locks", "symbolic-ref", "--short", "HEAD"])
.current_dir(working_dir)
.output()
{
@@ -105,7 +105,7 @@ impl GitSegment {
fn get_status(&self, working_dir: &str) -> GitStatus {
let output = Command::new("git")
- .args(["status", "--porcelain"])
+ .args(["--no-optional-locks", "status", "--porcelain"])
.current_dir(working_dir)
.output();
@@ -138,7 +138,7 @@ impl GitSegment {
fn get_commit_count(&self, working_dir: &str, range: &str) -> u32 {
let output = Command::new("git")
- .args(["rev-list", "--count", range])
+ .args(["--no-optional-locks", "rev-list", "--count", range])
.current_dir(working_dir)
.output();
@@ -153,7 +153,7 @@ impl GitSegment {
fn get_sha(&self, working_dir: &str) -> Option {
let output = Command::new("git")
- .args(["rev-parse", "--short=7", "HEAD"])
+ .args(["--no-optional-locks", "rev-parse", "--short=7", "HEAD"])
.current_dir(working_dir)
.output()
.ok()?;
diff --git a/src/core/segments/mod.rs b/src/core/segments/mod.rs
index ff036a9..76d8a08 100644
--- a/src/core/segments/mod.rs
+++ b/src/core/segments/mod.rs
@@ -4,6 +4,7 @@ pub mod directory;
pub mod git;
pub mod model;
pub mod output_style;
+pub mod quota;
pub mod session;
pub mod update;
pub mod usage;
@@ -31,6 +32,7 @@ pub use directory::DirectorySegment;
pub use git::GitSegment;
pub use model::ModelSegment;
pub use output_style::OutputStyleSegment;
+pub use quota::QuotaSegment;
pub use session::SessionSegment;
pub use update::UpdateSegment;
pub use usage::UsageSegment;
diff --git a/src/core/segments/quota.rs b/src/core/segments/quota.rs
new file mode 100644
index 0000000..2e87923
--- /dev/null
+++ b/src/core/segments/quota.rs
@@ -0,0 +1,481 @@
+use super::{Segment, SegmentData};
+use crate::config::{InputData, SegmentId};
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
+use std::env;
+use std::fs;
+use std::hash::{Hash, Hasher};
+use std::path::PathBuf;
+use std::time::{Duration, SystemTime};
+
+// API 通用包装响应结构
+#[derive(Debug, Deserialize)]
+struct ApiWrapper {
+ code: i32,
+ msg: String,
+ ok: bool,
+ data: T,
+}
+
+// Usage API 响应数据结构
+#[derive(Debug, Deserialize)]
+struct C88ApiResponse {
+ #[serde(rename = "creditLimit")]
+ credit_limit: f64,
+ #[serde(rename = "currentCredits")]
+ current_credits: f64,
+ #[serde(rename = "subscriptionName")]
+ subscription_name: Option,
+ #[serde(rename = "subscriptionId")]
+ subscription_id: Option,
+}
+
+// 订阅信息结构
+#[derive(Debug, Deserialize)]
+struct SubscriptionResponse {
+ id: u32,
+ #[serde(rename = "resetTimes")]
+ reset_times: u32,
+ #[serde(rename = "autoResetWhenZero")]
+ auto_reset_when_zero: bool,
+}
+
+// 端点配置
+#[derive(Debug, Clone)]
+struct EndpointConfig {
+ url: String,
+ name: String,
+}
+
+// 端点缓存
+#[allow(dead_code)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+struct EndpointCache {
+ api_key_hash: u64,
+ successful_endpoint: String,
+ last_success_time: SystemTime,
+ success_count: u32,
+}
+
+// 智能端点检测器
+struct SmartEndpointDetector {
+ endpoints: Vec,
+}
+
+impl SmartEndpointDetector {
+ fn new() -> Self {
+ let endpoints = vec![EndpointConfig {
+ url: "https://www.88code.org/api/usage".to_string(),
+ name: "main".to_string(),
+ }];
+
+ Self { endpoints }
+ }
+
+ #[allow(dead_code)]
+ fn get_cache_file_path() -> PathBuf {
+ if let Some(home) = dirs::home_dir() {
+ home.join(".claude")
+ .join("ccline")
+ .join("endpoint_cache.json")
+ } else {
+ PathBuf::from("endpoint_cache.json")
+ }
+ }
+
+ #[allow(dead_code)]
+ fn hash_api_key(api_key: &str) -> u64 {
+ let mut hasher = std::collections::hash_map::DefaultHasher::new();
+ api_key.hash(&mut hasher);
+ hasher.finish()
+ }
+
+ fn try_endpoint(&self, endpoint: &EndpointConfig, api_key: &str, model: &str) -> Option {
+ let debug = env::var("C88_DEBUG").is_ok();
+
+ // 构建带 model 参数的 URL
+ let url_with_model = format!("{}?model={}", endpoint.url, model);
+
+ if debug {
+ eprintln!("[DEBUG] Trying endpoint: {}", url_with_model);
+ }
+
+ let start_time = SystemTime::now();
+ let bearer_token = format!("Bearer {}", api_key);
+ let result = ureq::post(&url_with_model)
+ .set("accept", "*/*")
+ .set("content-type", "application/json")
+ .set("Authorization", &bearer_token)
+ .timeout(Duration::from_secs(5))
+ .call();
+
+ match result {
+ Ok(response) => {
+ if response.status() == 200 {
+ let elapsed = start_time.elapsed().unwrap_or(Duration::from_secs(0));
+ if debug {
+ eprintln!(
+ "[DEBUG] Success: {} in {}ms",
+ endpoint.name,
+ elapsed.as_millis()
+ );
+ }
+
+ // 解析包装后的响应
+ response
+ .into_json::>()
+ .ok()
+ .map(|wrapper| wrapper.data)
+ } else {
+ if debug {
+ eprintln!(
+ "[DEBUG] Failed: {} status {}",
+ endpoint.name,
+ response.status()
+ );
+ }
+ None
+ }
+ }
+ Err(e) => {
+ if debug {
+ eprintln!("[DEBUG] Error: {} - {}", endpoint.name, e);
+ }
+ None
+ }
+ }
+ }
+
+ fn detect_endpoint(&mut self, api_key: &str, model: &str) -> Option<(String, C88ApiResponse)> {
+ // 尝试所有端点
+ let endpoints_clone = self.endpoints.clone();
+ for endpoint in &endpoints_clone {
+ if let Some(response) = self.try_endpoint(endpoint, api_key, model) {
+ return Some((endpoint.url.clone(), response));
+ }
+ }
+
+ None
+ }
+
+ fn detect_endpoint_static(api_key: &str, model: &str) -> Option<(String, C88ApiResponse)> {
+ let mut detector = SmartEndpointDetector::new();
+ detector.detect_endpoint(api_key, model)
+ }
+}
+
+#[derive(Default)]
+pub struct QuotaSegment;
+
+impl QuotaSegment {
+ pub fn new() -> Self {
+ Self
+ }
+
+ fn load_api_key(&self) -> Option {
+ // 优先级:环境变量 > Claude Code settings.json > api_key 文件
+
+ // 1. 环境变量
+ if let Ok(key) = env::var("C88_API_KEY") {
+ return Some(key);
+ }
+
+ if let Ok(key) = env::var("ANTHROPIC_API_KEY") {
+ return Some(key);
+ }
+
+ if let Ok(key) = env::var("ANTHROPIC_AUTH_TOKEN") {
+ return Some(key);
+ }
+
+ // 2. Claude Code settings.json
+ if let Some(key) = self.load_from_settings() {
+ return Some(key);
+ }
+
+ // 3. api_key 文件
+ if let Some(home) = dirs::home_dir() {
+ let api_key_path = home.join(".claude").join("api_key");
+ if let Ok(key) = fs::read_to_string(api_key_path) {
+ return Some(key.trim().to_string());
+ }
+ }
+
+ None
+ }
+
+ fn load_from_settings(&self) -> Option {
+ if let Some(home) = dirs::home_dir() {
+ let settings_path = home.join(".claude").join("settings.json");
+ if let Ok(content) = fs::read_to_string(settings_path) {
+ if let Ok(settings) = serde_json::from_str::(&content) {
+ if let Some(env) = settings.get("env") {
+ if let Some(token) = env.get("ANTHROPIC_AUTH_TOKEN") {
+ if let Some(token_str) = token.as_str() {
+ return Some(token_str.to_string());
+ }
+ }
+ if let Some(key) = env.get("ANTHROPIC_API_KEY") {
+ if let Some(key_str) = key.as_str() {
+ return Some(key_str.to_string());
+ }
+ }
+ }
+ }
+ }
+ }
+ None
+ }
+
+ fn load_model(&self) -> String {
+ // 优先级:环境变量 > settings.json > 默认值
+
+ // 1. 环境变量 ANTHROPIC_MODEL
+ if let Ok(model) = env::var("ANTHROPIC_MODEL") {
+ return model;
+ }
+
+ // 2. settings.json(顶层 model 字段)
+ if let Some(home) = dirs::home_dir() {
+ let settings_path = home.join(".claude").join("settings.json");
+ if let Ok(content) = fs::read_to_string(settings_path) {
+ if let Ok(settings) = serde_json::from_str::(&content) {
+ if let Some(model) = settings.get("model") {
+ if let Some(model_str) = model.as_str() {
+ return model_str.to_string();
+ }
+ }
+ }
+ }
+ }
+
+ // 3. 默认值:使用 claude-sonnet-4-5-20251022
+ "claude-sonnet-4-5-20251022".to_string()
+ }
+
+ fn format_quota(&self, subscription_name: Option<&str>, used: f64, total: f64) -> String {
+ if let Some(name) = subscription_name {
+ format!("{} ${:.2}/${:.2}", name, used, total)
+ } else {
+ format!("${:.2}/${:.2}", used, total)
+ }
+ }
+
+ fn calculate_used(&self, response: &C88ApiResponse) -> f64 {
+ response.credit_limit - response.current_credits
+ }
+
+ fn fetch_subscription_info(&self, api_key: &str, subscription_id: u32, model: &str) -> Option {
+ let url = format!("https://www.88code.org/api/subscription?model={}", model);
+ let bearer_token = format!("Bearer {}", api_key);
+
+ let result = ureq::post(&url)
+ .set("accept", "*/*")
+ .set("content-type", "application/json")
+ .set("Authorization", &bearer_token)
+ .timeout(Duration::from_secs(5))
+ .call();
+
+ match result {
+ Ok(response) if response.status() == 200 => {
+ if let Ok(wrapper) = response.into_json::>>() {
+ // 从包装结构中提取数据并查找匹配的订阅ID
+ wrapper.data.into_iter().find(|sub| sub.id == subscription_id)
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ }
+
+ fn format_reset_info(&self, reset_times: u32, auto_reset_when_zero: bool, user_auto_reset_enabled: bool) -> String {
+ let status = if user_auto_reset_enabled {
+ // 用户在TUI中启用了Auto Reset
+ "[reset on auto]"
+ } else if auto_reset_when_zero {
+ // API返回的auto_reset_when_zero为true
+ "[reset on zero]"
+ } else {
+ "[reset off]"
+ };
+ format!("↻ {} {}", reset_times, status)
+ }
+
+ /// 检查当前是否在重置时间窗口内
+ /// - 18:55-18:59:必须剩余2次或更多重置机会才进行重置
+ /// - 23:55-23:59:只要有重置次数(>=1)就进行重置
+ fn is_in_reset_window(&self, reset_times: u32) -> bool {
+ use chrono::{Local, Timelike};
+
+ let now = Local::now();
+ let hour = now.hour();
+ let minute = now.minute();
+
+ // 18:55 - 18:59:需要2次或更多重置机会
+ if hour == 18 && minute >= 55 && minute <= 59 {
+ return reset_times >= 2;
+ }
+
+ // 23:55 - 23:59:只要有重置次数就可以
+ if hour == 23 && minute >= 55 && minute <= 59 {
+ return reset_times >= 1;
+ }
+
+ false
+ }
+
+ /// 执行重置操作(调用API)
+ /// 返回重置是否成功
+ fn perform_reset(&self, api_key: &str, subscription_id: u32) -> bool {
+ let url = format!("https://www.88code.org/api/reset-credits/{}", subscription_id);
+ let bearer_token = format!("Bearer {}", api_key);
+ let debug = env::var("C88_DEBUG").is_ok();
+
+ if debug {
+ eprintln!("[DEBUG] Attempting to reset credits for subscription {}", subscription_id);
+ }
+
+ let result = ureq::post(&url)
+ .set("accept", "*/*")
+ .set("content-type", "application/json")
+ .set("Authorization", &bearer_token)
+ .timeout(Duration::from_secs(5))
+ .call();
+
+ match result {
+ Ok(response) => {
+ if response.status() == 200 {
+ if debug {
+ eprintln!("[DEBUG] Reset successful for subscription {}", subscription_id);
+ }
+ true
+ } else {
+ if debug {
+ eprintln!("[DEBUG] Reset failed with status {}", response.status());
+ }
+ false
+ }
+ }
+ Err(e) => {
+ if debug {
+ eprintln!("[DEBUG] Reset error: {}", e);
+ }
+ false
+ }
+ }
+ }
+
+ /// 检查并执行自动重置(如果需要)
+ fn check_and_auto_reset(
+ &self,
+ api_key: &str,
+ subscription_id: u32,
+ reset_times: u32,
+ auto_reset_enabled: bool,
+ ) -> bool {
+ if !auto_reset_enabled {
+ return false;
+ }
+
+ if reset_times == 0 {
+ return false;
+ }
+
+ if !self.is_in_reset_window(reset_times) {
+ return false;
+ }
+
+ // 在重置窗口内,执行重置
+ self.perform_reset(api_key, subscription_id)
+ }
+}
+
+impl Segment for QuotaSegment {
+ fn collect(&self, _input: &InputData) -> Option {
+ #[cfg(not(feature = "quota"))]
+ {
+ return None;
+ }
+
+ #[cfg(feature = "quota")]
+ {
+ let api_key = self.load_api_key()?;
+ let model = self.load_model();
+
+ // 加载配置获取auto_reset_enabled选项
+ let auto_reset_enabled = if let Ok(config) = crate::config::Config::load() {
+ config
+ .segments
+ .iter()
+ .find(|s| s.id == SegmentId::Quota)
+ .and_then(|sc| sc.options.get("auto_reset_enabled"))
+ .and_then(|v| v.as_bool())
+ .unwrap_or(false)
+ } else {
+ false
+ };
+
+ // 使用静态方法进行端点检测,传递 model 参数
+ if let Some((endpoint_url, response)) =
+ SmartEndpointDetector::detect_endpoint_static(&api_key, &model)
+ {
+ let used = self.calculate_used(&response);
+ let total = response.credit_limit;
+ let quota_display = self.format_quota(response.subscription_name.as_deref(), used, total);
+
+ // 获取重置次数信息
+ let reset_info = if let Some(sub_id) = response.subscription_id {
+ if let Some(sub_info) = self.fetch_subscription_info(&api_key, sub_id, &model) {
+ // 检查并执行自动重置(内部会进行所有必要的检查)
+ let _ = self.check_and_auto_reset(
+ &api_key,
+ sub_id,
+ sub_info.reset_times,
+ auto_reset_enabled,
+ );
+
+ self.format_reset_info(
+ sub_info.reset_times,
+ sub_info.auto_reset_when_zero,
+ auto_reset_enabled
+ )
+ } else {
+ String::new()
+ }
+ } else {
+ String::new()
+ };
+
+ let mut metadata = HashMap::new();
+ metadata.insert("used".to_string(), used.to_string());
+ metadata.insert("total".to_string(), total.to_string());
+ metadata.insert("remain".to_string(), response.current_credits.to_string());
+ metadata.insert("endpoint_used".to_string(), endpoint_url);
+ if let Some(name) = &response.subscription_name {
+ metadata.insert("subscription_name".to_string(), name.clone());
+ }
+
+ Some(SegmentData {
+ primary: quota_display,
+ secondary: reset_info,
+ metadata,
+ })
+ } else {
+ // 所有端点都失败
+ let mut metadata = HashMap::new();
+ metadata.insert("status".to_string(), "offline".to_string());
+
+ Some(SegmentData {
+ primary: "Offline".to_string(),
+ secondary: String::new(),
+ metadata,
+ })
+ }
+ }
+ }
+
+ fn id(&self) -> SegmentId {
+ SegmentId::Quota
+ }
+}
diff --git a/src/core/segments/usage.rs b/src/core/segments/usage.rs
index 94fc27d..135ad47 100644
--- a/src/core/segments/usage.rs
+++ b/src/core/segments/usage.rs
@@ -1,7 +1,7 @@
use super::{Segment, SegmentData};
use crate::config::{InputData, SegmentId};
use crate::utils::credentials;
-use chrono::{DateTime, Datelike, Timelike, Utc};
+use chrono::{DateTime, Datelike, Duration, Local, Timelike, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -50,7 +50,16 @@ impl UsageSegment {
fn format_reset_time(reset_time_str: Option<&str>) -> String {
if let Some(time_str) = reset_time_str {
if let Ok(dt) = DateTime::parse_from_rfc3339(time_str) {
- return format!("{}-{}-{}", dt.month(), dt.day(), dt.hour());
+ let mut local_dt = dt.with_timezone(&Local);
+ if local_dt.minute() > 45 {
+ local_dt += Duration::hours(1);
+ }
+ return format!(
+ "{}-{}-{}",
+ local_dt.month(),
+ local_dt.day(),
+ local_dt.hour()
+ );
}
}
"?".to_string()
diff --git a/src/core/statusline.rs b/src/core/statusline.rs
index bd4e581..841d4c5 100644
--- a/src/core/statusline.rs
+++ b/src/core/statusline.rs
@@ -463,6 +463,11 @@ pub fn collect_all_segments(
let mut results = Vec::new();
for segment_config in &config.segments {
+ // Skip disabled segments to avoid unnecessary API requests
+ if !segment_config.enabled {
+ continue;
+ }
+
let segment_data = match segment_config.id {
crate::config::SegmentId::Model => {
let segment = ModelSegment::new();
@@ -505,6 +510,10 @@ pub fn collect_all_segments(
let segment = UpdateSegment::new();
segment.collect(input)
}
+ crate::config::SegmentId::Quota => {
+ let segment = QuotaSegment::new();
+ segment.collect(input)
+ }
};
if let Some(data) = segment_data {
diff --git a/src/main.rs b/src/main.rs
index 66706fb..dbfe679 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
-use ccometixline::cli::Cli;
-use ccometixline::config::{Config, InputData};
-use ccometixline::core::{collect_all_segments, StatusLineGenerator};
+use ccometixline_88cc::cli::Cli;
+use ccometixline_88cc::config::{Config, InputData};
+use ccometixline_88cc::core::{collect_all_segments, StatusLineGenerator};
use std::io::{self, IsTerminal};
fn main() -> Result<(), Box> {
@@ -17,7 +17,7 @@ fn main() -> Result<(), Box> {
// Apply theme override if provided
if let Some(theme) = cli.theme {
- config = ccometixline::ui::themes::ThemePresets::get_theme(&theme);
+ config = ccometixline_88cc::ui::themes::ThemePresets::get_theme(&theme);
}
config.print()?;
@@ -34,7 +34,7 @@ fn main() -> Result<(), Box> {
if cli.config {
#[cfg(feature = "tui")]
{
- ccometixline::ui::run_configurator()?;
+ ccometixline_88cc::ui::run_configurator()?;
}
#[cfg(not(feature = "tui"))]
{
@@ -58,7 +58,7 @@ fn main() -> Result<(), Box> {
// Handle Claude Code patcher
if let Some(claude_path) = cli.patch {
- use ccometixline::utils::ClaudeCodePatcher;
+ use ccometixline_88cc::utils::ClaudeCodePatcher;
println!("🔧 Claude Code Context Warning Disabler");
println!("Target file: {}", claude_path);
@@ -101,7 +101,7 @@ fn main() -> Result<(), Box> {
// Apply theme override if provided
if let Some(theme) = cli.theme {
- config = ccometixline::ui::themes::ThemePresets::get_theme(&theme);
+ config = ccometixline_88cc::ui::themes::ThemePresets::get_theme(&theme);
}
// Check if stdin has data
@@ -109,19 +109,19 @@ fn main() -> Result<(), Box> {
// No input data available, show main menu
#[cfg(feature = "tui")]
{
- use ccometixline::ui::{MainMenu, MenuResult};
+ use ccometixline_88cc::ui::{MainMenu, MenuResult};
if let Some(result) = MainMenu::run()? {
match result {
MenuResult::LaunchConfigurator => {
- ccometixline::ui::run_configurator()?;
+ ccometixline_88cc::ui::run_configurator()?;
}
MenuResult::InitConfig => {
- ccometixline::config::Config::init()?;
+ ccometixline_88cc::config::Config::init()?;
println!("Configuration initialized successfully!");
}
MenuResult::CheckConfig => {
- let config = ccometixline::config::Config::load()?;
+ let config = ccometixline_88cc::config::Config::load()?;
config.check()?;
println!("Configuration is valid!");
}
diff --git a/src/ui/app.rs b/src/ui/app.rs
index 0cca753..78ba40b 100644
--- a/src/ui/app.rs
+++ b/src/ui/app.rs
@@ -503,6 +503,7 @@ impl App {
SegmentId::Session => "Session",
SegmentId::OutputStyle => "Output Style",
SegmentId::Update => "Update",
+ SegmentId::Quota => "Quota",
};
let is_enabled = segment.enabled;
self.status_message = Some(format!(
@@ -530,6 +531,7 @@ impl App {
SegmentId::Session => "Session",
SegmentId::OutputStyle => "Output Style",
SegmentId::Update => "Update",
+ SegmentId::Quota => "Quota",
};
let is_enabled = segment.enabled;
self.status_message = Some(format!(
@@ -560,9 +562,36 @@ impl App {
}
}
FieldSelection::Options => {
- // TODO: Implement options editor
- self.status_message =
- Some("Options editor not implemented yet".to_string());
+ // Handle segment-specific options
+ if let Some(segment) = self.config.segments.get_mut(self.selected_segment) {
+ match segment.id {
+ SegmentId::Quota => {
+ // Toggle auto_reset_enabled for Quota segment
+ let current_value = segment
+ .options
+ .get("auto_reset_enabled")
+ .and_then(|v| v.as_bool())
+ .unwrap_or(false);
+ segment.options.insert(
+ "auto_reset_enabled".to_string(),
+ serde_json::Value::Bool(!current_value),
+ );
+ self.status_message = Some(format!(
+ "Auto Reset {}",
+ if !current_value {
+ "enabled"
+ } else {
+ "disabled"
+ }
+ ));
+ self.preview.update_preview(&self.config);
+ }
+ _ => {
+ self.status_message =
+ Some("No options available for this segment".to_string());
+ }
+ }
+ }
}
}
}
diff --git a/src/ui/components/preview.rs b/src/ui/components/preview.rs
index 53c5d66..31abb15 100644
--- a/src/ui/components/preview.rs
+++ b/src/ui/components/preview.rs
@@ -183,6 +183,22 @@ impl PreviewComponent {
map
},
},
+ SegmentId::Quota => SegmentData {
+ primary: "Pro $0.06/$20.25".to_string(),
+ secondary: "".to_string(),
+ metadata: {
+ let mut map = HashMap::new();
+ map.insert("used".to_string(), "0.0635".to_string());
+ map.insert("total".to_string(), "20.25".to_string());
+ map.insert("remain".to_string(), "20.1865".to_string());
+ map.insert("subscription_name".to_string(), "Pro".to_string());
+ map.insert(
+ "endpoint_used".to_string(),
+ "https://www.88code.org/api/usage".to_string(),
+ );
+ map
+ },
+ },
};
segments_data.push((segment_config.clone(), mock_data));
diff --git a/src/ui/components/segment_list.rs b/src/ui/components/segment_list.rs
index 832834b..13f6a89 100644
--- a/src/ui/components/segment_list.rs
+++ b/src/ui/components/segment_list.rs
@@ -57,6 +57,7 @@ impl SegmentListComponent {
SegmentId::Session => "Session",
SegmentId::OutputStyle => "Output Style",
SegmentId::Update => "Update",
+ SegmentId::Quota => "Quota",
};
if is_selected {
diff --git a/src/ui/components/settings.rs b/src/ui/components/settings.rs
index aa65acb..96fb841 100644
--- a/src/ui/components/settings.rs
+++ b/src/ui/components/settings.rs
@@ -36,6 +36,7 @@ impl SettingsComponent {
SegmentId::Session => "Session",
SegmentId::OutputStyle => "Output Style",
SegmentId::Update => "Update",
+ SegmentId::Quota => "Quota",
};
let current_icon = match config.style.mode {
StyleMode::Plain => &segment.icon.plain,
@@ -268,10 +269,25 @@ impl SettingsComponent {
),
create_field_line(
FieldSelection::Options,
- vec![Span::raw(format!(
- "└─ Options: {} items",
- segment.options.len()
- ))],
+ {
+ // Show auto_reset_enabled status for Quota segment
+ if segment.id == SegmentId::Quota {
+ let auto_reset_enabled = segment
+ .options
+ .get("auto_reset_enabled")
+ .and_then(|v| v.as_bool())
+ .unwrap_or(false);
+ vec![Span::raw(format!(
+ "└─ Auto Reset: {}",
+ if auto_reset_enabled { "[✓]" } else { "[ ]" }
+ ))]
+ } else {
+ vec![Span::raw(format!(
+ "└─ Options: {} items",
+ segment.options.len()
+ ))]
+ }
+ },
),
];
let text = Text::from(lines);
diff --git a/src/ui/themes/presets.rs b/src/ui/themes/presets.rs
index 0a51dab..f4742a2 100644
--- a/src/ui/themes/presets.rs
+++ b/src/ui/themes/presets.rs
@@ -137,6 +137,7 @@ impl ThemePresets {
theme_cometix::cost_segment(),
theme_cometix::session_segment(),
theme_cometix::output_style_segment(),
+ theme_cometix::quota_segment(),
],
theme: "cometix".to_string(),
}
@@ -157,6 +158,7 @@ impl ThemePresets {
theme_default::cost_segment(),
theme_default::session_segment(),
theme_default::output_style_segment(),
+ theme_default::quota_segment(),
],
theme: "default".to_string(),
}
@@ -177,6 +179,7 @@ impl ThemePresets {
theme_minimal::cost_segment(),
theme_minimal::session_segment(),
theme_minimal::output_style_segment(),
+ theme_minimal::quota_segment(),
],
theme: "minimal".to_string(),
}
@@ -197,6 +200,7 @@ impl ThemePresets {
theme_gruvbox::cost_segment(),
theme_gruvbox::session_segment(),
theme_gruvbox::output_style_segment(),
+ theme_gruvbox::quota_segment(),
],
theme: "gruvbox".to_string(),
}
@@ -217,6 +221,7 @@ impl ThemePresets {
theme_nord::cost_segment(),
theme_nord::session_segment(),
theme_nord::output_style_segment(),
+ theme_nord::quota_segment(),
],
theme: "nord".to_string(),
}
@@ -237,6 +242,7 @@ impl ThemePresets {
theme_powerline_dark::cost_segment(),
theme_powerline_dark::session_segment(),
theme_powerline_dark::output_style_segment(),
+ theme_powerline_dark::quota_segment(),
],
theme: "powerline-dark".to_string(),
}
@@ -257,6 +263,7 @@ impl ThemePresets {
theme_powerline_light::cost_segment(),
theme_powerline_light::session_segment(),
theme_powerline_light::output_style_segment(),
+ theme_powerline_light::quota_segment(),
],
theme: "powerline-light".to_string(),
}
@@ -277,6 +284,7 @@ impl ThemePresets {
theme_powerline_rose_pine::cost_segment(),
theme_powerline_rose_pine::session_segment(),
theme_powerline_rose_pine::output_style_segment(),
+ theme_powerline_rose_pine::quota_segment(),
],
theme: "powerline-rose-pine".to_string(),
}
@@ -297,8 +305,126 @@ impl ThemePresets {
theme_powerline_tokyo_night::cost_segment(),
theme_powerline_tokyo_night::session_segment(),
theme_powerline_tokyo_night::output_style_segment(),
+ theme_powerline_tokyo_night::quota_segment(),
],
theme: "powerline-tokyo-night".to_string(),
}
}
+
+ /// Create default theme configuration file with minimal template
+ pub fn create_default_theme_file(theme_name: &str) -> Result<(), Box> {
+ let themes_dir = Self::get_themes_path();
+ let theme_path = themes_dir.join(format!("{}.toml", theme_name));
+
+ // Create themes directory if it doesn't exist
+ std::fs::create_dir_all(&themes_dir)?;
+
+ // Create a minimal template config
+ let template_config = Self::get_default();
+ let mut theme_config = template_config;
+ theme_config.theme = theme_name.to_string();
+
+ let toml_content = toml::to_string_pretty(&theme_config)?;
+
+ // Add comments and examples to the template
+ let template_content = format!(
+ "# CCometixLine Theme Configuration: {}\n\
+ # This file defines a custom theme for CCometixLine\n\
+ # File location: ~/.claude/ccline/themes/{}.toml\n\
+ # You can modify colors, icons, and styles below\n\
+ \n\
+ {}\n",
+ theme_name,
+ theme_name,
+ toml_content.trim()
+ );
+
+ std::fs::write(&theme_path, template_content)?;
+ Ok(())
+ }
+
+ /// Check if a theme exists (built-in or custom)
+ pub fn theme_exists(theme_name: &str) -> bool {
+ // Check built-in themes
+ let built_in_themes = [
+ "cometix",
+ "default",
+ "minimal",
+ "gruvbox",
+ "nord",
+ "powerline-dark",
+ "powerline-light",
+ "powerline-rose-pine",
+ "powerline-tokyo-night",
+ ];
+
+ if built_in_themes.contains(&theme_name) {
+ return true;
+ }
+
+ // Check custom themes
+ let themes_dir = Self::get_themes_path();
+ let theme_path = themes_dir.join(format!("{}.toml", theme_name));
+ theme_path.exists()
+ }
+
+ /// Delete a custom theme file
+ pub fn delete_theme(theme_name: &str) -> Result<(), Box> {
+ // Don't allow deleting built-in themes
+ let built_in_themes = [
+ "cometix",
+ "default",
+ "minimal",
+ "gruvbox",
+ "nord",
+ "powerline-dark",
+ "powerline-light",
+ "powerline-rose-pine",
+ "powerline-tokyo-night",
+ ];
+
+ if built_in_themes.contains(&theme_name) {
+ return Err(format!("Cannot delete built-in theme: {}", theme_name).into());
+ }
+
+ let themes_dir = Self::get_themes_path();
+ let theme_path = themes_dir.join(format!("{}.toml", theme_name));
+
+ if theme_path.exists() {
+ std::fs::remove_file(theme_path)?;
+ }
+
+ Ok(())
+ }
+
+ /// Copy an existing theme to create a new one
+ pub fn copy_theme(
+ source_theme: &str,
+ new_theme: &str,
+ ) -> Result<(), Box> {
+ let source_config = Self::get_theme(source_theme);
+ Self::save_theme(new_theme, &source_config)?;
+ Ok(())
+ }
+
+ /// Get theme type (built-in or custom)
+ pub fn get_theme_type(theme_name: &str) -> &'static str {
+ let built_in_themes = [
+ "cometix",
+ "default",
+ "minimal",
+ "gruvbox",
+ "nord",
+ "powerline-dark",
+ "powerline-light",
+ "powerline-rose-pine",
+ "powerline-tokyo-night",
+ ];
+
+ if built_in_themes.contains(&theme_name) {
+ "built-in"
+ } else {
+ "custom"
+ }
+ }
}
diff --git a/src/ui/themes/theme_cometix.rs b/src/ui/themes/theme_cometix.rs
index dfcd1e6..e8c6cc8 100644
--- a/src/ui/themes/theme_cometix.rs
+++ b/src/ui/themes/theme_cometix.rs
@@ -162,3 +162,25 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Color16 { c16: 11 }), // Yellow
+ text: Some(AnsiColor::Color16 { c16: 11 }),
+ background: None,
+ },
+ styles: TextStyleConfig { text_bold: true },
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_default.rs b/src/ui/themes/theme_default.rs
index 20b21ca..027923f 100644
--- a/src/ui/themes/theme_default.rs
+++ b/src/ui/themes/theme_default.rs
@@ -162,3 +162,25 @@ pub fn output_style_segment() -> SegmentConfig {
options: HashMap::new(),
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Color16 { c16: 11 }), // Yellow
+ text: Some(AnsiColor::Color16 { c16: 11 }),
+ background: None,
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_gruvbox.rs b/src/ui/themes/theme_gruvbox.rs
index 6b071e1..461e7c2 100644
--- a/src/ui/themes/theme_gruvbox.rs
+++ b/src/ui/themes/theme_gruvbox.rs
@@ -162,3 +162,25 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Color256 { c256: 214 }), // Gruvbox yellow
+ text: Some(AnsiColor::Color256 { c256: 214 }),
+ background: None,
+ },
+ styles: TextStyleConfig { text_bold: true },
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_minimal.rs b/src/ui/themes/theme_minimal.rs
index 0c1cdd6..5306a00 100644
--- a/src/ui/themes/theme_minimal.rs
+++ b/src/ui/themes/theme_minimal.rs
@@ -162,3 +162,25 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "$".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Color16 { c16: 8 }),
+ text: Some(AnsiColor::Color16 { c16: 8 }),
+ background: None,
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_nord.rs b/src/ui/themes/theme_nord.rs
index 4811aab..1bc2f6a 100644
--- a/src/ui/themes/theme_nord.rs
+++ b/src/ui/themes/theme_nord.rs
@@ -246,3 +246,37 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Rgb {
+ r: 208,
+ g: 135,
+ b: 112,
+ }),
+ text: Some(AnsiColor::Rgb {
+ r: 208,
+ g: 135,
+ b: 112,
+ }),
+ background: Some(AnsiColor::Rgb {
+ r: 76,
+ g: 86,
+ b: 106,
+ }),
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_powerline_dark.rs b/src/ui/themes/theme_powerline_dark.rs
index d003e07..04e7e08 100644
--- a/src/ui/themes/theme_powerline_dark.rs
+++ b/src/ui/themes/theme_powerline_dark.rs
@@ -246,3 +246,37 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Rgb {
+ r: 255,
+ g: 255,
+ b: 255,
+ }),
+ text: Some(AnsiColor::Rgb {
+ r: 255,
+ g: 255,
+ b: 255,
+ }),
+ background: Some(AnsiColor::Rgb {
+ r: 85,
+ g: 85,
+ b: 85,
+ }),
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_powerline_light.rs b/src/ui/themes/theme_powerline_light.rs
index c747340..2776a4a 100644
--- a/src/ui/themes/theme_powerline_light.rs
+++ b/src/ui/themes/theme_powerline_light.rs
@@ -238,3 +238,37 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Rgb {
+ r: 255,
+ g: 255,
+ b: 255,
+ }),
+ text: Some(AnsiColor::Rgb {
+ r: 255,
+ g: 255,
+ b: 255,
+ }),
+ background: Some(AnsiColor::Rgb {
+ r: 76,
+ g: 175,
+ b: 80,
+ }),
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_powerline_rose_pine.rs b/src/ui/themes/theme_powerline_rose_pine.rs
index f0519b2..70890a8 100644
--- a/src/ui/themes/theme_powerline_rose_pine.rs
+++ b/src/ui/themes/theme_powerline_rose_pine.rs
@@ -246,3 +246,37 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Rgb {
+ r: 235,
+ g: 188,
+ b: 186,
+ }),
+ text: Some(AnsiColor::Rgb {
+ r: 235,
+ g: 188,
+ b: 186,
+ }),
+ background: Some(AnsiColor::Rgb {
+ r: 49,
+ g: 46,
+ b: 65,
+ }),
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}
diff --git a/src/ui/themes/theme_powerline_tokyo_night.rs b/src/ui/themes/theme_powerline_tokyo_night.rs
index c7e449b..21419e6 100644
--- a/src/ui/themes/theme_powerline_tokyo_night.rs
+++ b/src/ui/themes/theme_powerline_tokyo_night.rs
@@ -246,3 +246,37 @@ pub fn usage_segment() -> SegmentConfig {
},
}
}
+
+pub fn quota_segment() -> SegmentConfig {
+ SegmentConfig {
+ id: SegmentId::Quota,
+ enabled: true,
+ icon: IconConfig {
+ plain: "💰".to_string(),
+ nerd_font: "\u{f155}".to_string(),
+ },
+ colors: ColorConfig {
+ icon: Some(AnsiColor::Rgb {
+ r: 247,
+ g: 118,
+ b: 142,
+ }),
+ text: Some(AnsiColor::Rgb {
+ r: 247,
+ g: 118,
+ b: 142,
+ }),
+ background: Some(AnsiColor::Rgb {
+ r: 36,
+ g: 40,
+ b: 59,
+ }),
+ },
+ styles: TextStyleConfig::default(),
+ options: {
+ let mut opts = HashMap::new();
+ opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
+ opts
+ },
+ }
+}