datagrok-tools 6.0.6 → 6.0.8
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/PACKAGES_DEV.md +165 -371
- package/.devcontainer/entrypoint.sh +43 -29
- package/bin/commands/claude.js +31 -11
- package/package.json +1 -1
|
@@ -2,36 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
Isolated environment for JS/TS package development against a running Datagrok instance.
|
|
4
4
|
All images are pre-built on Docker Hub — no local build step needed. Install `datagrok-tools`
|
|
5
|
-
globally and run `grok claude` from any
|
|
5
|
+
globally and run `grok claude` from any directory.
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm i -g datagrok-tools # one-time install
|
|
11
|
-
export ANTHROPIC_API_KEY=... # or set in shell profile
|
|
12
11
|
|
|
13
12
|
# From any package directory:
|
|
14
|
-
grok claude
|
|
15
|
-
|
|
16
|
-
#
|
|
17
|
-
grok claude --
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
grok claude
|
|
13
|
+
grok claude GROK-12345 # start working on a task
|
|
14
|
+
grok claude GROK-12345 --version 1.22.0 # pin Datagrok version
|
|
15
|
+
grok claude GROK-12345 --profile full --keep # all services, keep running
|
|
16
|
+
grok claude GROK-12345 --prompt "fix the bug" # one-shot command
|
|
17
|
+
grok claude GROK-12345 --in-place # use current directory (no worktree)
|
|
18
|
+
grok claude destroy GROK-12345 # tear down a task
|
|
19
|
+
grok claude destroy-all # tear down everything
|
|
21
20
|
```
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
Authentication: Claude Code credentials are copied from the host `~/.claude/` into the
|
|
23
|
+
container on startup. Alternatively, set `ANTHROPIC_API_KEY` in the environment.
|
|
24
|
+
|
|
25
|
+
**Project name restrictions:** `master` and `main` are rejected.
|
|
27
26
|
|
|
28
27
|
### What it does
|
|
29
28
|
|
|
30
|
-
1.
|
|
31
|
-
2.
|
|
32
|
-
3.
|
|
33
|
-
4.
|
|
34
|
-
5.
|
|
29
|
+
1. Creates a git worktree at `~/pkg-worktrees/<project>` (unless `--in-place` or not in a git repo)
|
|
30
|
+
2. Generates `docker-compose.yaml`, `.env`, and optional `docker-compose.override.yaml` in `$TMPDIR/dg-pkg-<project>`
|
|
31
|
+
3. Runs `docker compose up -d --wait` (pulls pre-built images from Docker Hub)
|
|
32
|
+
4. Copies Claude credentials into the container and fixes ownership
|
|
33
|
+
5. Detects working directory based on repo type (see below)
|
|
34
|
+
6. Launches `claude --dangerously-skip-permissions` inside the `tools-dev` container
|
|
35
|
+
7. On exit, stops containers (unless `--keep`)
|
|
35
36
|
|
|
36
37
|
### Manual setup
|
|
37
38
|
|
|
@@ -39,126 +40,162 @@ For manual setup or customization, use the `docker-compose.yaml` in this directo
|
|
|
39
40
|
directly. The `Dockerfile.pkg_dev` and `entrypoint.sh` are the build recipe for the
|
|
40
41
|
`datagrok/tools-dev` Docker Hub image — end users don't need them.
|
|
41
42
|
|
|
42
|
-
## What you can do
|
|
43
|
-
|
|
44
|
-
| Workflow | How it works |
|
|
45
|
-
|----------|-------------|
|
|
46
|
-
| **Develop packages (public repo)** | Mount public repo worktree as `/workspace`. Agent reads js-api source, help docs, ApiSamples, and CLAUDE.md skills directly. |
|
|
47
|
-
| **Develop packages (separate repo)** | Mount your repo as `/workspace`. The public repo is auto-cloned to `/workspace/public` on first start, branch matching `DG_VERSION`. |
|
|
48
|
-
| **Learn from examples** | Agent reads `packages/ApiSamples/scripts/` for runnable code samples and `help/develop/` for guides. |
|
|
49
|
-
| **Search Jira and GitHub** | MCP plugins for Atlassian Jira and GitHub — agent searches for similar issues, reads context, updates status. |
|
|
50
|
-
| **Write and run tests** | Playwright for browser automation, `grok test` for Puppeteer-based package tests, Chrome remote debugging. |
|
|
51
|
-
| **Publish packages** | `grok publish` to the local Datagrok instance or any external server. Agent handles build + publish. |
|
|
52
|
-
| **Manage the Datagrok stand** | Agent changes `DG_VERSION`, pulls new images, resets DB, redeploys — all from inside the container via Docker socket. |
|
|
53
|
-
| **Interactive setup** | Agent asks the user for tokens, auth keys, server URLs via Claude Code prompts. No pre-configuration required. |
|
|
54
|
-
|
|
55
43
|
## Architecture
|
|
56
44
|
|
|
57
45
|
```
|
|
58
46
|
Host machine
|
|
59
47
|
┌──────────────────────────────────────────────────────────────────┐
|
|
60
|
-
│
|
|
61
|
-
│ └── public/ (auto-cloned if workspace is not public repo) │
|
|
62
|
-
│ │
|
|
63
|
-
│ Docker network: dg-pkg-TASK-123-net │
|
|
48
|
+
│ Docker network: dg-pkg-<project>-net │
|
|
64
49
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
|
65
|
-
│ │ datagrok
|
|
66
|
-
│ │ postgres
|
|
67
|
-
│ │ rabbitmq
|
|
68
|
-
│ │ grok_pipe
|
|
69
|
-
│ │ grok_connect
|
|
70
|
-
│ │
|
|
71
|
-
│ │
|
|
72
|
-
│ │
|
|
73
|
-
│ │
|
|
74
|
-
│ │ ├── /
|
|
75
|
-
│ │ ├──
|
|
50
|
+
│ │ datagrok (datagrok/datagrok:${VERSION}) → :${PORT} │ │
|
|
51
|
+
│ │ postgres (pgvector/pgvector:pg17) │ │
|
|
52
|
+
│ │ rabbitmq (rabbitmq:4.0.5-management) │ │
|
|
53
|
+
│ │ grok_pipe (datagrok/grok_pipe:latest) │ │
|
|
54
|
+
│ │ grok_connect (datagrok/grok_connect:latest) │ │
|
|
55
|
+
│ │ grok_spawner, jkg (optional profiles) │ │
|
|
56
|
+
│ │ world, test_db, northwind (optional demo DBs) │ │
|
|
57
|
+
│ │ │ │
|
|
58
|
+
│ │ tools-dev (datagrok/tools-dev:latest, runs as root) │ │
|
|
59
|
+
│ │ ├── /workspace/repo ← bind mount of worktree │ │
|
|
60
|
+
│ │ ├── /workspace/datagrok/ ← sparse clone of public repo │ │
|
|
61
|
+
│ │ │ ├── .claude/, CLAUDE.md │ │
|
|
62
|
+
│ │ │ ├── js-api/ │ │
|
|
63
|
+
│ │ │ ├── libraries/ │ │
|
|
64
|
+
│ │ │ └── packages/ │ │
|
|
65
|
+
│ │ │ ├── ApiSamples/ ← checked out │ │
|
|
66
|
+
│ │ │ └── <folder>/ ← bind mount of user's repo │ │
|
|
67
|
+
│ │ ├── /var/run/docker.sock ← host Docker for stand mgmt │ │
|
|
68
|
+
│ │ ├── entrypoint.sh ← bind-mounted from tools/ │ │
|
|
76
69
|
│ │ ├── Claude Code + MCP plugins (Jira, GitHub) │ │
|
|
77
70
|
│ │ ├── Playwright + Chrome for testing │ │
|
|
78
71
|
│ │ └── grok CLI for build/publish/test │ │
|
|
79
72
|
│ └────────────────────────────────────────────────────────────┘ │
|
|
80
|
-
│
|
|
81
|
-
│ Host browser → http://localhost
|
|
82
|
-
│ → chrome://inspect → localhost:9222 (Debug)
|
|
83
|
-
|
|
73
|
+
│ │
|
|
74
|
+
│ Host browser → http://localhost:${PORT} (Datagrok UI) │
|
|
75
|
+
│ → chrome://inspect → localhost:9222 (Debug) │
|
|
76
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
84
77
|
```
|
|
85
78
|
|
|
86
|
-
##
|
|
79
|
+
## Working directory detection
|
|
87
80
|
|
|
88
|
-
|
|
89
|
-
The `grok claude` command embeds this same configuration and generates it automatically
|
|
90
|
-
— you don't need this file unless you want manual control.
|
|
81
|
+
Claude Code launches in different directories depending on the repo type:
|
|
91
82
|
|
|
92
|
-
|
|
83
|
+
| Repo type | Working directory | How detected |
|
|
84
|
+
|-----------|------------------|--------------|
|
|
85
|
+
| Public repo root | `/workspace/repo` | Host has `js-api/` at git root |
|
|
86
|
+
| Monorepo | `/workspace/repo/public` | Host has `public/js-api/` at git root |
|
|
87
|
+
| External repo | `/workspace/datagrok/packages/<folder>` | Everything else |
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
For **external repos**, the user's directory is bind-mounted at both `/workspace/repo`
|
|
90
|
+
and `/workspace/datagrok/packages/<folder>`. Claude Code starts in the latter so it can
|
|
91
|
+
walk up the directory tree to find `CLAUDE.md`, `.claude/`, and `js-api/` from the
|
|
92
|
+
sparse-cloned public repo.
|
|
97
93
|
|
|
98
|
-
|
|
94
|
+
## Sparse clone (external repos)
|
|
99
95
|
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
When the workspace is not the public repo, the entrypoint sparse-clones it into
|
|
97
|
+
`/workspace/datagrok/` using **cone mode** with `--filter=blob:none`:
|
|
102
98
|
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
docker build -f Dockerfile.pkg_dev -t datagrok/tools-dev:latest .
|
|
99
|
+
```
|
|
100
|
+
git sparse-checkout set --cone .claude js-api libraries packages/ApiSamples
|
|
106
101
|
```
|
|
107
102
|
|
|
108
|
-
|
|
103
|
+
This fetches only ~3 MB (vs 1.67 GB for the full repo) and completes in ~10 seconds.
|
|
104
|
+
The checked-out directories provide:
|
|
105
|
+
- `.claude/` — Claude Code skills and settings
|
|
106
|
+
- `CLAUDE.md` — project instructions for the agent
|
|
107
|
+
- `js-api/` — JS API source for reference
|
|
108
|
+
- `libraries/` — shared library source
|
|
109
|
+
- `packages/ApiSamples/` — runnable code examples
|
|
109
110
|
|
|
110
|
-
###
|
|
111
|
+
### Branch resolution
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
1. `DG_PUBLIC_BRANCH` (explicit override)
|
|
114
|
+
2. Current branch of the host repo (if inside the public repo)
|
|
115
|
+
3. `DG_VERSION` mapped to a branch (version tags like `latest`/`bleeding-edge` → `master`)
|
|
116
|
+
4. Falls back to `master`
|
|
115
117
|
|
|
116
|
-
|
|
117
|
-
echo "WORKTREE_PATH=$HOME/pkg-worktrees/TASK-123" >> .env
|
|
118
|
-
docker compose up -d
|
|
119
|
-
```
|
|
118
|
+
To use a private fork: `DG_PUBLIC_REPO=https://github.com/myorg/public-fork.git`
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
- `/workspace/js-api/` — JS API source (read directly, no build needed for reference)
|
|
123
|
-
- `/workspace/packages/ApiSamples/scripts/` — runnable code examples
|
|
124
|
-
- `/workspace/help/develop/` — development guides
|
|
125
|
-
- `/workspace/packages/` — all existing packages as reference
|
|
120
|
+
## Entrypoint
|
|
126
121
|
|
|
127
|
-
|
|
122
|
+
The entrypoint (`entrypoint.sh`) runs as **root** (via `user: root` in compose) to
|
|
123
|
+
handle bind-mount permission issues, then drops to the `node` user (UID 1000) via
|
|
124
|
+
`setpriv` for the main process (`sleep infinity`).
|
|
128
125
|
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
Steps:
|
|
127
|
+
1. Fix ownership of `/workspace/datagrok` (bind-mounts create parents as root)
|
|
128
|
+
2. Detect repo type (public, monorepo, or external)
|
|
129
|
+
3. Sparse-clone public repo if needed (cone mode, ~10s)
|
|
130
|
+
4. `chown -R node:node` on cloned files
|
|
131
|
+
5. Link workspace into `packages/` (skipped if bind-mount already exists)
|
|
132
|
+
6. Create symlinks at `/workspace/` for CLAUDE.md and .claude/
|
|
133
|
+
7. Auto-configure `~/.grok/config.yaml` pointing to `http://datagrok:8080/api`
|
|
134
|
+
8. Drop privileges: `exec setpriv --reuid=node --regid=node --init-groups "$@"`
|
|
131
135
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```
|
|
136
|
+
The entrypoint is **bind-mounted from the host repo** (`tools/.devcontainer/entrypoint.sh`)
|
|
137
|
+
via the compose override, so changes take effect without rebuilding the Docker image.
|
|
135
138
|
|
|
136
|
-
|
|
137
|
-
(no `js-api/` at root) and automatically clones it to `/workspace/public`:
|
|
139
|
+
## Compose template
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
[tools-dev] Public repo ready at /workspace/public (branch: bleeding-edge).
|
|
142
|
-
```
|
|
141
|
+
The compose configuration is embedded in `bin/commands/claude.ts` — no external files
|
|
142
|
+
needed. It generates three files in `$TMPDIR/dg-pkg-<project>/`:
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
3. Falls back to `master` if the branch/tag doesn't exist
|
|
144
|
+
- `docker-compose.yaml` — main compose template
|
|
145
|
+
- `.env` — resolved variables (paths, versions, ports, tokens)
|
|
146
|
+
- `docker-compose.override.yaml` — host-specific volumes (entrypoint, credentials mount for external repos)
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
- `/workspace/` — your repo
|
|
151
|
-
- `/workspace/public/js-api/` — JS API source (matching Datagrok version)
|
|
152
|
-
- `/workspace/public/packages/ApiSamples/scripts/` — code examples
|
|
153
|
-
- `/workspace/public/help/` — docs
|
|
154
|
-
- `/workspace/public/packages/` — reference packages
|
|
148
|
+
### Key differences from `.devcontainer/docker-compose.yaml`
|
|
155
149
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
150
|
+
| | Embedded (grok claude) | .devcontainer/ |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| Version vars | Separate per service (`DATAGROK_VERSION`, `GROK_CONNECT_VERSION`, etc.) | Single `DG_VERSION` |
|
|
153
|
+
| Workspace mount | `/workspace/repo` | `/workspace` |
|
|
154
|
+
| grok_connect | Always on | Profile `full` only |
|
|
155
|
+
| grok_pipe | `grok_pipe:latest` | `grok_pipe:${DG_VERSION}` |
|
|
156
|
+
| Host ~/.grok | Not mounted (auto-created by entrypoint) | Mounted from host |
|
|
157
|
+
| Entrypoint | Bind-mounted from repo via override | Baked into image |
|
|
158
|
+
| User | `root` (drops to `node` via setpriv) | `node` (from Dockerfile) |
|
|
160
159
|
|
|
161
|
-
|
|
160
|
+
## Credential handling
|
|
161
|
+
|
|
162
|
+
Claude Code credentials are **copied** into the container after startup (not
|
|
163
|
+
bind-mounted) to avoid permission issues — host files may have different UID/GID
|
|
164
|
+
than the container's `node` user.
|
|
165
|
+
|
|
166
|
+
Files copied from `~/.claude/`:
|
|
167
|
+
- `.credentials.json` — OAuth credentials
|
|
168
|
+
- `settings.json` — Claude Code settings
|
|
169
|
+
- `settings.local.json` — local settings
|
|
170
|
+
|
|
171
|
+
After copying, ownership is fixed: `chown -R node:node /home/node/.claude`
|
|
172
|
+
|
|
173
|
+
The host `~/.claude` directory is found by searching (in order):
|
|
174
|
+
1. `CLAUDE_HOME` environment variable
|
|
175
|
+
2. `$HOME/.claude`
|
|
176
|
+
3. `$USERPROFILE/.claude` (Windows)
|
|
177
|
+
4. `$APPDATA/../.claude` (Windows fallback)
|
|
178
|
+
|
|
179
|
+
## Profiles
|
|
180
|
+
|
|
181
|
+
| Profile | Services added | Use case |
|
|
182
|
+
|---------|---------------|----------|
|
|
183
|
+
| (none) | postgres, rabbitmq, grok_pipe, datagrok, grok_connect, tools-dev | Basic package dev |
|
|
184
|
+
| `scripting` | + jupyter_kernel_gateway | Python/R/Julia scripts |
|
|
185
|
+
| `demo` | + world, test_db, northwind | Demo databases |
|
|
186
|
+
| `full` | + grok_spawner, JKG, demo DBs | Everything |
|
|
187
|
+
|
|
188
|
+
## tools-dev container
|
|
189
|
+
|
|
190
|
+
Based on `node:22-bookworm-slim`. Pre-installed:
|
|
191
|
+
- Google Chrome stable (for Puppeteer)
|
|
192
|
+
- Playwright + Chromium
|
|
193
|
+
- `datagrok-tools` (grok CLI) — global npm
|
|
194
|
+
- `@anthropic-ai/claude-code` — global npm
|
|
195
|
+
- git, curl, jq, docker CLI
|
|
196
|
+
- Node.js 22
|
|
197
|
+
|
|
198
|
+
Runs as **root** in compose (entrypoint drops to `node` user for the main process).
|
|
162
199
|
|
|
163
200
|
## MCP plugins: Jira and GitHub
|
|
164
201
|
|
|
@@ -176,100 +213,42 @@ claude mcp add mcp-atlassian -s user -- \
|
|
|
176
213
|
--jira-token "$JIRA_TOKEN"
|
|
177
214
|
```
|
|
178
215
|
|
|
179
|
-
The agent can then:
|
|
180
|
-
- Search for issues: "find similar bugs to GROK-12345"
|
|
181
|
-
- Read issue details, comments, attachments
|
|
182
|
-
- Update issue status, add comments
|
|
183
|
-
- Create new issues
|
|
184
|
-
|
|
185
216
|
### GitHub
|
|
186
217
|
|
|
187
218
|
```bash
|
|
188
|
-
# Inside tools-dev, register the MCP server:
|
|
189
219
|
claude mcp add github -s user -- \
|
|
190
220
|
npx -y @modelcontextprotocol/server-github
|
|
191
221
|
```
|
|
192
222
|
|
|
193
|
-
Requires `GITHUB_TOKEN` in the environment (already passed from `.env`).
|
|
194
|
-
- Search issues and PRs across repos
|
|
195
|
-
- Read issue comments and PR diffs
|
|
196
|
-
- Create issues, PRs, and comments
|
|
197
|
-
- Check CI status
|
|
198
|
-
|
|
199
|
-
### Interactive token setup
|
|
200
|
-
|
|
201
|
-
If tokens are not pre-configured, the agent asks the user:
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
Agent: I need a Jira API token to search for similar issues.
|
|
205
|
-
Go to https://id.atlassian.com/manage-profile/security/api-tokens
|
|
206
|
-
and create a token. Paste it here.
|
|
207
|
-
User: <pastes token>
|
|
208
|
-
Agent: <configures MCP server and proceeds>
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
The same flow works for GitHub tokens and grok dev keys.
|
|
223
|
+
Requires `GITHUB_TOKEN` in the environment (already passed from `.env`).
|
|
212
224
|
|
|
213
225
|
## Testing
|
|
214
226
|
|
|
215
|
-
###
|
|
216
|
-
|
|
217
|
-
Playwright is pre-installed with Chromium. Use it for custom browser automation,
|
|
218
|
-
E2E tests, and UI interaction scenarios.
|
|
227
|
+
### grok test (Puppeteer-based)
|
|
219
228
|
|
|
220
229
|
```bash
|
|
221
|
-
|
|
222
|
-
cd /workspace/packages/MyPkg
|
|
223
|
-
|
|
224
|
-
# Run Playwright tests (if the package has them)
|
|
225
|
-
npx playwright test --project chromium
|
|
226
|
-
|
|
227
|
-
# Or write ad-hoc automation
|
|
228
|
-
npx playwright codegen http://datagrok:8080
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### grok test (Puppeteer-based package tests)
|
|
232
|
-
|
|
233
|
-
Standard Datagrok package testing via the `grok` CLI:
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
# Inside tools-dev:
|
|
237
|
-
cd /workspace/packages/MyPkg
|
|
230
|
+
cd /workspace/datagrok/packages/MyPkg
|
|
238
231
|
grok test --host local # headless
|
|
239
232
|
grok test --host local --gui # visible browser
|
|
240
233
|
grok test --host local --verbose # detailed output
|
|
241
|
-
grok test --host local --category "MyCategory" # filter tests
|
|
242
234
|
```
|
|
243
235
|
|
|
244
|
-
###
|
|
245
|
-
|
|
246
|
-
`grok test --gui` runs Chrome with `--remote-debugging-port=9222`. Port 9222 is
|
|
247
|
-
exposed to the host.
|
|
248
|
-
|
|
249
|
-
On host: open `chrome://inspect` → Configure → add `localhost:9222` → click "inspect"
|
|
250
|
-
on the test session. Set breakpoints in package source during test execution.
|
|
251
|
-
|
|
252
|
-
### Developing test scenarios
|
|
253
|
-
|
|
254
|
-
The agent can:
|
|
255
|
-
1. Read existing tests in `packages/ApiTests/` and other packages for patterns
|
|
256
|
-
2. Create new test files following the `package-test.ts` template
|
|
257
|
-
3. Run tests and analyze failures
|
|
258
|
-
4. Generate test cases from Jira issue descriptions or GitHub issues
|
|
236
|
+
### Playwright
|
|
259
237
|
|
|
260
238
|
```bash
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
grok add test
|
|
239
|
+
cd /workspace/datagrok/packages/MyPkg
|
|
240
|
+
npx playwright test --project chromium
|
|
264
241
|
```
|
|
265
242
|
|
|
266
|
-
|
|
243
|
+
### Chrome remote debugging
|
|
267
244
|
|
|
268
|
-
|
|
245
|
+
`grok test --gui` runs Chrome with `--remote-debugging-port=9222`.
|
|
246
|
+
On host: `chrome://inspect` → Configure → add `localhost:9222`
|
|
247
|
+
|
|
248
|
+
## Publishing packages
|
|
269
249
|
|
|
270
250
|
```bash
|
|
271
|
-
|
|
272
|
-
cd /workspace/packages/MyPkg
|
|
251
|
+
cd /workspace/datagrok/packages/MyPkg
|
|
273
252
|
grok publish # debug mode (visible only to dev)
|
|
274
253
|
grok publish --release # public release
|
|
275
254
|
grok publish --build # build webpack first
|
|
@@ -278,184 +257,17 @@ grok publish --build # build webpack first
|
|
|
278
257
|
### To an external server
|
|
279
258
|
|
|
280
259
|
```bash
|
|
281
|
-
# Add a server config
|
|
282
260
|
grok config add --alias prod \
|
|
283
261
|
--server https://example.datagrok.ai/api \
|
|
284
262
|
--key <dev-key>
|
|
285
|
-
|
|
286
|
-
# Publish to it
|
|
287
263
|
grok publish prod --release --build
|
|
288
264
|
```
|
|
289
265
|
|
|
290
|
-
The agent handles the full cycle: build, check, publish, verify in the UI.
|
|
291
|
-
|
|
292
|
-
## Managing the Datagrok stand
|
|
293
|
-
|
|
294
|
-
The tools-dev container has the Docker socket mounted, so the agent can manage the
|
|
295
|
-
entire compose stack from inside.
|
|
296
|
-
|
|
297
|
-
### Version switching
|
|
298
|
-
|
|
299
|
-
```bash
|
|
300
|
-
# Inside tools-dev (or from host):
|
|
301
|
-
DG_VERSION=1.22.0 docker compose up -d --pull always
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
When the workspace is a separate repo (not public), the auto-cloned public repo
|
|
305
|
-
should also be updated to match the new version:
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
# Inside tools-dev — update the public clone to match new DG_VERSION:
|
|
309
|
-
cd /workspace/public && git fetch && git checkout 1.22.0
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
The agent does this autonomously when asked:
|
|
313
|
-
```
|
|
314
|
-
User: Switch to Datagrok 1.22.0
|
|
315
|
-
Agent: <updates DG_VERSION, pulls new images, updates public branch>
|
|
316
|
-
Datagrok 1.22.0 is running. Public repo updated to 1.22.0.
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### DB reset / redeploy
|
|
320
|
-
|
|
321
|
-
```bash
|
|
322
|
-
docker compose down -v && docker compose up -d
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### Adding profiles on the fly
|
|
326
|
-
|
|
327
|
-
```bash
|
|
328
|
-
# Need demo databases now
|
|
329
|
-
docker compose --profile demo up -d
|
|
330
|
-
|
|
331
|
-
# Need everything
|
|
332
|
-
docker compose --profile full up -d
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
## Profiles
|
|
336
|
-
|
|
337
|
-
| Profile | Services added | Use case |
|
|
338
|
-
|---------|---------------|----------|
|
|
339
|
-
| (none) | postgres, rabbitmq, grok_pipe, datagrok, tools-dev | Basic package dev |
|
|
340
|
-
| `demo` | + world, test_db, northwind | Need demo databases |
|
|
341
|
-
| `scripting` | + jupyter_kernel_gateway | Need Python/R/Julia scripts |
|
|
342
|
-
| `full` | + grok_connect, grok_spawner, demo DBs, JKG | Everything |
|
|
343
|
-
|
|
344
|
-
## JS API and code reference
|
|
345
|
-
|
|
346
|
-
The agent reads JS API source and documentation directly from the workspace — no
|
|
347
|
-
generated docs needed.
|
|
348
|
-
|
|
349
|
-
### Key paths (public repo at `/workspace`)
|
|
350
|
-
|
|
351
|
-
| What | Path |
|
|
352
|
-
|------|------|
|
|
353
|
-
| JS API source (types, classes, methods) | `js-api/src/` |
|
|
354
|
-
| JS API entry points (grok, ui, dg) | `js-api/grok.ts`, `js-api/ui.ts`, `js-api/dg.ts` |
|
|
355
|
-
| JS API CLAUDE.md (module map, patterns) | `js-api/CLAUDE.md` |
|
|
356
|
-
| Runnable code samples | `packages/ApiSamples/scripts/` |
|
|
357
|
-
| Package development guide | `help/develop/packages/` |
|
|
358
|
-
| All platform help docs | `help/` |
|
|
359
|
-
| Existing packages (patterns) | `packages/` |
|
|
360
|
-
| CLI tool source | `tools/` |
|
|
361
|
-
|
|
362
|
-
### Key paths (separate repo — public auto-cloned)
|
|
363
|
-
|
|
364
|
-
Same as above, prefixed with `public/`:
|
|
365
|
-
- `public/js-api/src/`, `public/packages/ApiSamples/scripts/`, etc.
|
|
366
|
-
|
|
367
|
-
The public branch matches `DG_VERSION` by default, so js-api types stay in sync
|
|
368
|
-
with the running Datagrok server.
|
|
369
|
-
|
|
370
|
-
### CLAUDE.md for the agent
|
|
371
|
-
|
|
372
|
-
Add to your project's CLAUDE.md so the agent knows where to look:
|
|
373
|
-
|
|
374
|
-
```markdown
|
|
375
|
-
## Reference
|
|
376
|
-
|
|
377
|
-
- JS API: read source in `js-api/src/` — see `js-api/CLAUDE.md` for module map
|
|
378
|
-
- Code samples: `packages/ApiSamples/scripts/` — runnable examples for eval
|
|
379
|
-
- Help docs: `help/develop/` — guides for packages, viewers, functions
|
|
380
|
-
- Existing packages: `packages/` — real-world patterns
|
|
381
|
-
```
|
|
382
|
-
|
|
383
266
|
## Exposing the client
|
|
384
267
|
|
|
385
|
-
- Datagrok UI: `http://localhost:${DG_PORT
|
|
386
|
-
- Default credentials: **admin / admin**
|
|
387
|
-
|
|
388
|
-
### grok CLI config inside the container
|
|
389
|
-
|
|
390
|
-
The entrypoint auto-creates `~/.grok/config.yaml` with the local Datagrok instance
|
|
391
|
-
(dev key `admin`). The grok CLI is ready to use immediately — no manual config needed.
|
|
392
|
-
|
|
393
|
-
If you need to reconfigure:
|
|
394
|
-
|
|
395
|
-
```bash
|
|
396
|
-
# Inside tools-dev:
|
|
397
|
-
grok config add --alias local \
|
|
398
|
-
--server http://datagrok:8080/api \
|
|
399
|
-
--key admin --default
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
## Claude Code inside the container
|
|
403
|
-
|
|
404
|
-
Mount `~/.claude/` from host (already in the compose file) for credentials and
|
|
405
|
-
config. Pass `ANTHROPIC_API_KEY` via `.env` or shell export.
|
|
406
|
-
|
|
407
|
-
```bash
|
|
408
|
-
# Single entry point — launch Claude Code interactively
|
|
409
|
-
docker exec -it <tools-dev_container> claude --dangerously-skip-permissions
|
|
410
|
-
|
|
411
|
-
# One-shot command
|
|
412
|
-
docker exec <tools-dev_container> claude -p "publish the Chem package" \
|
|
413
|
-
--dangerously-skip-permissions
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
The agent can:
|
|
417
|
-
- Build, test, and publish packages
|
|
418
|
-
- Search Jira/GitHub for context (via MCP plugins)
|
|
419
|
-
- Manage the Datagrok stand (version switch, redeploy, DB reset)
|
|
420
|
-
- Ask the user for tokens and auth when needed
|
|
421
|
-
- Read js-api source and ApiSamples for reference
|
|
422
|
-
|
|
423
|
-
## Quick reference
|
|
424
|
-
|
|
425
|
-
```bash
|
|
426
|
-
# Start (basic)
|
|
427
|
-
docker compose up -d
|
|
428
|
-
|
|
429
|
-
# Start (everything)
|
|
430
|
-
docker compose --profile full up -d
|
|
431
|
-
|
|
432
|
-
# Launch Claude agent (single entry point)
|
|
433
|
-
docker exec -it <tools-dev> claude --dangerously-skip-permissions
|
|
434
|
-
|
|
435
|
-
# Shell into tools-dev
|
|
436
|
-
docker exec -it <tools-dev> bash
|
|
437
|
-
|
|
438
|
-
# Publish a package
|
|
439
|
-
docker exec <tools-dev> bash -c "cd /workspace/packages/MyPkg && grok publish"
|
|
440
|
-
|
|
441
|
-
# Run grok tests
|
|
442
|
-
docker exec <tools-dev> bash -c "cd /workspace/packages/MyPkg && grok test --host local"
|
|
443
|
-
|
|
444
|
-
# Run Playwright tests
|
|
445
|
-
docker exec <tools-dev> bash -c "cd /workspace/packages/MyPkg && npx playwright test"
|
|
446
|
-
|
|
447
|
-
# Version switch
|
|
448
|
-
DG_VERSION=1.22.0 docker compose up -d --pull always
|
|
449
|
-
|
|
450
|
-
# DB reset
|
|
451
|
-
docker compose down -v && docker compose up -d
|
|
452
|
-
|
|
453
|
-
# Logs
|
|
454
|
-
docker compose logs -f datagrok
|
|
455
|
-
|
|
456
|
-
# Stop
|
|
457
|
-
docker compose down
|
|
458
|
-
```
|
|
268
|
+
- Datagrok UI: `http://localhost:${DG_PORT}` (port shown at startup, or use `--port` to fix it)
|
|
269
|
+
- Default credentials: **admin / admin**
|
|
270
|
+
- grok CLI inside container: auto-configured to `http://datagrok:8080/api` with key `admin`
|
|
459
271
|
|
|
460
272
|
## Troubleshooting
|
|
461
273
|
|
|
@@ -463,39 +275,21 @@ docker compose down
|
|
|
463
275
|
```bash
|
|
464
276
|
docker compose logs datagrok
|
|
465
277
|
# Wait for DB migrations — first start takes 1-2 minutes
|
|
466
|
-
# Look for: "Server started on port 8080"
|
|
467
278
|
```
|
|
468
279
|
|
|
469
280
|
### grok publish fails
|
|
470
|
-
Ensure `~/.grok/config.yaml` inside the container points to `http://datagrok:8080/api
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
### Chrome / Playwright not working
|
|
474
|
-
```bash
|
|
475
|
-
docker exec <tools-dev> google-chrome-stable --version
|
|
476
|
-
docker exec <tools-dev> npx playwright --version
|
|
477
|
-
```
|
|
478
|
-
If missing, pull the latest image: `docker pull datagrok/tools-dev:latest`
|
|
281
|
+
Ensure `~/.grok/config.yaml` inside the container points to `http://datagrok:8080/api`.
|
|
282
|
+
The container reaches Datagrok via Docker DNS (`datagrok`), not `localhost`.
|
|
479
283
|
|
|
480
|
-
###
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
docker exec <tools-dev> env | grep -E 'JIRA|GITHUB'
|
|
484
|
-
# Re-register if needed
|
|
485
|
-
docker exec -it <tools-dev> claude mcp add mcp-atlassian -s user -- \
|
|
486
|
-
npx -y mcp-atlassian --jira-url "$JIRA_URL" \
|
|
487
|
-
--jira-username "$JIRA_USERNAME" --jira-token "$JIRA_TOKEN"
|
|
488
|
-
```
|
|
284
|
+
### Permission denied on /workspace/datagrok
|
|
285
|
+
The entrypoint runs as root and fixes ownership. If using the image directly (not via
|
|
286
|
+
`grok claude`), add `user: root` to the compose service definition.
|
|
489
287
|
|
|
490
|
-
### Agent can't manage Docker
|
|
491
|
-
The Docker socket must be mounted
|
|
492
|
-
```bash
|
|
493
|
-
docker exec <tools-dev> docker ps
|
|
494
|
-
```
|
|
495
|
-
If permission denied, check that `/var/run/docker.sock` is mounted and accessible.
|
|
288
|
+
### Agent can't manage Docker
|
|
289
|
+
The Docker socket must be mounted. Check: `docker exec <tools-dev> docker ps`
|
|
496
290
|
|
|
497
291
|
### Container can't resolve `datagrok` hostname
|
|
498
292
|
All services must be on the same Docker network:
|
|
499
293
|
```bash
|
|
500
|
-
docker network inspect dg-pkg
|
|
294
|
+
docker network inspect dg-pkg-<project>-net
|
|
501
295
|
```
|
|
@@ -13,6 +13,11 @@ resolve_branch() {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
PUBLIC_DIR="${DG_PUBLIC_DIR:-/workspace/datagrok}"
|
|
16
|
+
# Ensure workspace dirs are writable by node user (bind-mounts create parents as root)
|
|
17
|
+
chown node:node /workspace "$PUBLIC_DIR" 2>/dev/null || true
|
|
18
|
+
# Allow git to operate on dirs owned by different users (root runs git, dir owned by node)
|
|
19
|
+
git config --global --add safe.directory "$PUBLIC_DIR" 2>/dev/null || true
|
|
20
|
+
git config --global init.defaultBranch master 2>/dev/null || true
|
|
16
21
|
# Detect if /workspace/repo IS the public repo.
|
|
17
22
|
# Require .git to avoid false positives from packages that have public/js-api via npm link.
|
|
18
23
|
if [ -e "/workspace/repo/.git" ] && [ -d "/workspace/repo/js-api" ]; then
|
|
@@ -29,31 +34,40 @@ else
|
|
|
29
34
|
else
|
|
30
35
|
BRANCH=$(resolve_branch "${DG_VERSION:-latest}")
|
|
31
36
|
fi
|
|
32
|
-
# Sparse checkout
|
|
33
|
-
#
|
|
34
|
-
# blobs
|
|
37
|
+
# Sparse checkout (cone mode) with partial clone: only fetch js-api, libraries, and
|
|
38
|
+
# ApiSamples. Cone mode integrates with --filter=blob:none so the server only sends
|
|
39
|
+
# blobs for the included directories (~3 MB vs 1.67 GB for the full tree).
|
|
35
40
|
sparse_clone() {
|
|
36
41
|
local branch="$1"
|
|
37
42
|
# Use init+fetch instead of clone to handle pre-existing directories (e.g. mount points)
|
|
38
|
-
git init "$PUBLIC_DIR" \
|
|
39
|
-
&& git -C "$PUBLIC_DIR" remote add origin "$REPO" \
|
|
40
|
-
&& git -C "$PUBLIC_DIR"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
&& git -C "$PUBLIC_DIR"
|
|
45
|
-
&& git -C "$PUBLIC_DIR" checkout -B "$branch" FETCH_HEAD
|
|
43
|
+
git init -q "$PUBLIC_DIR" \
|
|
44
|
+
&& (git -C "$PUBLIC_DIR" remote add origin "$REPO" 2>/dev/null || git -C "$PUBLIC_DIR" remote set-url origin "$REPO") \
|
|
45
|
+
&& git -C "$PUBLIC_DIR" config remote.origin.promisor true \
|
|
46
|
+
&& git -C "$PUBLIC_DIR" config remote.origin.partialclonefilter blob:none \
|
|
47
|
+
&& git -C "$PUBLIC_DIR" sparse-checkout set --cone .claude js-api libraries packages/ApiSamples \
|
|
48
|
+
&& git -C "$PUBLIC_DIR" fetch -q --depth 1 --filter=blob:none origin "$branch" \
|
|
49
|
+
&& git -C "$PUBLIC_DIR" checkout -q -B "$branch" FETCH_HEAD
|
|
46
50
|
}
|
|
47
|
-
# Clear
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
# Clear git state without touching bind-mounted subdirs (e.g. packages/awesome)
|
|
52
|
+
clear_git() {
|
|
53
|
+
rm -rf "$1/.git" 2>/dev/null || true
|
|
50
54
|
}
|
|
51
55
|
echo "[tools-dev] Cloning public repo ($BRANCH, sparse) into $PUBLIC_DIR..."
|
|
52
|
-
sparse_clone "$BRANCH"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if sparse_clone "$BRANCH"; then
|
|
57
|
+
echo "[tools-dev] Public repo ready."
|
|
58
|
+
elif [ "$BRANCH" != "master" ]; then
|
|
59
|
+
echo "[tools-dev] Branch '$BRANCH' clone failed, falling back to master."
|
|
60
|
+
clear_git "$PUBLIC_DIR"
|
|
61
|
+
if sparse_clone "master"; then
|
|
62
|
+
echo "[tools-dev] Public repo ready (branch: master)."
|
|
63
|
+
else
|
|
64
|
+
echo "[tools-dev] WARNING: Failed to clone public repo."
|
|
65
|
+
fi
|
|
66
|
+
else
|
|
67
|
+
echo "[tools-dev] WARNING: Failed to clone public repo."
|
|
68
|
+
fi
|
|
69
|
+
# Ensure node user can read cloned files (entrypoint runs as root)
|
|
70
|
+
chown -R node:node "$PUBLIC_DIR" 2>/dev/null || true
|
|
57
71
|
fi
|
|
58
72
|
|
|
59
73
|
# ── Mount workspace inside public repo for non-public workspaces ──
|
|
@@ -64,21 +78,20 @@ if [ -e "/workspace/repo/.git" ] && [ -d "/workspace/repo/js-api" ]; then
|
|
|
64
78
|
elif [ -e "/workspace/repo/.git" ] && [ -d "/workspace/repo/public/js-api" ]; then
|
|
65
79
|
echo "[tools-dev] Monorepo detected — public context at /workspace/repo/public/."
|
|
66
80
|
elif [ -d "$PUBLIC_DIR/js-api" ]; then
|
|
67
|
-
# Cloned public repo — link workspace into packages/ and expose context at /workspace/
|
|
68
81
|
LINK_NAME="${FOLDER_NAME:-$TASK_KEY}"
|
|
69
82
|
if [ -n "$LINK_NAME" ]; then
|
|
70
83
|
mkdir -p "$PUBLIC_DIR/packages" 2>/dev/null || true
|
|
71
|
-
[ ! -
|
|
72
|
-
|
|
84
|
+
if [ ! -d "$PUBLIC_DIR/packages/$LINK_NAME" ]; then
|
|
85
|
+
ln -sfn /workspace/repo "$PUBLIC_DIR/packages/$LINK_NAME"
|
|
86
|
+
fi
|
|
87
|
+
echo "[tools-dev] Workspace at $PUBLIC_DIR/packages/$LINK_NAME"
|
|
73
88
|
fi
|
|
74
89
|
PUBLIC_BASENAME=$(basename "$PUBLIC_DIR")
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
echo "[tools-dev] Linked public repo context at /workspace/"
|
|
90
|
+
ln -sfn "$PUBLIC_BASENAME/.claude" /workspace/.claude 2>/dev/null || true
|
|
91
|
+
ln -sfn "$PUBLIC_BASENAME/CLAUDE.md" /workspace/CLAUDE.md 2>/dev/null || true
|
|
78
92
|
fi
|
|
79
93
|
|
|
80
94
|
# Auto-configure grok CLI to point to the local Datagrok instance.
|
|
81
|
-
# Only creates the config if it doesn't already exist (preserves host config).
|
|
82
95
|
GROK_DIR="/home/node/.grok"
|
|
83
96
|
GROK_CFG="$GROK_DIR/config.yaml"
|
|
84
97
|
if [ ! -f "$GROK_CFG" ] || [ ! -s "$GROK_CFG" ]; then
|
|
@@ -91,9 +104,10 @@ servers:
|
|
|
91
104
|
key: admin
|
|
92
105
|
YAML
|
|
93
106
|
[ -s "$GROK_CFG" ] && echo "[tools-dev] Created grok config at $GROK_CFG"
|
|
94
|
-
elif ! grep -q "datagrok:8080" "$GROK_CFG" 2>/dev/null; then
|
|
95
|
-
echo "[tools-dev] Note: existing grok config found. Add 'local' server with:"
|
|
96
|
-
echo " grok config add --alias local --server http://datagrok:8080/api --key admin --default"
|
|
97
107
|
fi
|
|
98
108
|
|
|
109
|
+
# Drop to node user for the main process (entrypoint runs as root for permission fixes)
|
|
110
|
+
if [ "$(id -u)" = "0" ]; then
|
|
111
|
+
exec setpriv --reuid=node --regid=node --init-groups "$@"
|
|
112
|
+
fi
|
|
99
113
|
exec "$@"
|
package/bin/commands/claude.js
CHANGED
|
@@ -259,6 +259,7 @@ services:
|
|
|
259
259
|
networks:
|
|
260
260
|
dg:
|
|
261
261
|
aliases: [tools-dev]
|
|
262
|
+
user: root
|
|
262
263
|
stdin_open: true
|
|
263
264
|
tty: true
|
|
264
265
|
restart: unless-stopped
|
|
@@ -321,7 +322,7 @@ function findFreePort() {
|
|
|
321
322
|
srv.on('error', reject);
|
|
322
323
|
});
|
|
323
324
|
}
|
|
324
|
-
function writeProjectFiles(taskKey, args, worktreeRoot, dgPort) {
|
|
325
|
+
function writeProjectFiles(taskKey, args, worktreeRoot, dgPort, repoRoot) {
|
|
325
326
|
const projectDir = getProjectDir(taskKey);
|
|
326
327
|
if (!_fs.default.existsSync(projectDir)) _fs.default.mkdirSync(projectDir, {
|
|
327
328
|
recursive: true
|
|
@@ -349,14 +350,19 @@ function writeProjectFiles(taskKey, args, worktreeRoot, dgPort) {
|
|
|
349
350
|
// Bind-mount local entrypoint so fixes take effect without rebuilding the image
|
|
350
351
|
if (hasLocalEntrypoint) volumes.push(` - "${toDockerPath(entrypointPath)}:/usr/local/bin/entrypoint.sh"`);
|
|
351
352
|
|
|
352
|
-
//
|
|
353
|
+
// For external repos, also mount workspace inside the public repo tree so Claude Code
|
|
354
|
+
// sees the real path (not a symlink that resolves back to /workspace/repo).
|
|
355
|
+
const isPublic = repoRoot ? isPublicRepo(repoRoot) : false;
|
|
356
|
+
if (!isPublic) {
|
|
357
|
+
const folderName = _path.default.basename(worktreeRoot);
|
|
358
|
+
volumes.push(` - "${toDockerPath(worktreeRoot)}:/workspace/datagrok/packages/${folderName}"`);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Claude profile: credentials are copied into the container after startup (not bind-mounted)
|
|
362
|
+
// to avoid permission issues — host files may have different UID/GID than the container's
|
|
363
|
+
// node user.
|
|
353
364
|
const claudeHome = findClaudeHome();
|
|
354
|
-
if (claudeHome) {
|
|
355
|
-
volumes.push(` - "${toDockerPath(claudeHome)}:/home/node/.claude"`);
|
|
356
|
-
const claudeState = _path.default.join(_path.default.dirname(claudeHome), '.claude.json');
|
|
357
|
-
if (_fs.default.existsSync(claudeState) && _fs.default.statSync(claudeState).isFile()) volumes.push(` - "${toDockerPath(claudeState)}:/home/node/.claude.json"`);
|
|
358
|
-
color.info(`Claude profile: ${claudeHome}`);
|
|
359
|
-
} else color.warn('No Claude profile found. Set CLAUDE_HOME or run "claude" locally to log in.');
|
|
365
|
+
if (claudeHome) color.info(`Claude profile: ${claudeHome}`);else color.warn('No Claude profile found. Set CLAUDE_HOME or run "claude" locally to log in.');
|
|
360
366
|
const overridePath = _path.default.join(projectDir, 'docker-compose.override.yaml');
|
|
361
367
|
if (volumes.length > 0) {
|
|
362
368
|
const override = ['services:', ' tools-dev:', ' volumes:', ...volumes].join('\n') + '\n';
|
|
@@ -539,7 +545,7 @@ async function claude(args) {
|
|
|
539
545
|
color.info(`Datagrok UI will be at: http://localhost:${dgPort}`);
|
|
540
546
|
|
|
541
547
|
// Write compose + .env to temp dir (no external file dependencies)
|
|
542
|
-
const projectDir = writeProjectFiles(taskKey, args, worktreeRoot, dgPort);
|
|
548
|
+
const projectDir = writeProjectFiles(taskKey, args, worktreeRoot, dgPort, repoRoot);
|
|
543
549
|
color.info(`Workspace: ${worktreeRoot}`);
|
|
544
550
|
|
|
545
551
|
// Start containers
|
|
@@ -549,11 +555,25 @@ async function claude(args) {
|
|
|
549
555
|
color.error('Failed to start containers.');
|
|
550
556
|
return false;
|
|
551
557
|
}
|
|
558
|
+
const containerName = `dg-pkg-${taskKey.toLowerCase()}-tools-dev-1`;
|
|
559
|
+
|
|
560
|
+
// Copy Claude credentials into the container (avoids bind-mount permission issues)
|
|
561
|
+
const claudeHomePath = findClaudeHome();
|
|
562
|
+
if (claudeHomePath) {
|
|
563
|
+
const claudeFiles = ['.credentials.json', 'settings.json', 'settings.local.json'];
|
|
564
|
+
for (const file of claudeFiles) {
|
|
565
|
+
const filePath = _path.default.join(claudeHomePath, file);
|
|
566
|
+
if (_fs.default.existsSync(filePath) && _fs.default.statSync(filePath).isFile()) (0, _child_process.spawnSync)('docker', ['cp', filePath, `${containerName}:/home/node/.claude/${file}`]);
|
|
567
|
+
}
|
|
568
|
+
const claudeState = _path.default.join(_path.default.dirname(claudeHomePath), '.claude.json');
|
|
569
|
+
if (_fs.default.existsSync(claudeState) && _fs.default.statSync(claudeState).isFile()) (0, _child_process.spawnSync)('docker', ['cp', claudeState, `${containerName}:/home/node/.claude.json`]);
|
|
570
|
+
// Fix ownership — docker cp creates files as root
|
|
571
|
+
(0, _child_process.spawnSync)('docker', ['exec', '-u', 'root', containerName, 'chown', '-R', 'node:node', '/home/node/.claude']);
|
|
572
|
+
}
|
|
552
573
|
|
|
553
574
|
// Determine Claude working directory based on repo type
|
|
554
575
|
// Only trust public-repo markers when we are inside a real git repo — packages can have
|
|
555
576
|
// public/js-api via node_modules symlinks, which would cause a false positive.
|
|
556
|
-
const containerName = `dg-pkg-${taskKey.toLowerCase()}-tools-dev-1`;
|
|
557
577
|
let claudeWorkDir;
|
|
558
578
|
if (repoRoot && _fs.default.existsSync(_path.default.join(repoRoot, 'js-api'))) claudeWorkDir = '/workspace/repo';else if (repoRoot && _fs.default.existsSync(_path.default.join(repoRoot, 'public', 'js-api'))) claudeWorkDir = '/workspace/repo/public';else {
|
|
559
579
|
// External repo: entrypoint clones public repo and creates symlink — wait for it
|
|
@@ -587,7 +607,7 @@ async function claude(args) {
|
|
|
587
607
|
const claudeArgs = ['--dangerously-skip-permissions'];
|
|
588
608
|
if (args.prompt) claudeArgs.push('-p', args.prompt);
|
|
589
609
|
color.info(`Launching Claude Code in container ${containerName}...`);
|
|
590
|
-
(0, _child_process.spawnSync)('docker', ['exec', '-it', '-w', claudeWorkDir, containerName, 'claude', ...claudeArgs], {
|
|
610
|
+
(0, _child_process.spawnSync)('docker', ['exec', '-it', '-u', 'node', '-w', claudeWorkDir, containerName, 'claude', ...claudeArgs], {
|
|
591
611
|
stdio: 'inherit'
|
|
592
612
|
});
|
|
593
613
|
|
package/package.json
CHANGED