patchcord 0.3.5 → 0.3.6
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/.claude-plugin/plugin.json +1 -1
- package/README.md +0 -154
- package/bin/patchcord.mjs +11 -0
- package/package.json +1 -1
- package/scripts/statusline.sh +50 -154
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchcord",
|
|
3
3
|
"description": "Cross-machine agent messaging with auto-inbox checking. Agents automatically respond to messages from other agents without human intervention.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.6",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ppravdin"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -2,69 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Cross-machine messaging between Claude Code agents.
|
|
4
4
|
|
|
5
|
-
<<<<<<< Updated upstream
|
|
6
|
-
## Install
|
|
7
|
-
||||||| Stash base
|
|
8
|
-
## Setup (3 steps)
|
|
9
|
-
|
|
10
|
-
**1.** Copy `.env.example` to `.env` and paste your token:
|
|
11
|
-
=======
|
|
12
5
|
This plugin is not the connection itself.
|
|
13
6
|
|
|
14
7
|
The plugin provides:
|
|
15
|
-
>>>>>>> Stashed changes
|
|
16
8
|
|
|
17
|
-
<<<<<<< Updated upstream
|
|
18
|
-
```bash
|
|
19
|
-
npx patchcord@latest install
|
|
20
|
-
```
|
|
21
|
-
||||||| Stash base
|
|
22
|
-
```bash
|
|
23
|
-
cp .env.example .env
|
|
24
|
-
# Open .env, replace paste-your-token-here with your actual token
|
|
25
|
-
```
|
|
26
|
-
=======
|
|
27
9
|
- Patchcord skills
|
|
28
10
|
- statusline integration
|
|
29
11
|
- turn-end inbox checks
|
|
30
|
-
>>>>>>> Stashed changes
|
|
31
12
|
|
|
32
|
-
<<<<<<< Updated upstream
|
|
33
|
-
Or with full statusline (model, context%, git branch):
|
|
34
|
-
||||||| Stash base
|
|
35
|
-
**2.** Load the env vars (pick one):
|
|
36
|
-
=======
|
|
37
13
|
The actual Patchcord connection must still come from the current project configuration.
|
|
38
|
-
>>>>>>> Stashed changes
|
|
39
|
-
|
|
40
|
-
<<<<<<< Updated upstream
|
|
41
|
-
```bash
|
|
42
|
-
npx patchcord@latest install --full
|
|
43
|
-
```
|
|
44
|
-
||||||| Stash base
|
|
45
|
-
```bash
|
|
46
|
-
# Option A: add to your shell profile (~/.bashrc or ~/.zshrc)
|
|
47
|
-
echo 'source /path/to/your/.env' >> ~/.bashrc
|
|
48
14
|
|
|
49
|
-
# Option B: use direnv (if you have it)
|
|
50
|
-
cp .env .envrc && direnv allow
|
|
51
|
-
|
|
52
|
-
# Option C: just export manually
|
|
53
|
-
export PATCHCORD_TOKEN="your-token"
|
|
54
|
-
```
|
|
55
|
-
=======
|
|
56
15
|
## Safe model
|
|
57
16
|
|
|
58
17
|
Use this plugin with project-local Patchcord config.
|
|
59
18
|
|
|
60
19
|
Good:
|
|
61
|
-
>>>>>>> Stashed changes
|
|
62
20
|
|
|
63
|
-
<<<<<<< Updated upstream
|
|
64
|
-
The plugin provides skills, statusline integration, and turn-end inbox hooks. The actual Patchcord connection comes from the project's `.mcp.json`.
|
|
65
|
-
||||||| Stash base
|
|
66
|
-
**3.** Install the plugin and start Claude Code:
|
|
67
|
-
=======
|
|
68
21
|
- install the plugin once
|
|
69
22
|
- keep `.mcp.json` inside each Patchcord-enabled project
|
|
70
23
|
- let the plugin no-op in projects that do not have Patchcord configured
|
|
@@ -78,63 +31,12 @@ Bad:
|
|
|
78
31
|
## Setup
|
|
79
32
|
|
|
80
33
|
### 1. Install the plugin
|
|
81
|
-
>>>>>>> Stashed changes
|
|
82
|
-
|
|
83
|
-
<<<<<<< Updated upstream
|
|
84
|
-
## How it works
|
|
85
|
-
|
|
86
|
-
- Install the plugin once (globally)
|
|
87
|
-
- Keep `.mcp.json` inside each Patchcord-enabled project
|
|
88
|
-
- The plugin no-ops in projects without Patchcord configured
|
|
89
|
-
|
|
90
|
-
Don't export `PATCHCORD_TOKEN` / `PATCHCORD_URL` globally or put config in `~/.mcp.json`.
|
|
91
34
|
|
|
92
|
-
## Configure the project
|
|
93
|
-
|
|
94
|
-
Create a project-local `.mcp.json` in the project that should act as a Patchcord agent.
|
|
95
|
-
|
|
96
|
-
```json
|
|
97
|
-
{
|
|
98
|
-
"mcpServers": {
|
|
99
|
-
"patchcord": {
|
|
100
|
-
"type": "http",
|
|
101
|
-
"url": "https://patchcord.yourdomain.com/mcp",
|
|
102
|
-
"headers": {
|
|
103
|
-
"Authorization": "Bearer <project-token>",
|
|
104
|
-
"X-Patchcord-Client-Type": "claude_code"
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
||||||| Stash base
|
|
110
|
-
```bash
|
|
111
|
-
claude plugin marketplace add /path/to/patchcord-internal
|
|
112
|
-
claude plugin install patchcord@patchcord-marketplace
|
|
113
|
-
claude
|
|
114
|
-
=======
|
|
115
35
|
```bash
|
|
116
36
|
claude plugin marketplace add /path/to/patchcord-internal
|
|
117
37
|
claude plugin install patchcord@patchcord-marketplace
|
|
118
|
-
>>>>>>> Stashed changes
|
|
119
38
|
```
|
|
120
39
|
|
|
121
|
-
<<<<<<< Updated upstream
|
|
122
|
-
### 3. Start Claude Code in that project
|
|
123
|
-
|
|
124
|
-
The plugin and statusline scripts read the current project configuration from the session's working tree.
|
|
125
|
-
|
|
126
|
-
## What happens in non-Patchcord projects
|
|
127
|
-
|
|
128
|
-
Nothing Patchcord-specific should appear.
|
|
129
|
-
|
|
130
|
-
- no Patchcord identity in the statusline
|
|
131
|
-
- no inbox checks
|
|
132
|
-
- no hook-driven Patchcord prompts
|
|
133
|
-
|
|
134
|
-
The plugin can stay installed globally, but it must no-op unless the current project is configured.
|
|
135
|
-
||||||| Stash base
|
|
136
|
-
That's it. Inbox, send messages, reply — all works automatically.
|
|
137
|
-
=======
|
|
138
40
|
### 2. Configure the project
|
|
139
41
|
|
|
140
42
|
Create a project-local `.mcp.json` in the project that should act as a Patchcord agent.
|
|
@@ -168,39 +70,10 @@ Nothing Patchcord-specific should appear.
|
|
|
168
70
|
- no hook-driven Patchcord prompts
|
|
169
71
|
|
|
170
72
|
The plugin is allowed to stay installed globally, but it must no-op unless the current project is configured.
|
|
171
|
-
>>>>>>> Stashed changes
|
|
172
73
|
|
|
173
74
|
## Self-hosted server
|
|
174
75
|
|
|
175
|
-
<<<<<<< Updated upstream
|
|
176
|
-
Point the project `.mcp.json` at your own server URL.
|
|
177
|
-
|
|
178
|
-
Bearer-token clients can also use `/mcp/bearer` if you want the dedicated bearer-only endpoint.
|
|
179
|
-
|
|
180
|
-
## What the plugin provides
|
|
181
|
-
|
|
182
|
-
- Stop hook / turn-end inbox check
|
|
183
|
-
- Patchcord skill for Claude
|
|
184
|
-
- statusline identity display
|
|
185
|
-
|
|
186
|
-
The MCP tools themselves come from the project's `.mcp.json` server connection, not from the plugin bundle.
|
|
187
|
-
|
|
188
|
-
## Statusline
|
|
189
|
-
|
|
190
|
-
By default the statusline shows only Patchcord identity and inbox count. In non-Patchcord projects it outputs nothing.
|
|
191
|
-
|
|
192
|
-
To also show model, context usage, repo, and git branch:
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
npx patchcord@latest install --full
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Without `--full`:
|
|
199
|
-
||||||| Stash base
|
|
200
|
-
By default the plugin connects to `https://patchcord.dev`. If you run your own server, add to your `.env`:
|
|
201
|
-
=======
|
|
202
76
|
The project `.mcp.json` should point to your own server URL:
|
|
203
|
-
>>>>>>> Stashed changes
|
|
204
77
|
|
|
205
78
|
```json
|
|
206
79
|
{
|
|
@@ -215,32 +88,6 @@ The project `.mcp.json` should point to your own server URL:
|
|
|
215
88
|
}
|
|
216
89
|
}
|
|
217
90
|
```
|
|
218
|
-
<<<<<<< Updated upstream
|
|
219
|
-
ds@default (thick) 2 msg
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
With `--full`:
|
|
223
|
-
|
|
224
|
-
```
|
|
225
|
-
Opus 4.6 │ 73% │ myproject (main) │ ds@default (thick) 2 msg
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
## Verify
|
|
229
|
-
|
|
230
|
-
In a Patchcord-enabled project:
|
|
231
|
-
|
|
232
|
-
- statusline should show the Patchcord identity and pending message count
|
|
233
|
-
- `inbox()` should return the expected `namespace_id` and `agent_id`
|
|
234
|
-
|
|
235
|
-
In an unrelated project:
|
|
236
|
-
|
|
237
|
-
- statusline should be empty (default) or show only model/context/git (`--full`)
|
|
238
|
-
- no Patchcord hooks should fire
|
|
239
|
-
- no Patchcord tools should be present unless that project is configured
|
|
240
|
-
||||||| Stash base
|
|
241
|
-
PATCHCORD_URL=https://your-server.example.com
|
|
242
|
-
```
|
|
243
|
-
=======
|
|
244
91
|
|
|
245
92
|
## Verify
|
|
246
93
|
|
|
@@ -254,4 +101,3 @@ In an unrelated project:
|
|
|
254
101
|
- statusline should not show Patchcord identity
|
|
255
102
|
- no Patchcord hooks should fire
|
|
256
103
|
- no Patchcord tools should be present unless that project is configured
|
|
257
|
-
>>>>>>> Stashed changes
|
package/bin/patchcord.mjs
CHANGED
|
@@ -77,6 +77,17 @@ Then run: patchcord install`);
|
|
|
77
77
|
process.exit(1);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Disable patchcord as Codex ChatGPT app (prevents OAuth identity conflict)
|
|
81
|
+
const codexConfig = join(process.env.HOME || "", ".codex", "config.toml");
|
|
82
|
+
if (existsSync(codexConfig)) {
|
|
83
|
+
const { readFileSync, writeFileSync } = await import("fs");
|
|
84
|
+
const content = readFileSync(codexConfig, "utf-8");
|
|
85
|
+
if (!content.includes("[apps.patchcord]")) {
|
|
86
|
+
writeFileSync(codexConfig, content.trimEnd() + "\n\n[apps.patchcord]\nenabled = false\n");
|
|
87
|
+
console.log("✓ Disabled patchcord ChatGPT app in Codex (prevents identity conflict).");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
80
91
|
// Enable statusline
|
|
81
92
|
const enableScript = join(pluginRoot, "scripts", "enable-statusline.sh");
|
|
82
93
|
if (existsSync(enableScript)) {
|
package/package.json
CHANGED
package/scripts/statusline.sh
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Patchcord statusline for Claude Code.
|
|
3
|
-
#
|
|
4
|
-
# Default: shows only patchcord identity + inbox count.
|
|
5
|
-
# With --full: also shows model, context%, repo (branch).
|
|
6
|
-
#
|
|
7
|
-
# --full mode model/context/git display based on claude-statusline by Kamran Ahmed
|
|
8
|
-
# https://github.com/kamranahmedse/claude-statusline (MIT)
|
|
9
|
-
#
|
|
3
|
+
# Shows: model | context% | repo (branch) | agent@host [N msg]
|
|
10
4
|
# Receives session JSON on stdin, outputs ANSI-formatted text.
|
|
11
5
|
set -f
|
|
12
6
|
|
|
13
|
-
FULL=false
|
|
14
|
-
for arg in "$@"; do
|
|
15
|
-
[ "$arg" = "--full" ] && FULL=true
|
|
16
|
-
done
|
|
17
|
-
|
|
18
7
|
find_patchcord_mcp_json() {
|
|
19
8
|
local dir="$1"
|
|
20
9
|
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
@@ -30,6 +19,7 @@ find_patchcord_mcp_json() {
|
|
|
30
19
|
input=$(cat)
|
|
31
20
|
|
|
32
21
|
if [ -z "$input" ]; then
|
|
22
|
+
printf "Claude"
|
|
33
23
|
exit 0
|
|
34
24
|
fi
|
|
35
25
|
|
|
@@ -46,10 +36,44 @@ reset='\033[0m'
|
|
|
46
36
|
|
|
47
37
|
sep=" ${dim}│${reset} "
|
|
48
38
|
|
|
49
|
-
# ──
|
|
39
|
+
# ── Model + context ─────────────────────────────────────
|
|
40
|
+
model_name=$(echo "$input" | jq -r '.model.display_name // "Claude"')
|
|
41
|
+
|
|
42
|
+
size=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
|
|
43
|
+
[ "$size" -eq 0 ] 2>/dev/null && size=200000
|
|
44
|
+
|
|
45
|
+
input_tokens=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // 0')
|
|
46
|
+
cache_create=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // 0')
|
|
47
|
+
cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
|
|
48
|
+
current=$(( input_tokens + cache_create + cache_read ))
|
|
49
|
+
|
|
50
|
+
if [ "$size" -gt 0 ]; then
|
|
51
|
+
pct_used=$(( current * 100 / size ))
|
|
52
|
+
else
|
|
53
|
+
pct_used=0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ "$pct_used" -ge 90 ]; then pct_color="$red"
|
|
57
|
+
elif [ "$pct_used" -ge 70 ]; then pct_color="$yellow"
|
|
58
|
+
elif [ "$pct_used" -ge 50 ]; then pct_color="$orange"
|
|
59
|
+
else pct_color="$green"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# ── Directory + git ─────────────────────────────────────
|
|
50
63
|
cwd=$(echo "$input" | jq -r '.cwd // ""')
|
|
51
64
|
[ -z "$cwd" ] || [ "$cwd" = "null" ] && cwd=$(pwd)
|
|
65
|
+
dirname=$(basename "$cwd")
|
|
66
|
+
|
|
67
|
+
git_branch=""
|
|
68
|
+
git_dirty=""
|
|
69
|
+
if git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
70
|
+
git_branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null)
|
|
71
|
+
if [ -n "$(git -C "$cwd" status --porcelain 2>/dev/null)" ]; then
|
|
72
|
+
git_dirty="*"
|
|
73
|
+
fi
|
|
74
|
+
fi
|
|
52
75
|
|
|
76
|
+
# ── Patchcord: agent identity + inbox ───────────────────
|
|
53
77
|
pc_token=""
|
|
54
78
|
pc_url=""
|
|
55
79
|
mcp_json=$(find_patchcord_mcp_json "$cwd" || true)
|
|
@@ -83,54 +107,16 @@ if [ -n "$pc_url" ] && [ -n "$pc_token" ]; then
|
|
|
83
107
|
fi
|
|
84
108
|
|
|
85
109
|
if $needs_refresh; then
|
|
86
|
-
|
|
110
|
+
response=$(curl -sf --max-time 3 \
|
|
87
111
|
-H "Authorization: Bearer $pc_token" \
|
|
88
|
-
<<<<<<< Updated upstream
|
|
89
|
-
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || echo "000")
|
|
90
|
-
if [ "$http_code" = "401" ] || [ "$http_code" = "403" ]; then
|
|
91
|
-
pc_data='{"_auth_error":true}'
|
|
92
|
-
echo "$pc_data" > "$cache_file"
|
|
93
|
-
elif [ "$http_code" = "200" ]; then
|
|
94
|
-
pc_data=$(cat /tmp/claude/patchcord-sl-resp.json 2>/dev/null)
|
|
95
|
-
[ -n "$pc_data" ] && echo "$pc_data" > "$cache_file"
|
|
96
|
-
||||||| Stash base
|
|
97
112
|
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || true)
|
|
98
113
|
if [ -n "$response" ]; then
|
|
99
114
|
pc_data="$response"
|
|
100
115
|
echo "$response" > "$cache_file"
|
|
101
|
-
elif [ -f "$cache_file" ]; then
|
|
102
|
-
pc_data=$(cat "$cache_file" 2>/dev/null)
|
|
103
|
-
=======
|
|
104
|
-
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || true)
|
|
105
|
-
if [ -n "$response" ]; then
|
|
106
|
-
pc_data="$response"
|
|
107
|
-
echo "$response" > "$cache_file"
|
|
108
|
-
>>>>>>> Stashed changes
|
|
109
116
|
fi
|
|
110
|
-
rm -f /tmp/claude/patchcord-sl-resp.json
|
|
111
117
|
fi
|
|
112
118
|
|
|
113
119
|
if [ -n "$pc_data" ]; then
|
|
114
|
-
<<<<<<< Updated upstream
|
|
115
|
-
auth_error=$(echo "$pc_data" | jq -r '._auth_error // false' 2>/dev/null)
|
|
116
|
-
if [ "$auth_error" = "true" ]; then
|
|
117
|
-
pc_part="${red}BAD TOKEN${reset}"
|
|
118
|
-
else
|
|
119
|
-
agent_id=$(echo "$pc_data" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
120
|
-
namespace_id=$(echo "$pc_data" | jq -r '.namespace_id // empty' 2>/dev/null)
|
|
121
|
-
machine=$(echo "$pc_data" | jq -r '.machine_name // empty' 2>/dev/null)
|
|
122
|
-
if [ -z "$machine" ] || [ "$machine" = "null" ]; then
|
|
123
|
-
machine=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
|
124
|
-
||||||| Stash base
|
|
125
|
-
agent_id=$(echo "$pc_data" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
126
|
-
machine=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
|
127
|
-
count=$(echo "$pc_data" | jq -r '.count // .pending_count // 0' 2>/dev/null)
|
|
128
|
-
|
|
129
|
-
if [ -n "$agent_id" ]; then
|
|
130
|
-
pc_part="${white}${agent_id}${reset}"
|
|
131
|
-
if [ -n "$machine" ]; then
|
|
132
|
-
pc_part+="${dim}@${machine}${reset}"
|
|
133
|
-
=======
|
|
134
120
|
agent_id=$(echo "$pc_data" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
135
121
|
namespace_id=$(echo "$pc_data" | jq -r '.namespace_id // empty' 2>/dev/null)
|
|
136
122
|
machine=$(echo "$pc_data" | jq -r '.machine_name // empty' 2>/dev/null)
|
|
@@ -146,117 +132,27 @@ if [ -n "$pc_url" ] && [ -n "$pc_token" ]; then
|
|
|
146
132
|
fi
|
|
147
133
|
if [ -n "$machine" ]; then
|
|
148
134
|
pc_part+=" ${dim}(${machine})${reset}"
|
|
149
|
-
>>>>>>> Stashed changes
|
|
150
|
-
fi
|
|
151
|
-
count=$(echo "$pc_data" | jq -r '.count // .pending_count // 0' 2>/dev/null)
|
|
152
|
-
|
|
153
|
-
if [ -n "$agent_id" ]; then
|
|
154
|
-
pc_part="${white}${agent_id}${reset}"
|
|
155
|
-
if [ -n "$namespace_id" ] && [ "$namespace_id" != "null" ]; then
|
|
156
|
-
pc_part+="${dim}@${namespace_id}${reset}"
|
|
157
|
-
fi
|
|
158
|
-
if [ -n "$machine" ]; then
|
|
159
|
-
pc_part+=" ${dim}(${machine})${reset}"
|
|
160
|
-
fi
|
|
161
|
-
fi
|
|
162
|
-
|
|
163
|
-
if [ "$count" -gt 0 ] 2>/dev/null; then
|
|
164
|
-
pc_part+=" ${red}${count} msg${reset}"
|
|
165
135
|
fi
|
|
166
136
|
fi
|
|
167
|
-
fi
|
|
168
|
-
fi
|
|
169
137
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
plugin_json="${CLAUDE_PLUGIN_ROOT:-.}/.claude-plugin/plugin.json"
|
|
173
|
-
if [ -f "$plugin_json" ]; then
|
|
174
|
-
installed_ver=$(jq -r '.version // ""' "$plugin_json" 2>/dev/null)
|
|
175
|
-
if [ -n "$installed_ver" ]; then
|
|
176
|
-
update_cache="/tmp/claude/patchcord-update-check.json"
|
|
177
|
-
mkdir -p /tmp/claude
|
|
178
|
-
update_stale=true
|
|
179
|
-
if [ -f "$update_cache" ]; then
|
|
180
|
-
uc_mtime=$(stat -c %Y "$update_cache" 2>/dev/null || stat -f %m "$update_cache" 2>/dev/null)
|
|
181
|
-
uc_now=$(date +%s)
|
|
182
|
-
[ $(( uc_now - uc_mtime )) -lt 86400 ] && update_stale=false
|
|
183
|
-
fi
|
|
184
|
-
if $update_stale; then
|
|
185
|
-
latest=$(npm view patchcord version --json 2>/dev/null | tr -d '"' || true)
|
|
186
|
-
if [ -n "$latest" ]; then
|
|
187
|
-
echo "{\"latest\":\"$latest\"}" > "$update_cache"
|
|
188
|
-
fi
|
|
189
|
-
else
|
|
190
|
-
latest=$(jq -r '.latest // ""' "$update_cache" 2>/dev/null)
|
|
191
|
-
fi
|
|
192
|
-
if [ -n "$latest" ] && [ "$latest" != "$installed_ver" ]; then
|
|
193
|
-
update_part="${yellow}⬆ ${latest} (npm update -g patchcord)${reset}"
|
|
138
|
+
if [ "$count" -gt 0 ] 2>/dev/null; then
|
|
139
|
+
pc_part+=" ${red}${count} msg${reset}"
|
|
194
140
|
fi
|
|
195
141
|
fi
|
|
196
142
|
fi
|
|
197
143
|
|
|
198
|
-
# No patchcord config — output nothing in default mode
|
|
199
|
-
if [ -z "$pc_part" ] && [ -z "$update_part" ] && ! $FULL; then
|
|
200
|
-
exit 0
|
|
201
|
-
fi
|
|
202
|
-
|
|
203
144
|
# ── Build line ──────────────────────────────────────────
|
|
204
|
-
line=""
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
|
|
214
|
-
current=$(( input_tokens + cache_create + cache_read ))
|
|
215
|
-
if [ "$size" -gt 0 ]; then
|
|
216
|
-
pct_used=$(( current * 100 / size ))
|
|
217
|
-
else
|
|
218
|
-
pct_used=0
|
|
219
|
-
fi
|
|
220
|
-
if [ "$pct_used" -ge 90 ]; then pct_color="$red"
|
|
221
|
-
elif [ "$pct_used" -ge 70 ]; then pct_color="$yellow"
|
|
222
|
-
elif [ "$pct_used" -ge 50 ]; then pct_color="$orange"
|
|
223
|
-
else pct_color="$green"
|
|
224
|
-
fi
|
|
225
|
-
|
|
226
|
-
dirname=$(basename "$cwd")
|
|
227
|
-
git_branch=""
|
|
228
|
-
git_dirty=""
|
|
229
|
-
if git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
230
|
-
git_branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null)
|
|
231
|
-
if [ -n "$(git -C "$cwd" status --porcelain 2>/dev/null)" ]; then
|
|
232
|
-
git_dirty="*"
|
|
233
|
-
fi
|
|
234
|
-
fi
|
|
235
|
-
|
|
236
|
-
line="${blue}${model_name}${reset}"
|
|
237
|
-
line+="${sep}"
|
|
238
|
-
line+="${pct_color}${pct_used}%${reset}"
|
|
145
|
+
line="${blue}${model_name}${reset}"
|
|
146
|
+
line+="${sep}"
|
|
147
|
+
line+="${pct_color}${pct_used}%${reset}"
|
|
148
|
+
line+="${sep}"
|
|
149
|
+
line+="${cyan}${dirname}${reset}"
|
|
150
|
+
if [ -n "$git_branch" ]; then
|
|
151
|
+
line+=" ${green}(${git_branch}${red}${git_dirty}${green})${reset}"
|
|
152
|
+
fi
|
|
153
|
+
if [ -n "$pc_part" ]; then
|
|
239
154
|
line+="${sep}"
|
|
240
|
-
line+="${
|
|
241
|
-
if [ -n "$git_branch" ]; then
|
|
242
|
-
line+=" ${green}(${git_branch}${red}${git_dirty}${green})${reset}"
|
|
243
|
-
fi
|
|
244
|
-
if [ -n "$pc_part" ]; then
|
|
245
|
-
line+="${sep}"
|
|
246
|
-
line+="${pc_part}"
|
|
247
|
-
fi
|
|
248
|
-
if [ -n "$update_part" ]; then
|
|
249
|
-
line+="${sep}"
|
|
250
|
-
line+="${update_part}"
|
|
251
|
-
fi
|
|
252
|
-
else
|
|
253
|
-
line="${pc_part}"
|
|
254
|
-
if [ -n "$update_part" ]; then
|
|
255
|
-
if [ -n "$line" ]; then
|
|
256
|
-
line+="${sep}"
|
|
257
|
-
fi
|
|
258
|
-
line+="${update_part}"
|
|
259
|
-
fi
|
|
155
|
+
line+="${pc_part}"
|
|
260
156
|
fi
|
|
261
157
|
|
|
262
158
|
# ── Output ──────────────────────────────────────────────
|