lean-claudient-shell 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/bash-init.sh +14 -0
- package/fish-init.fish +41 -0
- package/install-shell.sh +47 -0
- package/package.json +39 -0
- package/powerline-segment.py +54 -0
- package/src/queryDaemon.sh +37 -0
- package/zsh-init.sh +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Lean Claudient Shell Integration
|
|
2
|
+
|
|
3
|
+
Real-time token status in your shell prompt.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Automatic
|
|
8
|
+
```bash
|
|
9
|
+
bash packages/shell-integration/install-shell.sh
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Manual Bash
|
|
13
|
+
Add to ~/.bashrc:
|
|
14
|
+
```bash
|
|
15
|
+
source /path/to/lean-claudient/packages/shell-integration/bash-init.sh
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Manual Zsh
|
|
19
|
+
Add to ~/.zshrc:
|
|
20
|
+
```bash
|
|
21
|
+
source /path/to/lean-claudient/packages/shell-integration/zsh-init.sh
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Manual Fish
|
|
25
|
+
Copy fish-init.fish to ~/.config/fish/conf.d/lean-claudient.fish
|
|
26
|
+
|
|
27
|
+
### Powerline
|
|
28
|
+
Copy powerline-segment.py to ~/.config/powerline/segments/custom/lean_claudient.py
|
|
29
|
+
|
|
30
|
+
## Status Format
|
|
31
|
+
|
|
32
|
+
`[💰 $X.XX | 📊 Y.Yx | 🔄 Z]`
|
|
33
|
+
|
|
34
|
+
- 💰 Cost spent this session
|
|
35
|
+
- 📊 Compression ratio achieved
|
|
36
|
+
- 🔄 Active subagents
|
|
37
|
+
|
|
38
|
+
## Performance
|
|
39
|
+
|
|
40
|
+
- Status cached for 5 seconds (no lag on every keystroke)
|
|
41
|
+
- Falls back gracefully if daemon not running
|
|
42
|
+
- <50ms added to prompt rendering
|
package/bash-init.sh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Add to ~/.bashrc
|
|
2
|
+
# Lean Claudient Status Integration
|
|
3
|
+
|
|
4
|
+
_lean_status_prompt() {
|
|
5
|
+
local status=$(bash "$(dirname "${BASH_SOURCE[0]}")"/src/queryDaemon.sh 2>/dev/null)
|
|
6
|
+
if [[ -n "$status" ]]; then
|
|
7
|
+
echo " $status"
|
|
8
|
+
fi
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# Only add status if it doesn't already exist in PS1
|
|
12
|
+
if [[ ! "$PS1" =~ "lean_status" ]]; then
|
|
13
|
+
export PS1="${PS1%\\\$ }$(_lean_status_prompt)\\\$ "
|
|
14
|
+
fi
|
package/fish-init.fish
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Add to ~/.config/fish/config.fish
|
|
2
|
+
# Lean Claudient Status Integration
|
|
3
|
+
|
|
4
|
+
function lean_status --description "Query Lean Claudient daemon status"
|
|
5
|
+
set -l cache_file /tmp/.lean_claudient_status
|
|
6
|
+
set -l cache_ttl 5
|
|
7
|
+
|
|
8
|
+
# Check cache
|
|
9
|
+
if test -f $cache_file
|
|
10
|
+
set -l age (math (date +%s) - (stat -f %m $cache_file 2>/dev/null || stat -c %Y $cache_file 2>/dev/null))
|
|
11
|
+
if test $age -lt $cache_ttl
|
|
12
|
+
cat $cache_file
|
|
13
|
+
return 0
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Query daemon
|
|
18
|
+
set -l result (curl -s --connect-timeout 1 --max-time 2 http://localhost:9831/api/metrics 2>/dev/null)
|
|
19
|
+
if test -z "$result"
|
|
20
|
+
return 1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Parse JSON
|
|
24
|
+
set -l cost (echo "$result" | jq -r '.totalCost // "$0.00"' 2>/dev/null)
|
|
25
|
+
set -l saved (echo "$result" | jq -r '.averageCompressionRatio // "0"' 2>/dev/null)
|
|
26
|
+
set -l subagents (echo "$result" | jq -r '.averageSubagentCount // "0"' 2>/dev/null)
|
|
27
|
+
|
|
28
|
+
# Format and cache
|
|
29
|
+
set -l status "[💰 $cost | 📊 ${saved}x | 🔄 $subagents]"
|
|
30
|
+
echo -n "$status" > $cache_file
|
|
31
|
+
echo "$status"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Integrate into prompt
|
|
35
|
+
function fish_prompt
|
|
36
|
+
set -l status_line (lean_status 2>/dev/null)
|
|
37
|
+
if test -n "$status_line"
|
|
38
|
+
echo -n "$status_line "
|
|
39
|
+
end
|
|
40
|
+
echo -n "❯ "
|
|
41
|
+
end
|
package/install-shell.sh
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
BASH_INIT="$SCRIPT_DIR/bash-init.sh"
|
|
7
|
+
ZSH_INIT="$SCRIPT_DIR/zsh-init.sh"
|
|
8
|
+
FISH_INIT="$SCRIPT_DIR/fish-init.fish"
|
|
9
|
+
|
|
10
|
+
echo "Lean Claudient: Installing shell integration..."
|
|
11
|
+
|
|
12
|
+
# Bash
|
|
13
|
+
if [[ -f ~/.bashrc ]]; then
|
|
14
|
+
if ! grep -q "lean-claudient" ~/.bashrc; then
|
|
15
|
+
echo "" >> ~/.bashrc
|
|
16
|
+
echo "# Lean Claudient Status Integration" >> ~/.bashrc
|
|
17
|
+
echo "source \"$BASH_INIT\"" >> ~/.bashrc
|
|
18
|
+
echo "✓ Installed bash hook"
|
|
19
|
+
fi
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Zsh
|
|
23
|
+
if [[ -f ~/.zshrc ]]; then
|
|
24
|
+
if ! grep -q "lean-claudient" ~/.zshrc; then
|
|
25
|
+
echo "" >> ~/.zshrc
|
|
26
|
+
echo "# Lean Claudient Status Integration" >> ~/.zshrc
|
|
27
|
+
echo "source \"$ZSH_INIT\"" >> ~/.zshrc
|
|
28
|
+
echo "✓ Installed zsh hook"
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Fish
|
|
33
|
+
if [[ -d ~/.config/fish/conf.d ]]; then
|
|
34
|
+
FISH_CONF="$HOME/.config/fish/conf.d/lean-claudient.fish"
|
|
35
|
+
if [[ ! -f "$FISH_CONF" ]]; then
|
|
36
|
+
cp "$FISH_INIT" "$FISH_CONF"
|
|
37
|
+
echo "✓ Installed fish hook"
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Powerline
|
|
42
|
+
if [[ -d ~/.config/powerline/segments/custom ]]; then
|
|
43
|
+
cp "$SCRIPT_DIR/powerline-segment.py" ~/.config/powerline/segments/custom/lean_claudient.py
|
|
44
|
+
echo "✓ Installed powerline segment"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "Installation complete. Restart your shell or run: source ~/.bashrc (or ~/.zshrc)"
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lean-claudient-shell",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shell integration for Lean Claudient: prompt status line hooks",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"author": "Lean Claudient Contributors",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/Claudient/LeanClaudient#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/Claudient/LeanClaudient.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Claudient/LeanClaudient/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"claude",
|
|
18
|
+
"shell",
|
|
19
|
+
"prompt",
|
|
20
|
+
"status-line",
|
|
21
|
+
"llm",
|
|
22
|
+
"anthropic"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "echo 'Shell integration scripts (no compilation needed)'",
|
|
26
|
+
"dev": "echo 'Shell integration development mode'",
|
|
27
|
+
"test": "echo 'integration tests pending'",
|
|
28
|
+
"test:watch": "echo 'integration tests pending'",
|
|
29
|
+
"test:coverage": "echo 'integration tests pending'",
|
|
30
|
+
"lint": "echo 'linter pending'",
|
|
31
|
+
"format": "echo 'formatter pending'",
|
|
32
|
+
"type-check": "echo 'Shell scripts do not require type checking'",
|
|
33
|
+
"install": "bash install-shell.sh"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^5.3.2",
|
|
37
|
+
"@types/node": "^20.10.0"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Save to ~/.config/powerline/segments/custom/lean_claudient.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
import os
|
|
7
|
+
from powerline.segments import Segment, register_segment
|
|
8
|
+
|
|
9
|
+
@register_segment('custom:lean_claudient')
|
|
10
|
+
class LeanClaudientSegment(Segment):
|
|
11
|
+
def __call__(self, pl, segment_info):
|
|
12
|
+
cache_file = '/tmp/.lean_claudient_status'
|
|
13
|
+
cache_ttl = 5
|
|
14
|
+
|
|
15
|
+
# Check cache
|
|
16
|
+
if os.path.exists(cache_file):
|
|
17
|
+
age = time.time() - os.path.getmtime(cache_file)
|
|
18
|
+
if age < cache_ttl:
|
|
19
|
+
with open(cache_file) as f:
|
|
20
|
+
status = f.read().strip()
|
|
21
|
+
if status:
|
|
22
|
+
return [
|
|
23
|
+
{'contents': status, 'highlight_group': 'lean_claudient_normal'}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# Query daemon
|
|
27
|
+
try:
|
|
28
|
+
result = subprocess.run(
|
|
29
|
+
['curl', '-s', '--connect-timeout', '1', '--max-time', '2',
|
|
30
|
+
'http://localhost:9831/api/metrics'],
|
|
31
|
+
capture_output=True,
|
|
32
|
+
text=True,
|
|
33
|
+
timeout=3
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if result.returncode == 0:
|
|
37
|
+
data = json.loads(result.stdout)
|
|
38
|
+
cost = data.get('totalCost', '$0.00')
|
|
39
|
+
saved = data.get('averageCompressionRatio', 0)
|
|
40
|
+
subagents = data.get('averageSubagentCount', 0)
|
|
41
|
+
|
|
42
|
+
status = f"[💰 {cost} | 📊 {saved}x | 🔄 {subagents}]"
|
|
43
|
+
|
|
44
|
+
# Cache result
|
|
45
|
+
with open(cache_file, 'w') as f:
|
|
46
|
+
f.write(status)
|
|
47
|
+
|
|
48
|
+
return [
|
|
49
|
+
{'contents': status, 'highlight_group': 'lean_claudient_normal'}
|
|
50
|
+
]
|
|
51
|
+
except:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
return []
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Query daemon with 5-second cache
|
|
4
|
+
CACHE_FILE="/tmp/.lean_claudient_status"
|
|
5
|
+
CACHE_TTL=5
|
|
6
|
+
|
|
7
|
+
get_lean_status() {
|
|
8
|
+
local now=$(date +%s)
|
|
9
|
+
|
|
10
|
+
# Check cache
|
|
11
|
+
if [[ -f "$CACHE_FILE" ]]; then
|
|
12
|
+
local mtime=$(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE" 2>/dev/null)
|
|
13
|
+
if (( now - mtime < CACHE_TTL )); then
|
|
14
|
+
cat "$CACHE_FILE"
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Query daemon
|
|
20
|
+
local result=$(curl -s --connect-timeout 1 --max-time 2 http://localhost:9831/api/metrics 2>/dev/null)
|
|
21
|
+
if [[ -z "$result" ]]; then
|
|
22
|
+
echo ""
|
|
23
|
+
return 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Parse JSON
|
|
27
|
+
local cost=$(echo "$result" | jq -r '.totalCost // "$0.00"' 2>/dev/null)
|
|
28
|
+
local saved=$(echo "$result" | jq -r '.averageCompressionRatio // "0"' 2>/dev/null)
|
|
29
|
+
local subagents=$(echo "$result" | jq -r '.averageSubagentCount // "0"' 2>/dev/null)
|
|
30
|
+
|
|
31
|
+
# Format and cache
|
|
32
|
+
local status="[💰 $cost | 📊 ${saved}x | 🔄 $subagents]"
|
|
33
|
+
echo -n "$status" > "$CACHE_FILE"
|
|
34
|
+
echo "$status"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get_lean_status
|
package/zsh-init.sh
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Add to ~/.zshrc
|
|
2
|
+
# Lean Claudient Status Integration
|
|
3
|
+
|
|
4
|
+
_lean_status_precmd() {
|
|
5
|
+
LEAN_STATUS=$(bash "$(dirname "${(%):-%x}")"/src/queryDaemon.sh 2>/dev/null)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
precmd_functions+=(_lean_status_precmd)
|
|
9
|
+
|
|
10
|
+
# Only add status if it doesn't already exist in PS1
|
|
11
|
+
if [[ ! "$PS1" =~ "LEAN_STATUS" ]]; then
|
|
12
|
+
export PS1="${PS1%% %} ${LEAN_STATUS}% "
|
|
13
|
+
fi
|