Przeglądaj źródła

feat(claude): add Claude Code integration

Joe 1 miesiąc temu
rodzic
commit
83902b39df

+ 2 - 1
.config/brew/Brewfile

@@ -64,6 +64,8 @@ brew "pgcli"
 brew "tmux"
 
 # CLI
+brew "ccusage"
+brew "claude"
 brew "coreutils"
 brew "cowsay"
 brew "fd"
@@ -72,7 +74,6 @@ brew "fortune"
 brew "fswatch"
 brew "fzf"
 brew "gcc"
-brew "gemini-cli"
 brew "gh"
 brew "git"
 brew "gnu-sed"

+ 106 - 0
.config/nvim/custom/status-beast/lua/status-beast/init.lua

@@ -8,6 +8,14 @@ if not unpack then unpack = table.unpack end
 
 local setup = function()
     local maps = require("status-beast.maps")
+
+    local claude_usage_cache = {
+        data = nil,
+        last_update = 0,
+        update_interval = 45,
+        updating = false
+    }
+
     -- Gutter options
     vim.opt.number = true
     vim.opt.relativenumber = true
@@ -74,6 +82,85 @@ local setup = function()
         return maps.mode_map[mode_code] == nil and "Other" or
             maps.mode_map[mode_code]
     end
+
+    local update_claude_usage_async = function()
+        if claude_usage_cache.updating then return end
+
+        local claude_dir = vim.fn.getcwd() .. "/.claude"
+        if vim.fn.isdirectory(claude_dir) == 0 or vim.fn.executable("ccusage") == 0 then
+            claude_usage_cache.data = nil
+            claude_usage_cache.last_update = os.time()
+            return
+        end
+
+        local ok, Job = pcall(require, "plenary.job")
+        if not ok then return end
+
+        claude_usage_cache.updating = true
+
+        local usage = {}
+        local completed = 0
+
+        local on_complete = function()
+            completed = completed + 1
+            if completed == 3 then
+                claude_usage_cache.data = usage
+                claude_usage_cache.last_update = os.time()
+                claude_usage_cache.updating = false
+                vim.schedule(function() vim.cmd("redrawtabline") end)
+            end
+        end
+
+        local parse_and_store = function(j, return_val, key, data_key, index_key)
+            if return_val == 0 then
+                local ok_parse, data = pcall(vim.json.decode,
+                    table.concat(j:result(), "\n"))
+                if ok_parse and data[data_key] and #data[data_key] > 0 then
+                    if index_key then
+                        usage[key] = data[data_key][#data[data_key]][index_key]
+                    else
+                        local total = 0
+                        for _, item in ipairs(data[data_key]) do
+                            total = total + item.totalCost
+                        end
+                        usage[key] = total / #data[data_key]
+                    end
+                end
+            end
+            on_complete()
+        end
+
+        Job:new({
+            command = "ccusage",
+            args = { "monthly", "--json" },
+            on_exit = vim.schedule_wrap(function(j, ret)
+                parse_and_store(j, ret, "month", "monthly", "totalCost")
+            end),
+        }):start()
+
+        Job:new({
+            command = "ccusage",
+            args = { "weekly", "--json" },
+            on_exit = vim.schedule_wrap(function(j, ret)
+                parse_and_store(j, ret, "week", "weekly", "totalCost")
+            end),
+        }):start()
+
+        Job:new({
+            command = "ccusage",
+            args = { "daily", "--json", "--since", os.date("%Y%m%d", os.time() - 30 * 24 * 60 * 60) },
+            on_exit = vim.schedule_wrap(function(j, ret)
+                parse_and_store(j, ret, "avg_day", "daily", nil)
+            end),
+        }):start()
+    end
+
+    local get_claude_usage = function()
+        if os.time() - claude_usage_cache.last_update >= claude_usage_cache.update_interval then
+            update_claude_usage_async()
+        end
+        return claude_usage_cache.data
+    end
     _G.StatusBeast = {
         column = function()
             local gitsign = get_gitsigns()
@@ -169,6 +256,25 @@ local setup = function()
                         v["name"])
                 end
             end
+            -- Claude usage
+            local usage = get_claude_usage()
+            if usage then
+                local parts = {}
+                if usage.month then
+                    table.insert(parts, string.format("M%.0f", usage.month))
+                end
+                if usage.week then
+                    table.insert(parts, string.format("W%.0f", usage.week))
+                end
+                if usage.avg_day then
+                    table.insert(parts, string.format("D̄%.0f", usage.avg_day))
+                end
+                if #parts > 0 then
+                    table.insert(s,
+                        "%#StatusBeastBarIcon#󱚥 %#StatusBeastBarNormal#" ..
+                        table.concat(parts, " "))
+                end
+            end
             -- Git
             local status_dict = vim.b.gitsigns_status_dict;
             if (status_dict ~= nil) then

+ 1 - 1
.config/nvim/init.lua

@@ -424,7 +424,7 @@ local function config_like_a_butterfly()
     MakeTerm("ts", "Beta", "zsh")
     MakeTerm("tr", "Gamma", "zsh")
     MakeTerm("ta", "Delta", "zsh")
-    MakeTerm("tn", "Epsilon", "gemini --model gemini-2.5-pro")
+    MakeTerm("tn", "Epsilon", "claude")
     MakeTerm("te", "Zeta", "/bin/zsh $DOTFILES_DIR/.scripts/omniscratch.zsh")
     MakeTerm("ti", "Eta", "lazydocker", true)
     MakeTerm("to", "Theta", "lazygit", true)