247-cli 0.8.3 → 1.0.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/agent/dist/db/index.d.ts.map +1 -1
- package/agent/dist/db/index.js +41 -2
- package/agent/dist/db/index.js.map +1 -1
- package/agent/dist/db/schema.d.ts +12 -2
- package/agent/dist/db/schema.d.ts.map +1 -1
- package/agent/dist/db/schema.js +8 -2
- package/agent/dist/db/schema.js.map +1 -1
- package/agent/dist/db/sessions.d.ts +5 -0
- package/agent/dist/db/sessions.d.ts.map +1 -1
- package/agent/dist/db/sessions.js +21 -3
- package/agent/dist/db/sessions.js.map +1 -1
- package/agent/dist/heartbeat-monitor.d.ts +20 -0
- package/agent/dist/heartbeat-monitor.d.ts.map +1 -0
- package/agent/dist/heartbeat-monitor.js +99 -0
- package/agent/dist/heartbeat-monitor.js.map +1 -0
- package/agent/dist/routes/heartbeat.d.ts +10 -0
- package/agent/dist/routes/heartbeat.d.ts.map +1 -0
- package/agent/dist/routes/heartbeat.js +103 -0
- package/agent/dist/routes/heartbeat.js.map +1 -0
- package/agent/dist/routes/index.d.ts +1 -1
- package/agent/dist/routes/index.d.ts.map +1 -1
- package/agent/dist/routes/index.js +1 -1
- package/agent/dist/routes/index.js.map +1 -1
- package/agent/dist/routes/sessions.d.ts.map +1 -1
- package/agent/dist/routes/sessions.js +30 -1
- package/agent/dist/routes/sessions.js.map +1 -1
- package/agent/dist/server.d.ts.map +1 -1
- package/agent/dist/server.js +10 -2
- package/agent/dist/server.js.map +1 -1
- package/agent/dist/setup-statusline.d.ts +10 -0
- package/agent/dist/setup-statusline.d.ts.map +1 -0
- package/agent/dist/setup-statusline.js +94 -0
- package/agent/dist/setup-statusline.js.map +1 -0
- package/agent/dist/status.d.ts +6 -0
- package/agent/dist/status.d.ts.map +1 -1
- package/agent/dist/status.js.map +1 -1
- package/agent/dist/websocket-handlers.d.ts.map +1 -1
- package/agent/dist/websocket-handlers.js +19 -2
- package/agent/dist/websocket-handlers.js.map +1 -1
- package/agent/node_modules/247-shared/dist/types/index.d.ts +6 -1
- package/agent/node_modules/247-shared/dist/types/index.d.ts.map +1 -1
- package/agent/node_modules/247-shared/dist/types/index.js.map +1 -1
- package/agent/node_modules/247-shared/package.json +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +8 -11
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/hooks.d.ts.map +1 -1
- package/dist/commands/hooks.js +37 -89
- package/dist/commands/hooks.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +0 -21
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +0 -18
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +6 -9
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +0 -10
- package/dist/commands/update.js.map +1 -1
- package/dist/hooks/installer.d.ts +4 -21
- package/dist/hooks/installer.d.ts.map +1 -1
- package/dist/hooks/installer.js +6 -129
- package/dist/hooks/installer.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/paths.d.ts +1 -3
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +1 -5
- package/dist/lib/paths.js.map +1 -1
- package/package.json +1 -1
- package/agent/dist/routes/hooks.d.ts +0 -6
- package/agent/dist/routes/hooks.d.ts.map +0 -1
- package/agent/dist/routes/hooks.js +0 -80
- package/agent/dist/routes/hooks.js.map +0 -1
- package/hooks/.claude-plugin/plugin.json +0 -5
- package/hooks/hooks/hooks.json +0 -66
- package/hooks/scripts/check-duplication.sh +0 -91
- package/hooks/scripts/notify-status.sh +0 -89
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const program = new Command();
|
|
|
15
15
|
program
|
|
16
16
|
.name('247')
|
|
17
17
|
.description('247 - Access Claude Code from anywhere 24/7\nby The Vibe Company')
|
|
18
|
-
.version('0.
|
|
18
|
+
.version('1.0.0')
|
|
19
19
|
.option('-P, --profile <name>', 'Use a specific profile (dev, prod, etc.)');
|
|
20
20
|
// Add commands
|
|
21
21
|
program.addCommand(initCommand);
|
package/dist/lib/paths.d.ts
CHANGED
|
@@ -9,9 +9,7 @@ export interface AgentPaths {
|
|
|
9
9
|
cliRoot: string;
|
|
10
10
|
/** Where the agent server code is located */
|
|
11
11
|
agentRoot: string;
|
|
12
|
-
/** Where
|
|
13
|
-
hooksSource: string;
|
|
14
|
-
/** Where hooks should be installed for Claude Code */
|
|
12
|
+
/** Where old hooks were installed (for cleanup) */
|
|
15
13
|
hooksDestination: string;
|
|
16
14
|
/** Configuration directory (~/.247/) */
|
|
17
15
|
configDir: string;
|
package/dist/lib/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAEhB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAElB,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAEhB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAC;IAEzB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAElB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IAEnB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAEhB,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IAEf,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAC;CAChB;AAID,wBAAgB,aAAa,IAAI,UAAU,CAkD1C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAUxC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|
package/dist/lib/paths.js
CHANGED
|
@@ -22,16 +22,13 @@ export function getAgentPaths() {
|
|
|
22
22
|
const monorepoRoot = resolve(cliRoot, '..', '..');
|
|
23
23
|
const isDev = existsSync(join(monorepoRoot, 'pnpm-workspace.yaml'));
|
|
24
24
|
let agentRoot;
|
|
25
|
-
let hooksSource;
|
|
26
25
|
if (isDev) {
|
|
27
|
-
// Development: agent
|
|
26
|
+
// Development: agent is in the monorepo
|
|
28
27
|
agentRoot = resolve(monorepoRoot, 'apps', 'agent');
|
|
29
|
-
hooksSource = resolve(monorepoRoot, 'packages', 'hooks');
|
|
30
28
|
}
|
|
31
29
|
else {
|
|
32
30
|
// Production: agent code is bundled with CLI
|
|
33
31
|
agentRoot = join(cliRoot, 'agent');
|
|
34
|
-
hooksSource = join(cliRoot, 'hooks');
|
|
35
32
|
}
|
|
36
33
|
// Use testable home directory (allows override via AGENT_247_HOME)
|
|
37
34
|
const home = getTestableHomedir();
|
|
@@ -49,7 +46,6 @@ export function getAgentPaths() {
|
|
|
49
46
|
cachedPaths = {
|
|
50
47
|
cliRoot,
|
|
51
48
|
agentRoot,
|
|
52
|
-
hooksSource,
|
|
53
49
|
hooksDestination: join(home, '.claude-plugins', '247-hooks'),
|
|
54
50
|
configDir,
|
|
55
51
|
configPath: join(configDir, 'config.json'),
|
package/dist/lib/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAEvC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,EAAE,CAAC;AACjD,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/routes/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMjC,wBAAgB,iBAAiB,IAAI,MAAM,CA0F1C"}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hooks API routes: receive status updates from Claude Code hooks.
|
|
3
|
-
*/
|
|
4
|
-
import { Router } from 'express';
|
|
5
|
-
import { tmuxSessionStatus, broadcastStatusUpdate } from '../status.js';
|
|
6
|
-
import * as sessionsDb from '../db/sessions.js';
|
|
7
|
-
import { getEnvironmentMetadata, getSessionEnvironment } from '../db/environments.js';
|
|
8
|
-
export function createHooksRoutes() {
|
|
9
|
-
const router = Router();
|
|
10
|
-
// Receive status updates from Claude Code hooks
|
|
11
|
-
router.post('/status', (req, res) => {
|
|
12
|
-
const { event, status, attention_reason, session_id, tmux_session, project, timestamp } = req.body;
|
|
13
|
-
if (!event) {
|
|
14
|
-
return res.status(400).json({ error: 'Missing event' });
|
|
15
|
-
}
|
|
16
|
-
const validStatuses = ['init', 'working', 'needs_attention', 'idle'];
|
|
17
|
-
const receivedStatus = validStatuses.includes(status) ? status : 'working';
|
|
18
|
-
const validReasons = [
|
|
19
|
-
'permission',
|
|
20
|
-
'input',
|
|
21
|
-
'plan_approval',
|
|
22
|
-
'task_complete',
|
|
23
|
-
];
|
|
24
|
-
const receivedReason = attention_reason && validReasons.includes(attention_reason) ? attention_reason : undefined;
|
|
25
|
-
const now = Date.now();
|
|
26
|
-
if (tmux_session) {
|
|
27
|
-
const existing = tmuxSessionStatus.get(tmux_session);
|
|
28
|
-
const statusChanged = !existing || existing.status !== receivedStatus;
|
|
29
|
-
const hookData = {
|
|
30
|
-
status: receivedStatus,
|
|
31
|
-
attentionReason: receivedReason,
|
|
32
|
-
lastEvent: event,
|
|
33
|
-
lastActivity: timestamp || now,
|
|
34
|
-
lastStatusChange: statusChanged ? now : existing.lastStatusChange,
|
|
35
|
-
project,
|
|
36
|
-
};
|
|
37
|
-
const sessionProject = tmux_session.split('--')[0] || project;
|
|
38
|
-
const dbSession = sessionsDb.upsertSession(tmux_session, {
|
|
39
|
-
project: sessionProject,
|
|
40
|
-
status: receivedStatus,
|
|
41
|
-
attentionReason: receivedReason,
|
|
42
|
-
lastEvent: event,
|
|
43
|
-
lastActivity: timestamp || now,
|
|
44
|
-
lastStatusChange: statusChanged ? now : (existing?.lastStatusChange ?? now),
|
|
45
|
-
environmentId: getSessionEnvironment(tmux_session),
|
|
46
|
-
});
|
|
47
|
-
tmuxSessionStatus.set(tmux_session, hookData);
|
|
48
|
-
const envId = getSessionEnvironment(tmux_session);
|
|
49
|
-
const envMeta = envId ? getEnvironmentMetadata(envId) : undefined;
|
|
50
|
-
broadcastStatusUpdate({
|
|
51
|
-
name: tmux_session,
|
|
52
|
-
project: sessionProject || project,
|
|
53
|
-
status: hookData.status,
|
|
54
|
-
attentionReason: hookData.attentionReason,
|
|
55
|
-
statusSource: 'hook',
|
|
56
|
-
lastEvent: hookData.lastEvent,
|
|
57
|
-
lastStatusChange: hookData.lastStatusChange,
|
|
58
|
-
createdAt: dbSession.created_at,
|
|
59
|
-
lastActivity: undefined,
|
|
60
|
-
environmentId: envId,
|
|
61
|
-
environment: envMeta
|
|
62
|
-
? {
|
|
63
|
-
id: envMeta.id,
|
|
64
|
-
name: envMeta.name,
|
|
65
|
-
provider: envMeta.provider,
|
|
66
|
-
icon: envMeta.icon,
|
|
67
|
-
isDefault: envMeta.isDefault,
|
|
68
|
-
}
|
|
69
|
-
: undefined,
|
|
70
|
-
});
|
|
71
|
-
console.log(`[Hook] ${tmux_session}: ${event} → ${receivedStatus}${receivedReason ? ` (${receivedReason})` : ''}`);
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
console.warn(`[Hook] WARNING: Missing tmux_session for ${event} (session_id=${session_id}, project=${project})`);
|
|
75
|
-
}
|
|
76
|
-
res.json({ received: true });
|
|
77
|
-
});
|
|
78
|
-
return router;
|
|
79
|
-
}
|
|
80
|
-
//# sourceMappingURL=hooks.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/routes/hooks.ts"],"names":[],"mappings":"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"}
|
package/hooks/hooks/hooks.json
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"description": "Simplified status tracking hooks for 247",
|
|
3
|
-
"hooks": {
|
|
4
|
-
"SessionStart": [
|
|
5
|
-
{
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/notify-status.sh",
|
|
10
|
-
"timeout": 5000
|
|
11
|
-
}
|
|
12
|
-
]
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"PermissionRequest": [
|
|
16
|
-
{
|
|
17
|
-
"matcher": "*",
|
|
18
|
-
"hooks": [
|
|
19
|
-
{
|
|
20
|
-
"type": "command",
|
|
21
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/notify-status.sh",
|
|
22
|
-
"timeout": 5000
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"Stop": [
|
|
28
|
-
{
|
|
29
|
-
"hooks": [
|
|
30
|
-
{
|
|
31
|
-
"type": "command",
|
|
32
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/notify-status.sh",
|
|
33
|
-
"timeout": 5000
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"type": "command",
|
|
37
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/check-duplication.sh",
|
|
38
|
-
"timeout": 30000
|
|
39
|
-
}
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
],
|
|
43
|
-
"Notification": [
|
|
44
|
-
{
|
|
45
|
-
"hooks": [
|
|
46
|
-
{
|
|
47
|
-
"type": "command",
|
|
48
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/notify-status.sh",
|
|
49
|
-
"timeout": 5000
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
"SessionEnd": [
|
|
55
|
-
{
|
|
56
|
-
"hooks": [
|
|
57
|
-
{
|
|
58
|
-
"type": "command",
|
|
59
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/notify-status.sh",
|
|
60
|
-
"timeout": 5000
|
|
61
|
-
}
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Code duplication check hook for Claude Code
|
|
3
|
-
# Runs jscpd and outputs a report after each task
|
|
4
|
-
|
|
5
|
-
# Don't fail on errors - we never want to block Claude
|
|
6
|
-
set +e
|
|
7
|
-
|
|
8
|
-
# Read stdin for hook input (contains cwd)
|
|
9
|
-
INPUT=$(cat)
|
|
10
|
-
CWD=$(echo "$INPUT" | jq -r '.cwd // ""' 2>/dev/null || echo "")
|
|
11
|
-
|
|
12
|
-
# If no cwd from hook, use current directory
|
|
13
|
-
if [ -z "$CWD" ]; then
|
|
14
|
-
CWD=$(pwd)
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
# Find the project root (look for .jscpd.json or package.json)
|
|
18
|
-
find_project_root() {
|
|
19
|
-
local dir="$1"
|
|
20
|
-
while [ "$dir" != "/" ]; do
|
|
21
|
-
if [ -f "$dir/.jscpd.json" ] || [ -f "$dir/package.json" ]; then
|
|
22
|
-
echo "$dir"
|
|
23
|
-
return 0
|
|
24
|
-
fi
|
|
25
|
-
dir=$(dirname "$dir")
|
|
26
|
-
done
|
|
27
|
-
return 1
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
PROJECT_ROOT=$(find_project_root "$CWD")
|
|
31
|
-
|
|
32
|
-
# If no project root found, skip silently
|
|
33
|
-
if [ -z "$PROJECT_ROOT" ]; then
|
|
34
|
-
exit 0
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
# Check if jscpd config exists
|
|
38
|
-
if [ ! -f "$PROJECT_ROOT/.jscpd.json" ]; then
|
|
39
|
-
exit 0
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# Check if npx is available
|
|
43
|
-
if ! command -v npx &> /dev/null; then
|
|
44
|
-
exit 0
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# Create temp directory for report
|
|
48
|
-
REPORT_DIR=$(mktemp -d)
|
|
49
|
-
trap "rm -rf $REPORT_DIR" EXIT
|
|
50
|
-
|
|
51
|
-
# Run jscpd with JSON output
|
|
52
|
-
cd "$PROJECT_ROOT"
|
|
53
|
-
npx jscpd --reporters json --output "$REPORT_DIR" > /dev/null 2>&1 || true
|
|
54
|
-
|
|
55
|
-
REPORT_FILE="$REPORT_DIR/jscpd-report.json"
|
|
56
|
-
|
|
57
|
-
# Check if report was generated
|
|
58
|
-
if [ ! -f "$REPORT_FILE" ]; then
|
|
59
|
-
exit 0
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
# Parse the JSON report
|
|
63
|
-
DUPLICATES=$(jq '.statistics.clones // 0' "$REPORT_FILE" 2>/dev/null || echo "0")
|
|
64
|
-
PERCENTAGE=$(jq -r '.statistics.percentage // "0"' "$REPORT_FILE" 2>/dev/null || echo "0")
|
|
65
|
-
TOTAL_LINES=$(jq '.statistics.total.lines // 0' "$REPORT_FILE" 2>/dev/null || echo "0")
|
|
66
|
-
|
|
67
|
-
# Only show report if there are duplicates
|
|
68
|
-
if [ "$DUPLICATES" -gt 0 ]; then
|
|
69
|
-
echo ""
|
|
70
|
-
echo "=========================================="
|
|
71
|
-
echo " CODE DUPLICATION REPORT"
|
|
72
|
-
echo "=========================================="
|
|
73
|
-
echo ""
|
|
74
|
-
echo " Duplicate blocks: $DUPLICATES"
|
|
75
|
-
echo " Duplication: ${PERCENTAGE}% of $TOTAL_LINES lines"
|
|
76
|
-
echo ""
|
|
77
|
-
echo " Duplicated locations:"
|
|
78
|
-
echo " ---------------------"
|
|
79
|
-
|
|
80
|
-
# Extract and format duplicate locations
|
|
81
|
-
jq -r '.duplicates[] | " [\(.firstFile.name):\(.firstFile.startLoc.line)-\(.firstFile.endLoc.line)]\n [\(.secondFile.name):\(.secondFile.startLoc.line)-\(.secondFile.endLoc.line)]\n Lines: \(.lines) | Tokens: \(.tokens)\n"' "$REPORT_FILE" 2>/dev/null || true
|
|
82
|
-
|
|
83
|
-
echo ""
|
|
84
|
-
echo " TIP: Refactor with:"
|
|
85
|
-
echo " 'Refactor the duplicated code above to follow DRY'"
|
|
86
|
-
echo ""
|
|
87
|
-
echo "=========================================="
|
|
88
|
-
echo ""
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
exit 0
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# Read stdin for hook input
|
|
5
|
-
INPUT=$(cat)
|
|
6
|
-
|
|
7
|
-
# Extract event details from JSON
|
|
8
|
-
EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // "unknown"' 2>/dev/null || echo "unknown")
|
|
9
|
-
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // ""' 2>/dev/null || echo "")
|
|
10
|
-
NOTIFICATION_TYPE=$(echo "$INPUT" | jq -r '.notification_type // ""' 2>/dev/null || echo "")
|
|
11
|
-
STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // ""' 2>/dev/null || echo "")
|
|
12
|
-
CWD=$(echo "$INPUT" | jq -r '.cwd // ""' 2>/dev/null || echo "")
|
|
13
|
-
|
|
14
|
-
# Detect tmux session name
|
|
15
|
-
# Priority 1: CLAUDE_TMUX_SESSION env var (set by agent - most reliable)
|
|
16
|
-
TMUX_SESSION="${CLAUDE_TMUX_SESSION:-}"
|
|
17
|
-
|
|
18
|
-
# Priority 2: If not set, try tmux display-message (only if in tmux context)
|
|
19
|
-
if [ -z "$TMUX_SESSION" ] && [ -n "${TMUX:-}" ]; then
|
|
20
|
-
TMUX_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null || echo "")
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
# If still no session detected, log warning but continue
|
|
24
|
-
if [ -z "$TMUX_SESSION" ]; then
|
|
25
|
-
echo "[WARN] Could not detect tmux session for hook $EVENT" >&2
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
# Map events to simplified status model
|
|
29
|
-
# Status: working | needs_attention | idle
|
|
30
|
-
# AttentionReason: permission | input | plan_approval | task_complete
|
|
31
|
-
STATUS="working"
|
|
32
|
-
ATTENTION_REASON=""
|
|
33
|
-
|
|
34
|
-
case "$EVENT" in
|
|
35
|
-
"SessionStart")
|
|
36
|
-
STATUS="working"
|
|
37
|
-
;;
|
|
38
|
-
"PermissionRequest")
|
|
39
|
-
STATUS="needs_attention"
|
|
40
|
-
ATTENTION_REASON="permission"
|
|
41
|
-
;;
|
|
42
|
-
"Stop")
|
|
43
|
-
STATUS="needs_attention"
|
|
44
|
-
# end_turn means Claude is waiting for user input
|
|
45
|
-
# Otherwise, task is complete
|
|
46
|
-
if [ "$STOP_REASON" = "end_turn" ]; then
|
|
47
|
-
ATTENTION_REASON="input"
|
|
48
|
-
else
|
|
49
|
-
ATTENTION_REASON="task_complete"
|
|
50
|
-
fi
|
|
51
|
-
;;
|
|
52
|
-
"Notification")
|
|
53
|
-
# idle_prompt notification means Claude is waiting for user input
|
|
54
|
-
if [ "$NOTIFICATION_TYPE" = "idle_prompt" ]; then
|
|
55
|
-
STATUS="needs_attention"
|
|
56
|
-
ATTENTION_REASON="input"
|
|
57
|
-
fi
|
|
58
|
-
;;
|
|
59
|
-
"SessionEnd")
|
|
60
|
-
STATUS="idle"
|
|
61
|
-
;;
|
|
62
|
-
*)
|
|
63
|
-
# Unknown event, default to working
|
|
64
|
-
STATUS="working"
|
|
65
|
-
;;
|
|
66
|
-
esac
|
|
67
|
-
|
|
68
|
-
# Extract project name from cwd (last component of path)
|
|
69
|
-
PROJECT=$(basename "$CWD" 2>/dev/null || echo "")
|
|
70
|
-
|
|
71
|
-
# Get current timestamp in milliseconds
|
|
72
|
-
TIMESTAMP=$(($(date +%s) * 1000))
|
|
73
|
-
|
|
74
|
-
# Send status update to local agent
|
|
75
|
-
# Note: Use || true to ensure we never block Claude execution
|
|
76
|
-
curl -s -X POST "http://localhost:4678/api/hooks/status" \
|
|
77
|
-
-H "Content-Type: application/json" \
|
|
78
|
-
-d "{
|
|
79
|
-
\"event\": \"$EVENT\",
|
|
80
|
-
\"status\": \"$STATUS\",
|
|
81
|
-
\"attention_reason\": \"$ATTENTION_REASON\",
|
|
82
|
-
\"session_id\": \"$SESSION_ID\",
|
|
83
|
-
\"tmux_session\": \"$TMUX_SESSION\",
|
|
84
|
-
\"project\": \"$PROJECT\",
|
|
85
|
-
\"timestamp\": $TIMESTAMP
|
|
86
|
-
}" > /dev/null 2>&1 || true
|
|
87
|
-
|
|
88
|
-
# Exit successfully (never block Claude)
|
|
89
|
-
exit 0
|