claudepod 1.1.2 → 1.2.2
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/.devcontainer/.env +18 -0
- package/.devcontainer/CHANGELOG.md +68 -0
- package/.devcontainer/CLAUDE.md +100 -0
- package/.devcontainer/README.md +220 -0
- package/.devcontainer/config/main-system-prompt.md +118 -0
- package/.devcontainer/config/settings.json +41 -0
- package/.devcontainer/devcontainer.json +71 -113
- package/.devcontainer/features/README.md +113 -0
- package/.devcontainer/features/ast-grep/README.md +24 -0
- package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
- package/.devcontainer/features/ast-grep/install.sh +51 -0
- package/.devcontainer/features/ccstatusline/README.md +296 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
- package/.devcontainer/features/ccstatusline/install.sh +290 -0
- package/.devcontainer/features/ccusage/README.md +205 -0
- package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccusage/install.sh +132 -0
- package/.devcontainer/features/claude-code/README.md +498 -0
- package/.devcontainer/features/claude-code/config/settings.json +36 -0
- package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
- package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
- package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
- package/.devcontainer/features/claude-code/install.sh +466 -0
- package/.devcontainer/features/claude-monitor/README.md +74 -0
- package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
- package/.devcontainer/features/claude-monitor/install.sh +99 -0
- package/.devcontainer/features/lsp-servers/README.md +85 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +34 -0
- package/.devcontainer/features/lsp-servers/install.sh +92 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
- package/.devcontainer/features/mcp-qdrant/README.md +474 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
- package/.devcontainer/features/mcp-reasoner/README.md +177 -0
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
- package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
- package/.devcontainer/features/splitrail/README.md +140 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
- package/.devcontainer/features/splitrail/install.sh +129 -0
- package/.devcontainer/features/tree-sitter/README.md +138 -0
- package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
- package/.devcontainer/features/tree-sitter/install.sh +173 -0
- package/.devcontainer/scripts/setup-aliases.sh +52 -0
- package/.devcontainer/scripts/setup-config.sh +28 -0
- package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
- package/.devcontainer/scripts/setup-lsp.sh +20 -0
- package/.devcontainer/scripts/setup-plugins.sh +31 -0
- package/.devcontainer/scripts/setup.sh +60 -0
- package/README.md +153 -187
- package/package.json +6 -10
- package/setup.js +2 -2
- package/.devcontainer/config/claude/mcp.json +0 -76
- package/.devcontainer/config/claude/mcp.json.template +0 -117
- package/.devcontainer/config/claude/output-styles/strict-development.md +0 -158
- package/.devcontainer/config/claude/settings.json +0 -10
- package/.devcontainer/config/claude/system-prompt.md +0 -3
- package/.devcontainer/config/searxng/ods_config.json +0 -22
- package/.devcontainer/config/searxng/searxng_env_template +0 -71
- package/.devcontainer/config/serena/serena_config.yml +0 -72
- package/.devcontainer/config/taskmaster/config.json +0 -37
- package/.devcontainer/ods_config.json +0 -21
- package/.devcontainer/post-create.sh +0 -1077
- package/.devcontainer/post-start.sh +0 -551
- package/.devcontainer/sanitize-system-prompt.sh +0 -31
- package/.devcontainer/scripts/config/claude-core.sh +0 -210
- package/.devcontainer/scripts/config/searxng.sh +0 -411
- package/.devcontainer/scripts/config/serena.sh +0 -47
- package/.devcontainer/scripts/config/taskmaster.sh +0 -41
- package/.devcontainer/scripts/generate-mcp-config.js +0 -205
- package/.devcontainer/scripts/install/claude-code.sh +0 -112
- package/.devcontainer/scripts/shell/zsh-config.sh +0 -271
- package/.devcontainer/scripts/utils.sh +0 -44
- package/.devcontainer/setup-zsh.sh +0 -234
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# No cleanup needed - using CLI instead of temp files
|
|
5
|
+
|
|
6
|
+
# Import options
|
|
7
|
+
USERNAME="${USERNAME:-automatic}"
|
|
8
|
+
|
|
9
|
+
echo "[mcp-reasoner] Starting MCP Reasoner installation..."
|
|
10
|
+
|
|
11
|
+
# Source NVM (Node is installed via NVM by the node feature)
|
|
12
|
+
if [ -f /usr/local/share/nvm/nvm.sh ]; then
|
|
13
|
+
source /usr/local/share/nvm/nvm.sh
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Validate node is available
|
|
17
|
+
if ! command -v node &>/dev/null; then
|
|
18
|
+
echo "[mcp-reasoner] ERROR: node is not available. Please ensure node feature is installed first."
|
|
19
|
+
echo " NVM path: /usr/local/share/nvm/nvm.sh"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Validate npm is available
|
|
24
|
+
if ! command -v npm &>/dev/null; then
|
|
25
|
+
echo "[mcp-reasoner] ERROR: npm is not available. Please ensure node feature is installed first."
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Determine the user
|
|
30
|
+
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
|
31
|
+
USERNAME=""
|
|
32
|
+
for CURRENT_USER in vscode node codespace; do
|
|
33
|
+
if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
|
|
34
|
+
USERNAME=${CURRENT_USER}
|
|
35
|
+
break
|
|
36
|
+
fi
|
|
37
|
+
done
|
|
38
|
+
[ -z "${USERNAME}" ] && USERNAME=root
|
|
39
|
+
elif [ "${USERNAME}" = "none" ] || ! id -u "${USERNAME}" >/dev/null 2>&1; then
|
|
40
|
+
USERNAME=root
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo "[mcp-reasoner] Installing for user: ${USERNAME}"
|
|
44
|
+
|
|
45
|
+
INSTALL_DIR="/home/${USERNAME}/mcp-reasoner"
|
|
46
|
+
DIST_FILE="${INSTALL_DIR}/dist/index.js"
|
|
47
|
+
|
|
48
|
+
if [[ -f "$DIST_FILE" ]]; then
|
|
49
|
+
echo "[mcp-reasoner] MCP-reasoner installation already present. Skipping..."
|
|
50
|
+
else
|
|
51
|
+
echo "[mcp-reasoner] Installing MCP-reasoner to ${INSTALL_DIR}"
|
|
52
|
+
|
|
53
|
+
# Clone and build as detected user with NVM environment
|
|
54
|
+
sudo -u "${USERNAME}" bash -c "
|
|
55
|
+
source /usr/local/share/nvm/nvm.sh
|
|
56
|
+
cd /home/${USERNAME}
|
|
57
|
+
|
|
58
|
+
# Remove existing directory if present (handles failed previous runs)
|
|
59
|
+
rm -rf mcp-reasoner
|
|
60
|
+
|
|
61
|
+
# Clone the repository
|
|
62
|
+
git clone https://github.com/Jacck/mcp-reasoner.git
|
|
63
|
+
cd mcp-reasoner
|
|
64
|
+
|
|
65
|
+
# Install dependencies and build
|
|
66
|
+
npm install
|
|
67
|
+
npm run build
|
|
68
|
+
"
|
|
69
|
+
|
|
70
|
+
# Verify installation
|
|
71
|
+
if [[ ! -f "$DIST_FILE" ]]; then
|
|
72
|
+
echo "[mcp-reasoner] ERROR: MCP-reasoner installation failed - dist/index.js not found"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
echo "[mcp-reasoner] MCP-reasoner installed successfully"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Create post-start hook for Claude Code registration
|
|
80
|
+
echo "[mcp-reasoner] Creating post-start hook for Claude Code registration..."
|
|
81
|
+
mkdir -p /usr/local/devcontainer-poststart.d
|
|
82
|
+
|
|
83
|
+
cat > /usr/local/devcontainer-poststart.d/51-mcp-reasoner.sh <<'HOOK_EOF'
|
|
84
|
+
#!/bin/bash
|
|
85
|
+
set -euo pipefail
|
|
86
|
+
|
|
87
|
+
echo "[mcp-reasoner] Registering Reasoner MCP server with Claude Code..."
|
|
88
|
+
|
|
89
|
+
# Determine user
|
|
90
|
+
USERNAME="${USERNAME:-vscode}"
|
|
91
|
+
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
|
92
|
+
for CURRENT_USER in vscode node codespace; do
|
|
93
|
+
if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
|
|
94
|
+
USERNAME=${CURRENT_USER}
|
|
95
|
+
break
|
|
96
|
+
fi
|
|
97
|
+
done
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Check if reasoner is installed
|
|
101
|
+
REASONER_PATH="/home/${USERNAME}/mcp-reasoner/dist/index.js"
|
|
102
|
+
if [ ! -f "$REASONER_PATH" ]; then
|
|
103
|
+
echo "[mcp-reasoner] WARNING: Reasoner not found at $REASONER_PATH, skipping registration"
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Ensure settings.json exists
|
|
108
|
+
SETTINGS_FILE="/workspaces/.claude/settings.json"
|
|
109
|
+
if [ ! -f "$SETTINGS_FILE" ]; then
|
|
110
|
+
echo "[mcp-reasoner] ERROR: $SETTINGS_FILE not found"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Check if jq is available
|
|
115
|
+
if ! command -v jq &>/dev/null; then
|
|
116
|
+
echo "[mcp-reasoner] ERROR: jq not available"
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Build the server configuration
|
|
121
|
+
SERVER_CONFIG=$(jq -n \
|
|
122
|
+
--arg cmd "node" \
|
|
123
|
+
--arg path "$REASONER_PATH" \
|
|
124
|
+
'{
|
|
125
|
+
command: $cmd,
|
|
126
|
+
args: [$path]
|
|
127
|
+
}')
|
|
128
|
+
|
|
129
|
+
# Update settings.json - add or update reasoner server
|
|
130
|
+
# Create temporary file for atomic update
|
|
131
|
+
TEMP_FILE=$(mktemp)
|
|
132
|
+
jq --argjson server "$SERVER_CONFIG" \
|
|
133
|
+
'.mcpServers.reasoner = $server' \
|
|
134
|
+
"$SETTINGS_FILE" > "$TEMP_FILE"
|
|
135
|
+
|
|
136
|
+
# Verify the JSON is valid
|
|
137
|
+
if jq empty "$TEMP_FILE" 2>/dev/null; then
|
|
138
|
+
mv "$TEMP_FILE" "$SETTINGS_FILE"
|
|
139
|
+
echo "[mcp-reasoner] ✓ Reasoner MCP server registered in Claude Code settings"
|
|
140
|
+
else
|
|
141
|
+
echo "[mcp-reasoner] ERROR: Generated invalid JSON"
|
|
142
|
+
rm -f "$TEMP_FILE"
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# Set proper permissions
|
|
147
|
+
chmod 644 "$SETTINGS_FILE"
|
|
148
|
+
chown vscode:vscode "$SETTINGS_FILE" 2>/dev/null || true
|
|
149
|
+
|
|
150
|
+
echo "[mcp-reasoner] ✓ Configuration complete"
|
|
151
|
+
HOOK_EOF
|
|
152
|
+
|
|
153
|
+
chmod +x /usr/local/devcontainer-poststart.d/51-mcp-reasoner.sh
|
|
154
|
+
echo "[mcp-reasoner] ✓ Post-start hook created at /usr/local/devcontainer-poststart.d/51-mcp-reasoner.sh"
|
|
155
|
+
|
|
156
|
+
echo ""
|
|
157
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
158
|
+
echo " MCP Reasoner Installation Complete"
|
|
159
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
160
|
+
echo ""
|
|
161
|
+
echo "Configuration:"
|
|
162
|
+
echo " • Install Path: ${INSTALL_DIR}"
|
|
163
|
+
echo " • User: ${USERNAME}"
|
|
164
|
+
echo " • MCP Server: reasoner (native devcontainer support)"
|
|
165
|
+
echo ""
|
|
166
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
167
|
+
echo " Next Steps"
|
|
168
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
169
|
+
echo ""
|
|
170
|
+
echo "1. MCP server will auto-register with Claude Code on container start"
|
|
171
|
+
echo ""
|
|
172
|
+
echo "2. Test the server directly:"
|
|
173
|
+
echo " node ${DIST_FILE}"
|
|
174
|
+
echo ""
|
|
175
|
+
echo "3. Verify available MCP servers in your AI agent"
|
|
176
|
+
echo ""
|
|
177
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "[mcp-reasoner] Registering Reasoner MCP server with Claude Code..."
|
|
5
|
+
|
|
6
|
+
# Determine user
|
|
7
|
+
USERNAME="${USERNAME:-vscode}"
|
|
8
|
+
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
|
9
|
+
for CURRENT_USER in vscode node codespace; do
|
|
10
|
+
if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
|
|
11
|
+
USERNAME=${CURRENT_USER}
|
|
12
|
+
break
|
|
13
|
+
fi
|
|
14
|
+
done
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Check if reasoner is installed
|
|
18
|
+
REASONER_PATH="/home/${USERNAME}/mcp-reasoner/dist/index.js"
|
|
19
|
+
if [ ! -f "$REASONER_PATH" ]; then
|
|
20
|
+
echo "[mcp-reasoner] WARNING: Reasoner not found at $REASONER_PATH, skipping registration"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Ensure settings.json exists
|
|
25
|
+
SETTINGS_FILE="/workspaces/.claude/settings.json"
|
|
26
|
+
if [ ! -f "$SETTINGS_FILE" ]; then
|
|
27
|
+
echo "[mcp-reasoner] ERROR: $SETTINGS_FILE not found"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check if jq is available
|
|
32
|
+
if ! command -v jq &>/dev/null; then
|
|
33
|
+
echo "[mcp-reasoner] ERROR: jq not available"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Build the server configuration
|
|
38
|
+
SERVER_CONFIG=$(jq -n \
|
|
39
|
+
--arg cmd "node" \
|
|
40
|
+
--arg path "$REASONER_PATH" \
|
|
41
|
+
'{
|
|
42
|
+
command: $cmd,
|
|
43
|
+
args: [$path]
|
|
44
|
+
}')
|
|
45
|
+
|
|
46
|
+
# Update settings.json - add or update reasoner server
|
|
47
|
+
# Create temporary file for atomic update
|
|
48
|
+
TEMP_FILE=$(mktemp)
|
|
49
|
+
jq --argjson server "$SERVER_CONFIG" \
|
|
50
|
+
'.mcpServers.reasoner = $server' \
|
|
51
|
+
"$SETTINGS_FILE" > "$TEMP_FILE"
|
|
52
|
+
|
|
53
|
+
# Verify the JSON is valid
|
|
54
|
+
if jq empty "$TEMP_FILE" 2>/dev/null; then
|
|
55
|
+
mv "$TEMP_FILE" "$SETTINGS_FILE"
|
|
56
|
+
echo "[mcp-reasoner] ✓ Reasoner MCP server registered in Claude Code settings"
|
|
57
|
+
else
|
|
58
|
+
echo "[mcp-reasoner] ERROR: Generated invalid JSON"
|
|
59
|
+
rm -f "$TEMP_FILE"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Set proper permissions
|
|
64
|
+
chmod 644 "$SETTINGS_FILE"
|
|
65
|
+
chown vscode:vscode "$SETTINGS_FILE" 2>/dev/null || true
|
|
66
|
+
|
|
67
|
+
echo "[mcp-reasoner] ✓ Configuration complete"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Splitrail Token Usage Tracker Feature
|
|
2
|
+
|
|
3
|
+
A DevContainer Feature that installs Splitrail - a real-time AI token usage tracker and cost monitor for AI coding agents.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"features": {
|
|
10
|
+
"ghcr.io/devcontainers/features/rust:1": {},
|
|
11
|
+
"ghcr.io/devcontainers/features/common-utils:2": {},
|
|
12
|
+
"./features/splitrail": {}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Note:** This feature requires Rust and common-utils features to be installed first.
|
|
18
|
+
|
|
19
|
+
## Options
|
|
20
|
+
|
|
21
|
+
| Option | Type | Default | Description |
|
|
22
|
+
|--------|------|---------|-------------|
|
|
23
|
+
| `repoUrl` | string | `https://github.com/Piebald-AI/splitrail.git` | Git repository URL |
|
|
24
|
+
| `branch` | string | `main` | Git branch to checkout |
|
|
25
|
+
| `username` | string | `automatic` | User to install for (auto-detects: vscode, node, codespace, or root) |
|
|
26
|
+
|
|
27
|
+
## What This Feature Installs
|
|
28
|
+
|
|
29
|
+
- **splitrail**: Compiled from source (Rust)
|
|
30
|
+
- **Binary Location**: `/home/{username}/.cargo/bin/splitrail`
|
|
31
|
+
- **Compile Time**: 2-3 minutes on first build
|
|
32
|
+
- **Disk Usage**: ~50MB source + build artifacts
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
This feature has explicit dependencies that **must** be installed first:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"features": {
|
|
41
|
+
"ghcr.io/devcontainers/features/rust:1": {},
|
|
42
|
+
"ghcr.io/devcontainers/features/common-utils:2": {},
|
|
43
|
+
"./features/splitrail": {}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Required by this feature:**
|
|
49
|
+
- **Rust + Cargo**: For compiling splitrail from source
|
|
50
|
+
- **Git**: For cloning the repository
|
|
51
|
+
|
|
52
|
+
The feature will validate these are present and exit with an error if missing.
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- ✅ **Real-time Tracking**: Monitor token usage as you code
|
|
57
|
+
- ✅ **Cost Monitoring**: Track costs for different AI models
|
|
58
|
+
- ✅ **Multi-agent Support**: Supports Claude Code, Gemini, Codex
|
|
59
|
+
- ✅ **Cloud Upload**: Optional private cloud aggregation across machines
|
|
60
|
+
- ✅ **Fast Performance**: Written in Rust for minimal overhead
|
|
61
|
+
- ✅ **Idempotent**: Safe to run multiple times
|
|
62
|
+
- ✅ **Multi-user**: Automatically detects container user
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
### Start Monitoring
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
splitrail
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Check Version
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
splitrail --version
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### View Help
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
splitrail --help
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Architecture
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
AI Agent (Claude Code, etc.)
|
|
88
|
+
↓
|
|
89
|
+
Splitrail monitors usage
|
|
90
|
+
↓
|
|
91
|
+
Real-time display + optional cloud upload
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Troubleshooting
|
|
95
|
+
|
|
96
|
+
### Compilation Fails
|
|
97
|
+
|
|
98
|
+
**Cause:** Rust/Cargo not available
|
|
99
|
+
|
|
100
|
+
**Solution:** Ensure Rust feature is installed first:
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"features": {
|
|
104
|
+
"ghcr.io/devcontainers/features/rust:1": {},
|
|
105
|
+
"./features/splitrail": {}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Binary Not Found
|
|
111
|
+
|
|
112
|
+
**Symptom:** `splitrail: command not found`
|
|
113
|
+
|
|
114
|
+
**Solution:** Check the binary location:
|
|
115
|
+
```bash
|
|
116
|
+
ls -la /home/node/.cargo/bin/splitrail
|
|
117
|
+
# Should exist
|
|
118
|
+
|
|
119
|
+
# Verify PATH includes cargo bin
|
|
120
|
+
echo $PATH | grep cargo
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Build Errors
|
|
124
|
+
|
|
125
|
+
**Symptom:** Cargo build fails during compilation
|
|
126
|
+
|
|
127
|
+
**Checks:**
|
|
128
|
+
- Verify Rust version: `rustc --version`
|
|
129
|
+
- Check cargo: `cargo --version`
|
|
130
|
+
- Review build output for specific errors
|
|
131
|
+
- Try cleaning: `cd ~/splitrail && cargo clean && cargo build --release`
|
|
132
|
+
|
|
133
|
+
## Resources
|
|
134
|
+
|
|
135
|
+
- [Splitrail GitHub](https://github.com/Piebald-AI/splitrail)
|
|
136
|
+
- [Rust Language](https://www.rust-lang.org/)
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT License - See repository for details.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "splitrail",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"name": "Splitrail Token Usage Tracker",
|
|
5
|
+
"description": "Installs Splitrail - real-time AI token usage tracker and cost monitor",
|
|
6
|
+
"maintainer": "AnExiledDev",
|
|
7
|
+
"documentationURL": "https://github.com/Piebald-AI/splitrail",
|
|
8
|
+
"options": {
|
|
9
|
+
"repoUrl": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Git repository URL for splitrail",
|
|
12
|
+
"default": "https://github.com/Piebald-AI/splitrail.git"
|
|
13
|
+
},
|
|
14
|
+
"branch": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Git branch to checkout",
|
|
17
|
+
"default": "main"
|
|
18
|
+
},
|
|
19
|
+
"username": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Container user to install for",
|
|
22
|
+
"default": "automatic"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"installsAfter": [
|
|
26
|
+
"ghcr.io/devcontainers/features/rust:1",
|
|
27
|
+
"ghcr.io/devcontainers/features/common-utils:2"
|
|
28
|
+
],
|
|
29
|
+
"customizations": {
|
|
30
|
+
"vscode": {
|
|
31
|
+
"extensions": []
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Cleanup on exit
|
|
5
|
+
cleanup() {
|
|
6
|
+
rm -f /tmp/splitrail-* 2>/dev/null || true
|
|
7
|
+
}
|
|
8
|
+
trap cleanup EXIT
|
|
9
|
+
|
|
10
|
+
# Import options
|
|
11
|
+
# NOTE: DevContainer converts camelCase to UPPERCASE without underscores
|
|
12
|
+
REPO_URL="${REPOURL:-https://github.com/Piebald-AI/splitrail.git}"
|
|
13
|
+
BRANCH="${BRANCH:-main}"
|
|
14
|
+
USERNAME="${USERNAME:-automatic}"
|
|
15
|
+
|
|
16
|
+
echo "[splitrail] Starting Splitrail installation..."
|
|
17
|
+
|
|
18
|
+
# Validate git is available
|
|
19
|
+
if ! command -v git &>/dev/null; then
|
|
20
|
+
echo "[splitrail] ERROR: git is not available"
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Validate cargo is available
|
|
25
|
+
if ! command -v cargo &>/dev/null; then
|
|
26
|
+
echo "[splitrail] ERROR: cargo is not available. Please ensure Rust feature is installed first."
|
|
27
|
+
echo " Expected cargo at: /usr/local/cargo/bin/cargo"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Validate input parameters
|
|
32
|
+
if [ -n "${REPO_URL}" ]; then
|
|
33
|
+
if [[ ! "${REPO_URL}" =~ ^https?:// ]] && [[ ! "${REPO_URL}" =~ ^git@.+:.+\.git$ ]]; then
|
|
34
|
+
echo "[splitrail] ERROR: repoUrl must be a valid git URL"
|
|
35
|
+
echo " Provided: ${REPO_URL}"
|
|
36
|
+
echo " Expected: https://... or git@github.com:.../*.git"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Determine the user
|
|
42
|
+
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
|
43
|
+
USERNAME=""
|
|
44
|
+
for CURRENT_USER in vscode node codespace; do
|
|
45
|
+
if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
|
|
46
|
+
USERNAME=${CURRENT_USER}
|
|
47
|
+
break
|
|
48
|
+
fi
|
|
49
|
+
done
|
|
50
|
+
[ -z "${USERNAME}" ] && USERNAME=root
|
|
51
|
+
elif [ "${USERNAME}" = "none" ] || ! id -u "${USERNAME}" >/dev/null 2>&1; then
|
|
52
|
+
USERNAME=root
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
echo "[splitrail] Installing for user: ${USERNAME}"
|
|
56
|
+
|
|
57
|
+
INSTALL_DIR="/home/${USERNAME}/splitrail"
|
|
58
|
+
BINARY="/home/${USERNAME}/.cargo/bin/splitrail"
|
|
59
|
+
|
|
60
|
+
if [[ -f "$BINARY" ]]; then
|
|
61
|
+
echo "[splitrail] Splitrail already installed at $BINARY. Skipping..."
|
|
62
|
+
else
|
|
63
|
+
echo "[splitrail] Installing Splitrail (Rust compilation - may take 2-3 minutes)..."
|
|
64
|
+
|
|
65
|
+
# Use explicit cargo path and rustup home (global installation from devcontainer Rust feature)
|
|
66
|
+
export PATH="/usr/local/cargo/bin:$PATH"
|
|
67
|
+
export RUSTUP_HOME="/usr/local/rustup"
|
|
68
|
+
|
|
69
|
+
# Fix permissions on rustup directories for non-root user access during build
|
|
70
|
+
mkdir -p /usr/local/rustup/tmp
|
|
71
|
+
chmod -R 777 /usr/local/rustup 2>/dev/null || true
|
|
72
|
+
|
|
73
|
+
# Clone and build as detected user
|
|
74
|
+
sudo -u "${USERNAME}" bash -c "
|
|
75
|
+
# Use explicit cargo path and rustup home for user context
|
|
76
|
+
export PATH=\"/usr/local/cargo/bin:\$PATH\"
|
|
77
|
+
export RUSTUP_HOME=\"/usr/local/rustup\"
|
|
78
|
+
|
|
79
|
+
cd /home/${USERNAME}
|
|
80
|
+
rm -rf splitrail
|
|
81
|
+
|
|
82
|
+
echo \"[splitrail] → Cloning splitrail repository...\"
|
|
83
|
+
git clone -b \"${BRANCH}\" \"${REPO_URL}\" splitrail
|
|
84
|
+
cd splitrail
|
|
85
|
+
|
|
86
|
+
echo \"[splitrail] → Compiling splitrail (this will take a few minutes)...\"
|
|
87
|
+
cargo build --release
|
|
88
|
+
|
|
89
|
+
echo \"[splitrail] → Installing binary...\"
|
|
90
|
+
cargo install --path .
|
|
91
|
+
"
|
|
92
|
+
|
|
93
|
+
# Verify installation
|
|
94
|
+
if [[ ! -f "$BINARY" ]]; then
|
|
95
|
+
echo "[splitrail] ERROR: Splitrail compilation failed - binary not found"
|
|
96
|
+
echo " Expected location: $BINARY"
|
|
97
|
+
echo " Check build output above for errors"
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo "[splitrail] ✓ Splitrail installed successfully at $BINARY"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
echo ""
|
|
105
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
106
|
+
echo " Splitrail Installation Complete"
|
|
107
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
108
|
+
echo ""
|
|
109
|
+
echo "Configuration:"
|
|
110
|
+
echo " • Install Path: ${INSTALL_DIR}"
|
|
111
|
+
echo " • Binary: ${BINARY}"
|
|
112
|
+
echo " • Repository: ${REPO_URL}"
|
|
113
|
+
echo " • Branch: ${BRANCH}"
|
|
114
|
+
echo " • User: ${USERNAME}"
|
|
115
|
+
echo ""
|
|
116
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
117
|
+
echo " Next Steps"
|
|
118
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
119
|
+
echo ""
|
|
120
|
+
echo "1. Test the binary:"
|
|
121
|
+
echo " splitrail --version"
|
|
122
|
+
echo ""
|
|
123
|
+
echo "2. Start monitoring:"
|
|
124
|
+
echo " splitrail"
|
|
125
|
+
echo ""
|
|
126
|
+
echo "3. View help:"
|
|
127
|
+
echo " splitrail --help"
|
|
128
|
+
echo ""
|
|
129
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Tree-sitter Parser Feature
|
|
2
|
+
|
|
3
|
+
Installs [tree-sitter](https://tree-sitter.github.io/tree-sitter/) parsing library with Node.js and Python bindings.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"features": {
|
|
10
|
+
"./features/tree-sitter": {}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Options
|
|
16
|
+
|
|
17
|
+
| Option | Type | Default | Description |
|
|
18
|
+
|--------|------|---------|-------------|
|
|
19
|
+
| `version` | string | `latest` | tree-sitter version (e.g., `0.24.4`) |
|
|
20
|
+
| `bindings` | enum | `both` | Language bindings: `node`, `python`, `both`, `none` |
|
|
21
|
+
| `installCli` | boolean | `true` | Install tree-sitter CLI tool (requires Node.js) |
|
|
22
|
+
| `grammars` | string | `javascript,typescript,python` | Comma-separated grammars to preload |
|
|
23
|
+
| `username` | string | `automatic` | Container user to install for |
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### Default (CLI + Node + Python + JS/TS/Python grammars)
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"features": {
|
|
32
|
+
"./features/tree-sitter": {}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### With Additional Grammars
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"features": {
|
|
42
|
+
"./features/tree-sitter": {
|
|
43
|
+
"grammars": "javascript,typescript,python,rust,go,json"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Node.js Only
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"features": {
|
|
54
|
+
"./features/tree-sitter": {
|
|
55
|
+
"bindings": "node",
|
|
56
|
+
"grammars": "javascript,typescript"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Python Only (No CLI)
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"features": {
|
|
67
|
+
"./features/tree-sitter": {
|
|
68
|
+
"bindings": "python",
|
|
69
|
+
"installCli": false,
|
|
70
|
+
"grammars": "python"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Installed Components
|
|
77
|
+
|
|
78
|
+
### CLI (`installCli: true`)
|
|
79
|
+
|
|
80
|
+
- `tree-sitter` CLI installed via npm ([tree-sitter-cli](https://www.npmjs.com/package/tree-sitter-cli))
|
|
81
|
+
- Requires Node.js to be installed
|
|
82
|
+
|
|
83
|
+
### Node.js Bindings (`bindings: "node"` or `"both"`)
|
|
84
|
+
|
|
85
|
+
- `web-tree-sitter` - WebAssembly-based tree-sitter for Node.js
|
|
86
|
+
- Grammar packages as `tree-sitter-{language}`
|
|
87
|
+
|
|
88
|
+
### Python Bindings (`bindings: "python"` or `"both"`)
|
|
89
|
+
|
|
90
|
+
- `tree-sitter` - Python bindings package
|
|
91
|
+
- Grammar packages as `tree-sitter-{language}`
|
|
92
|
+
|
|
93
|
+
## Available Grammars
|
|
94
|
+
|
|
95
|
+
Common grammars available via npm/pip:
|
|
96
|
+
|
|
97
|
+
- `javascript`, `typescript`, `tsx`
|
|
98
|
+
- `python`, `rust`, `go`, `c`, `cpp`
|
|
99
|
+
- `java`, `ruby`, `php`, `swift`
|
|
100
|
+
- `json`, `yaml`, `toml`, `html`, `css`
|
|
101
|
+
- `bash`, `markdown`, `regex`
|
|
102
|
+
|
|
103
|
+
## Dependencies
|
|
104
|
+
|
|
105
|
+
This feature requires:
|
|
106
|
+
|
|
107
|
+
- **Node.js** (via `ghcr.io/devcontainers/features/node:1`) - required for CLI and Node bindings
|
|
108
|
+
- **Python** (via `ghcr.io/devcontainers/features/python:1`) - for Python bindings only
|
|
109
|
+
|
|
110
|
+
## Quick Start
|
|
111
|
+
|
|
112
|
+
### Node.js
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const Parser = require('web-tree-sitter');
|
|
116
|
+
|
|
117
|
+
await Parser.init();
|
|
118
|
+
const parser = new Parser();
|
|
119
|
+
|
|
120
|
+
const JavaScript = await Parser.Language.load('path/to/tree-sitter-javascript.wasm');
|
|
121
|
+
parser.setLanguage(JavaScript);
|
|
122
|
+
|
|
123
|
+
const tree = parser.parse('const x = 1;');
|
|
124
|
+
console.log(tree.rootNode.toString());
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Python
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
import tree_sitter_python as tspython
|
|
131
|
+
from tree_sitter import Language, Parser
|
|
132
|
+
|
|
133
|
+
PY_LANGUAGE = Language(tspython.language())
|
|
134
|
+
parser = Parser(PY_LANGUAGE)
|
|
135
|
+
|
|
136
|
+
tree = parser.parse(b"def hello(): pass")
|
|
137
|
+
print(tree.root_node.sexp())
|
|
138
|
+
```
|