Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·145 lines (131 loc) · 6.73 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·145 lines (131 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env bash
# Install the tailbell agent side — run this on the machine where Claude Code
# itself runs (the cluster login node, in the Remote-SSH case).
#
# If you installed tailbell as a Claude Code plugin, you do NOT need this: the
# plugin's hooks/hooks.json registers the same hooks automatically. Use this when
# you want the hooks in your own ~/.claude/settings.json instead, pointing at this
# checkout.
set -euo pipefail
REPO="$(cd "$(dirname "$0")" && pwd)"
TB="$HOME/.tailbell"
echo "==> 1/3 检查依赖"
# Required: without these the hook can do nothing at all.
missing=""
for t in jq hostname stat tee date; do
command -v "$t" >/dev/null 2>&1 || missing="$missing $t"
done
if [ -n "$missing" ]; then
echo " ❌ 缺少:$missing"
echo " tailbell 会静默失效。装上再来。"
exit 1
fi
# flock is NOT required, and treating it as required made this script exit 1 on
# every Mac — macOS has no flock(1) at all, so the agent side could not be
# installed on the machine release 4 exists to support. Caught by CI on
# macos-latest, which is what that runner is for.
#
# What it actually buys: serialising concurrent sessions appending to one log on
# a shared NFS $HOME. That is the cluster case. Without it the sink falls back to
# a plain append, which is fine on a local filesystem.
if command -v flock >/dev/null 2>&1; then
echo " jq / flock / coreutils 都在"
else
echo " jq / coreutils 都在"
echo " ⚠️ 没有 flock(macOS 本来就没有)—— 并发写日志退回普通追加。"
echo " 本地文件系统上没问题;共享 NFS 上多个会话同时写才需要它。"
fi
echo "==> 2/3 建立 $TB"
mkdir -p "$TB/state"
if [ ! -f "$TB/config" ]; then
cat > "$TB/config" <<'EOF'
# tailbell agent config.
#
# ---------------------------------------------------------------------------
# Channels: where a notification is sent. A comma-separated list; every name in
# it is tried, and a failure in one never stops another.
#
# file — append to events.log; the workstation tails it over the SSH
# connection your editor already holds. No third party, no account,
# no quota, and it works from compute nodes because $HOME is one
# shared NFS mount. This is the guaranteed path: leave it in.
# ntfy — push to a phone, reaches you with every editor closed.
# slack / discord / feishu — post to an incoming webhook.
#
# Everything after `file` puts a third party in the path, which is why none of
# it is on by default. Leave TAILBELL_CHANNELS commented out and tailbell
# behaves exactly as it did before channels existed.
#TAILBELL_CHANNELS="file,ntfy"
TAILBELL_TRANSPORT="file" # legacy name for a single channel; still honoured
# Turns shorter than this are not worth interrupting you for — you were watching.
TAILBELL_MIN_SECONDS=60
# ---------------------------------------------------------------------------
# ntfy. THE TOPIC IS THE PASSWORD: anyone who knows it reads every notification
# you send, so make it long and random —
# head -c 18 /dev/urandom | base64 | tr -d '/+='
# and note that a *free* ntfy.sh account cannot reserve or privatise a topic.
# Measured: limits.basis is "ip" for a free account exactly as for an anonymous
# one — same 250/day, still metered on this login node's shared address.
#TAILBELL_NTFY_TOPIC=""
#TAILBELL_NTFY_SERVER="https://ntfy.sh"
#TAILBELL_NTFY_TOKEN=""
# ---------------------------------------------------------------------------
# Webhooks. Each of these URLs *is* a credential — whoever holds it can post as
# you. This file is chmod 600 for that reason; keep it that way, and remember a
# shared login node has other people's root on it.
#TAILBELL_SLACK_WEBHOOK=""
#TAILBELL_DISCORD_WEBHOOK=""
#TAILBELL_FEISHU_WEBHOOK=""
#TAILBELL_FEISHU_SECRET="" # only if the bot is in "signed request" mode
# ---------------------------------------------------------------------------
# Compute nodes reach the outside through ARC's preset http_proxy and curl picks
# that up on its own. Set this only to override a preset one that is wrong.
#TAILBELL_HTTP_PROXY=""
#TAILBELL_HTTP_TIMEOUT=8
# ---------------------------------------------------------------------------
# Approve or deny a permission prompt from your phone. Terminal CLI only — in
# the VS Code chat panel there is no permission event to hook (measured; see
# docs/architecture.md §1).
#
# Register the hook with: tailbell-register --approve
# Then turn it on here. Both steps are needed, deliberately: this hook holds the
# tool call for up to TTL seconds while it waits for you, which is what you want
# when you are away from the keyboard and not what you want when you are at it.
#
# TAILBELL_APPROVE_TOOLS is REQUIRED and doubles as the hook's matcher. The hook
# runs before every matching tool call, not only the ones that would have
# prompted, so an empty list means a phone push hundreds of times a session —
# tailbell-register refuses without it.
#
# THE APPROVAL TOPIC MUST NOT BE THE NOTIFICATION TOPIC. Anyone who can read the
# topic can answer the prompt, and your notification topic is the one that ends
# up in screenshots. tailbell refuses to run if you set them to the same value.
#TAILBELL_APPROVE=0
#TAILBELL_APPROVE_TOPIC="" # a SECOND, long random topic, not the one above
#TAILBELL_APPROVE_TOKEN="" # ntfy auth token — strongly recommended here
#TAILBELL_APPROVE_TTL=90
#TAILBELL_APPROVE_TOOLS="Bash,Write" # required; also the hook matcher
EOF
chmod 600 "$TB/config"
echo " 写入 $TB/config"
else
echo " $TB/config 已存在,保留"
fi
echo "==> 3/3 注册 hooks 到 ~/.claude/settings.json"
# Delegated to tailbell-register rather than repeated here. Keeping a second
# copy of the merge meant this script registered five events while the register
# script registered seven — so StopFailure and Elicitation silently did nothing
# for anyone who installed the documented way. It also creates
# ~/.tailbell/cluster-id, which the workstation listener uses to open exactly one
# stream per cluster; without that file the listener skips the host entirely and
# you get silence with every other check green.
bash "$REPO/bin/tailbell-register" "$REPO/bin/tailbell-notify" | sed 's/^/ /'
cat <<DONE
────────────────────────────────────────────────
agent 侧装好了。设置是热加载的,不需要重启 Claude Code。
自查:
$REPO/bin/tailbell-doctor --test
接下来在你的工作站上装接收端:
macOS → scp -r <this-host>:$REPO /tmp/tailbell && bash /tmp/tailbell/mac/install.sh
────────────────────────────────────────────────
DONE