create-claude-docker 1.0.1
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/LICENSE +21 -0
- package/README.md +326 -0
- package/bin/create.js +226 -0
- package/package.json +45 -0
- package/template/.claude/agents/architecture-reviewer.md +134 -0
- package/template/.claude/agents/backend-node-pro.md +177 -0
- package/template/.claude/agents/debugging-expert.md +124 -0
- package/template/.claude/agents/technical-writer.md +128 -0
- package/template/.claude/agents/ui-architect.md +82 -0
- package/template/.claude/settings.json +21 -0
- package/template/.docker/Dockerfile +47 -0
- package/template/.docker/entrypoint.sh +128 -0
- package/template/.env.example +25 -0
- package/template/README.md +53 -0
- package/template/docker-compose.yml +22 -0
- package/template/gitignore.template +7 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 create-claude-docker contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# create-claude-docker
|
|
2
|
+
|
|
3
|
+
Create Docker-based Claude Code development environment with **Z.AI GLM-4.7** support.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/create-claude-docker)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🐳 **Docker-based**: Isolated environment for each project
|
|
11
|
+
- 🔑 **Auto-configured**: API key injection on container start
|
|
12
|
+
- 🤖 **Z.AI GLM-4.7**: Pre-configured for Z.AI's Claude-compatible models
|
|
13
|
+
- 👤 **Non-root user**: Supports `--dangerously-skip-permissions` flag
|
|
14
|
+
- 🛠️ **Default agents**: Pre-configured specialized agents (backend, frontend, debugging, etc.)
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### Create a new project with npx
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Interactive mode
|
|
22
|
+
npx create-claude-docker my-project
|
|
23
|
+
|
|
24
|
+
# With options
|
|
25
|
+
npx create-claude-docker my-project --description "My AI project" --author "Your Name"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### CLI Options
|
|
29
|
+
|
|
30
|
+
| Option | Alias | Description |
|
|
31
|
+
|--------|-------|-------------|
|
|
32
|
+
| `--description` | `-d` | Project description |
|
|
33
|
+
| `--author` | `-a` | Author name |
|
|
34
|
+
|
|
35
|
+
### After creation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd my-project
|
|
39
|
+
|
|
40
|
+
# Add your Z.AI API key
|
|
41
|
+
nano .env
|
|
42
|
+
|
|
43
|
+
# Build and start
|
|
44
|
+
npm run docker:build
|
|
45
|
+
npm run docker:up
|
|
46
|
+
|
|
47
|
+
# Run Claude Code
|
|
48
|
+
npm run claude:unsafe
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Manual Setup (Alternative)
|
|
52
|
+
|
|
53
|
+
### Option 2: Using Z.AI GLM-4.7 Models
|
|
54
|
+
|
|
55
|
+
Z.AI provides GLM-4.7 models that are compatible with Claude Code through an Anthropic-compatible API endpoint.
|
|
56
|
+
|
|
57
|
+
1. **Get Z.AI API key:**
|
|
58
|
+
- Visit: https://z.ai/manage-apikey/apikey-list
|
|
59
|
+
- Or: https://open.bigmodel.cn/
|
|
60
|
+
- Sign up and get your API key
|
|
61
|
+
|
|
62
|
+
2. **Configure environment:**
|
|
63
|
+
```bash
|
|
64
|
+
cp .env.example .env
|
|
65
|
+
# Edit .env and set your Z.AI API key:
|
|
66
|
+
ZAI_API_KEY=your-zai-api-key-here
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
3. **Build and start:**
|
|
70
|
+
```bash
|
|
71
|
+
npm run docker:build
|
|
72
|
+
npm run docker:up
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The container will **automatically configure** Claude Code with your API key on startup. You should see:
|
|
76
|
+
```
|
|
77
|
+
🚀 Starting Claude Code container...
|
|
78
|
+
🔧 Configuring Claude Code settings...
|
|
79
|
+
✅ Claude Code configured with Z.AI API key
|
|
80
|
+
📋 Current settings.json:
|
|
81
|
+
...
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
4. **Run Claude Code:**
|
|
85
|
+
```bash
|
|
86
|
+
npm run claude:unsafe
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
5. **Verify configuration:**
|
|
90
|
+
Once inside Claude Code, run `/status` to check the current model in use.
|
|
91
|
+
You should see `glm-4.7` as the active model.
|
|
92
|
+
|
|
93
|
+
## Switching Between Models
|
|
94
|
+
|
|
95
|
+
### To switch from GLM-4.7 back to Anthropic Claude:
|
|
96
|
+
|
|
97
|
+
1. Edit `.env` and set `ANTHROPIC_API_KEY` to your Anthropic key
|
|
98
|
+
2. Remove or edit `.claude/settings.json` to remove the GLM model configuration
|
|
99
|
+
3. Restart the container:
|
|
100
|
+
```bash
|
|
101
|
+
npm run docker:down
|
|
102
|
+
npm run docker:up
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### To customize model selection:
|
|
106
|
+
|
|
107
|
+
Edit `./claude-data/settings.json` (created on first run) or `.claude/settings.json`:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"env": {
|
|
112
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-3-5-haiku-20241022",
|
|
113
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-3-5-sonnet-20241022",
|
|
114
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-3-5-sonnet-20241022"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Available Commands
|
|
120
|
+
|
|
121
|
+
| Command | Description |
|
|
122
|
+
|---------|-------------|
|
|
123
|
+
| `npm run docker:build` | Build Docker image |
|
|
124
|
+
| `npm run docker:up` | Start container in background |
|
|
125
|
+
| `npm run docker:down` | Stop and remove container |
|
|
126
|
+
| `npm run docker:logs` | View container logs |
|
|
127
|
+
| `npm run docker:shell` | Open bash shell in container |
|
|
128
|
+
| `npm run claude` | Run Claude Code (normal mode) |
|
|
129
|
+
| `npm run claude:unsafe` | Run Claude Code with --dangerously-skip-permissions |
|
|
130
|
+
|
|
131
|
+
## Project Structure
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
.
|
|
135
|
+
├── .docker/
|
|
136
|
+
│ └── Dockerfile # Docker image definition
|
|
137
|
+
├── .claude/
|
|
138
|
+
│ ├── settings.json # Default GLM-4.7 model configuration
|
|
139
|
+
│ └── agents/ # Default agent configurations
|
|
140
|
+
│ ├── backend-node-pro.md
|
|
141
|
+
│ ├── ui-architect.md
|
|
142
|
+
│ ├── debugging-expert.md
|
|
143
|
+
│ ├── architecture-reviewer.md
|
|
144
|
+
│ └── technical-writer.md
|
|
145
|
+
├── .env.example # Environment variables template
|
|
146
|
+
├── docker-compose.yml # Docker Compose configuration
|
|
147
|
+
├── package.json # NPM scripts
|
|
148
|
+
├── claude-data/ # Claude Code config (auto-created, overrides .claude/)
|
|
149
|
+
└── README.md # This file
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Default Agents
|
|
153
|
+
|
|
154
|
+
The boilerplate includes pre-configured specialized agents:
|
|
155
|
+
|
|
156
|
+
| Agent | Purpose | Model |
|
|
157
|
+
|-------|---------|-------|
|
|
158
|
+
| `backend-node-pro` | Backend Node.js development (API clients, workers, Firebase) | Opus/GLM-4.7 |
|
|
159
|
+
| `ui-architect` | Frontend/React design (components, styling, UX) | Opus/GLM-4.7 |
|
|
160
|
+
| `debugging-expert` | Debugging complex issues and root cause analysis | Opus/GLM-4.7 |
|
|
161
|
+
| `architecture-reviewer` | System design evaluation and architectural decisions | Sonnet/GLM-4.7 |
|
|
162
|
+
| `technical-writer` | Documentation, API references, guides | Sonnet/GLM-4.7 |
|
|
163
|
+
|
|
164
|
+
## Configuration
|
|
165
|
+
|
|
166
|
+
### Non-Root User
|
|
167
|
+
|
|
168
|
+
The container runs as user `claude` (UID 2000) to satisfy Claude Code's security requirements when using `--dangerously-skip-permissions`.
|
|
169
|
+
|
|
170
|
+
### Environment Variables
|
|
171
|
+
|
|
172
|
+
Create a `.env` file from `.env.example`:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Option 1: Anthropic Claude
|
|
176
|
+
ANTHROPIC_API_KEY=sk-ant-xxxxx
|
|
177
|
+
|
|
178
|
+
# Option 2: Z.AI GLM-4.7 (uses ZAI_API_KEY, overrides ANTHROPIC_API_KEY)
|
|
179
|
+
ZAI_API_KEY=your-zai-api-key-here
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Default Configuration
|
|
183
|
+
|
|
184
|
+
The container **automatically generates** `settings.json` on every startup using your API key from `.env`.
|
|
185
|
+
|
|
186
|
+
- **API key injection**: The entrypoint script reads `ZAI_API_KEY` (or `ANTHROPIC_API_KEY`) and creates a properly configured `settings.json`
|
|
187
|
+
- **Agents**: Pre-defined agent configurations from `.claude/agents/` are copied on first run
|
|
188
|
+
- **Persistence**: Settings are stored in `./claude-data/` volume
|
|
189
|
+
|
|
190
|
+
**Important:** Changes to `./claude-data/settings.json` will be overwritten on container restart. To persist custom settings, modify `.docker/entrypoint.sh`.
|
|
191
|
+
|
|
192
|
+
### Git Integration
|
|
193
|
+
|
|
194
|
+
Your host's `.gitconfig` is mounted read-only at `/home/claude/.gitconfig`, so commits in the container will be signed with your credentials.
|
|
195
|
+
|
|
196
|
+
## Manual Docker Commands
|
|
197
|
+
|
|
198
|
+
If you prefer running Docker commands directly:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Build and start
|
|
202
|
+
docker compose up -d --build
|
|
203
|
+
|
|
204
|
+
# Enter container
|
|
205
|
+
docker compose exec claude bash
|
|
206
|
+
|
|
207
|
+
# Run claude directly
|
|
208
|
+
docker compose exec claude claude --dangerously-skip-permissions
|
|
209
|
+
|
|
210
|
+
# Stop
|
|
211
|
+
docker compose down
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Tips
|
|
215
|
+
|
|
216
|
+
1. **First setup**: Run `npm run docker:build && npm run docker:up` before first use
|
|
217
|
+
2. **Persistent config**: Claude Code settings stored in `./claude-data/` (gitignore this)
|
|
218
|
+
3. **Shared gitconfig**: Commits use your host's git identity
|
|
219
|
+
4. **Workspace**: Project mounted at `/workspace` in container
|
|
220
|
+
5. **GLM-4.7 users**: The default `settings.json` is pre-configured for GLM-4.7. Just set your Z.AI API key in `.env`
|
|
221
|
+
6. **Reset config**: Delete `./claude-data/` and restart to revert to default configuration
|
|
222
|
+
7. **Custom agents**: Add new `.md` files to `.claude/agents/` or `./claude-data/agents/` before building
|
|
223
|
+
|
|
224
|
+
### Multi-line Prompts in Docker Container
|
|
225
|
+
|
|
226
|
+
The `/terminal-setup` command doesn't work in Docker containers (detected as `xterm`). Use these alternatives:
|
|
227
|
+
|
|
228
|
+
| Method | How to use |
|
|
229
|
+
|--------|------------|
|
|
230
|
+
| **Ctrl+J** | Press `Ctrl+J` to insert a new line (recommended) |
|
|
231
|
+
| **Backslash** | Type `\` before pressing Enter to continue on next line |
|
|
232
|
+
|
|
233
|
+
Example with backslash:
|
|
234
|
+
```
|
|
235
|
+
> This is line one\
|
|
236
|
+
and this continues on line two\
|
|
237
|
+
and line three
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Troubleshooting
|
|
241
|
+
|
|
242
|
+
### GLM-4.7 Configuration Not Working
|
|
243
|
+
|
|
244
|
+
1. **Check API key**: Ensure `ZAI_API_KEY` or `ANTHROPIC_API_KEY` is set in your `.env` file
|
|
245
|
+
2. **Check container logs** to verify settings were generated:
|
|
246
|
+
```bash
|
|
247
|
+
npm run docker:logs
|
|
248
|
+
# Should show: ✅ Claude Code configured with Z.AI API key
|
|
249
|
+
```
|
|
250
|
+
3. **Verify settings.json**: Run `/status` in Claude Code to see current model
|
|
251
|
+
4. **Debug inside container**:
|
|
252
|
+
```bash
|
|
253
|
+
npm run docker:shell
|
|
254
|
+
cat ~/.claude/settings.json
|
|
255
|
+
```
|
|
256
|
+
5. **Rebuild and restart** (if API key changed):
|
|
257
|
+
```bash
|
|
258
|
+
npm run docker:down
|
|
259
|
+
npm run docker:up
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Permission Denied Errors
|
|
263
|
+
|
|
264
|
+
The container runs as non-root user `claude` (UID 2000). If you encounter permission issues:
|
|
265
|
+
|
|
266
|
+
1. **Check file ownership**: Ensure your project files are accessible by UID 2000
|
|
267
|
+
2. **Adjust UID**: Modify the UID in Dockerfile if needed (currently 2000)
|
|
268
|
+
|
|
269
|
+
## Project Structure
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
create-claude-docker/
|
|
273
|
+
├── bin/
|
|
274
|
+
│ └── create.js # CLI entry point
|
|
275
|
+
├── template/ # Boilerplate files copied to new projects
|
|
276
|
+
│ ├── .docker/
|
|
277
|
+
│ │ ├── Dockerfile
|
|
278
|
+
│ │ └── entrypoint.sh
|
|
279
|
+
│ ├── .claude/
|
|
280
|
+
│ │ ├── settings.json
|
|
281
|
+
│ │ └── agents/
|
|
282
|
+
│ ├── .env.example
|
|
283
|
+
│ ├── .gitignore
|
|
284
|
+
│ ├── docker-compose.yml
|
|
285
|
+
│ └── README.md
|
|
286
|
+
├── package.json
|
|
287
|
+
└── README.md
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Publishing to npm
|
|
291
|
+
|
|
292
|
+
To publish this package to npm:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Login to npm
|
|
296
|
+
npm login
|
|
297
|
+
|
|
298
|
+
# Update version
|
|
299
|
+
npm version patch # or minor, major
|
|
300
|
+
|
|
301
|
+
# Publish
|
|
302
|
+
npm publish
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
After publishing, users can create new projects with:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
npx create-claude-docker my-awesome-project
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Development
|
|
312
|
+
|
|
313
|
+
To test the CLI locally:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# From the repository root
|
|
317
|
+
node bin/create.js test-project
|
|
318
|
+
|
|
319
|
+
# Or link globally
|
|
320
|
+
npm link
|
|
321
|
+
create-claude-docker test-project
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## License
|
|
325
|
+
|
|
326
|
+
MIT
|
package/bin/create.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-claude-docker CLI
|
|
5
|
+
* Creates a new Claude Code Docker project from template
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const readline = require('readline');
|
|
11
|
+
const { execSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
// ANSI colors
|
|
14
|
+
const colors = {
|
|
15
|
+
reset: '\x1b[0m',
|
|
16
|
+
bright: '\x1b[1m',
|
|
17
|
+
green: '\x1b[32m',
|
|
18
|
+
cyan: '\x1b[36m',
|
|
19
|
+
yellow: '\x1b[33m',
|
|
20
|
+
red: '\x1b[31m',
|
|
21
|
+
dim: '\x1b[2m',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const log = {
|
|
25
|
+
info: (msg) => console.log(`${colors.cyan}ℹ${colors.reset} ${msg}`),
|
|
26
|
+
success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
|
|
27
|
+
warn: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
|
|
28
|
+
error: (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`),
|
|
29
|
+
step: (msg) => console.log(`${colors.dim} ${msg}${colors.reset}`),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const rl = readline.createInterface({
|
|
33
|
+
input: process.stdin,
|
|
34
|
+
output: process.stdout,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
function ask(question, defaultValue = '') {
|
|
38
|
+
const defaultHint = defaultValue ? ` ${colors.dim}(${defaultValue})${colors.reset}` : '';
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
rl.question(`${question}${defaultHint}: `, (answer) => {
|
|
41
|
+
resolve(answer.trim() || defaultValue);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function copyRecursive(src, dest, replacements = {}) {
|
|
47
|
+
const stats = fs.statSync(src);
|
|
48
|
+
|
|
49
|
+
if (stats.isDirectory()) {
|
|
50
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
51
|
+
const files = fs.readdirSync(src);
|
|
52
|
+
for (const file of files) {
|
|
53
|
+
copyRecursive(path.join(src, file), path.join(dest, file), replacements);
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
let content = fs.readFileSync(src, 'utf8');
|
|
57
|
+
|
|
58
|
+
// Apply replacements for text files
|
|
59
|
+
if (!isBinaryFile(src)) {
|
|
60
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
61
|
+
content = content.replace(new RegExp(key, 'g'), value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fs.writeFileSync(dest, content);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isBinaryFile(filePath) {
|
|
70
|
+
const binaryExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.ico', '.woff', '.woff2', '.ttf', '.eot'];
|
|
71
|
+
return binaryExtensions.some(ext => filePath.endsWith(ext));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function toKebabCase(str) {
|
|
75
|
+
return str
|
|
76
|
+
.toLowerCase()
|
|
77
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
78
|
+
.replace(/^-|-$/g, '');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function main() {
|
|
82
|
+
console.log(`
|
|
83
|
+
${colors.bright}${colors.cyan}╔═══════════════════════════════════════════════════════════╗
|
|
84
|
+
║ create-claude-docker ║
|
|
85
|
+
║ Docker-based Claude Code development environment ║
|
|
86
|
+
╚═══════════════════════════════════════════════════════════╝${colors.reset}
|
|
87
|
+
`);
|
|
88
|
+
|
|
89
|
+
// Get project name from args or prompt
|
|
90
|
+
let projectName = process.argv[2];
|
|
91
|
+
let description = '';
|
|
92
|
+
let author = '';
|
|
93
|
+
|
|
94
|
+
// Parse CLI arguments
|
|
95
|
+
const args = process.argv.slice(2);
|
|
96
|
+
const descIndex = args.findIndex(a => a === '--description' || a === '-d');
|
|
97
|
+
if (descIndex !== -1 && args[descIndex + 1]) {
|
|
98
|
+
description = args[descIndex + 1];
|
|
99
|
+
args.splice(descIndex, 2);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const authorIndex = args.findIndex(a => a === '--author' || a === '-a');
|
|
103
|
+
if (authorIndex !== -1 && args[authorIndex + 1]) {
|
|
104
|
+
author = args[authorIndex + 1];
|
|
105
|
+
args.splice(authorIndex, 2);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
projectName = args[0];
|
|
109
|
+
|
|
110
|
+
// Interactive prompts if not provided
|
|
111
|
+
if (!projectName) {
|
|
112
|
+
projectName = await ask('Project name', 'my-claude-project');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
projectName = toKebabCase(projectName);
|
|
116
|
+
|
|
117
|
+
if (!description) {
|
|
118
|
+
description = await ask('Description', 'A Claude Code Docker project');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!author) {
|
|
122
|
+
try {
|
|
123
|
+
author = execSync('git config user.name', { encoding: 'utf8' }).trim();
|
|
124
|
+
} catch {
|
|
125
|
+
author = '';
|
|
126
|
+
}
|
|
127
|
+
author = await ask('Author', author);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
rl.close();
|
|
131
|
+
|
|
132
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
133
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
134
|
+
|
|
135
|
+
// Check if directory exists
|
|
136
|
+
if (fs.existsSync(targetDir)) {
|
|
137
|
+
log.error(`Directory "${projectName}" already exists!`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log('');
|
|
142
|
+
log.info(`Creating project "${projectName}"...`);
|
|
143
|
+
|
|
144
|
+
// Create project directory
|
|
145
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
146
|
+
log.step('Created project directory');
|
|
147
|
+
|
|
148
|
+
// Copy template files
|
|
149
|
+
copyRecursive(templateDir, targetDir);
|
|
150
|
+
log.step('Copied template files');
|
|
151
|
+
|
|
152
|
+
// Generate package.json
|
|
153
|
+
const packageJson = {
|
|
154
|
+
name: projectName,
|
|
155
|
+
version: '1.0.0',
|
|
156
|
+
description: description,
|
|
157
|
+
author: author,
|
|
158
|
+
scripts: {
|
|
159
|
+
'docker:build': 'docker compose build',
|
|
160
|
+
'docker:up': 'docker compose up -d',
|
|
161
|
+
'docker:down': 'docker compose down',
|
|
162
|
+
'docker:logs': 'docker compose logs -f',
|
|
163
|
+
'docker:shell': 'docker compose exec claude bash',
|
|
164
|
+
'claude': 'docker compose exec claude claude',
|
|
165
|
+
'claude:unsafe': 'docker compose exec claude claude --dangerously-skip-permissions',
|
|
166
|
+
},
|
|
167
|
+
keywords: ['claude-code', 'docker', 'anthropic', 'z-ai', 'glm-4'],
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
fs.writeFileSync(
|
|
171
|
+
path.join(targetDir, 'package.json'),
|
|
172
|
+
JSON.stringify(packageJson, null, 2) + '\n'
|
|
173
|
+
);
|
|
174
|
+
log.step('Generated package.json');
|
|
175
|
+
|
|
176
|
+
// Create .env from .env.example
|
|
177
|
+
const envExamplePath = path.join(targetDir, '.env.example');
|
|
178
|
+
const envPath = path.join(targetDir, '.env');
|
|
179
|
+
if (fs.existsSync(envExamplePath)) {
|
|
180
|
+
fs.copyFileSync(envExamplePath, envPath);
|
|
181
|
+
log.step('Created .env from .env.example');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Rename gitignore.template to .gitignore (npm pack ignores .gitignore files)
|
|
185
|
+
const gitignoreTemplate = path.join(targetDir, 'gitignore.template');
|
|
186
|
+
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
187
|
+
if (fs.existsSync(gitignoreTemplate)) {
|
|
188
|
+
fs.renameSync(gitignoreTemplate, gitignorePath);
|
|
189
|
+
log.step('Created .gitignore');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Initialize git (optional)
|
|
193
|
+
try {
|
|
194
|
+
execSync('git init', { cwd: targetDir, stdio: 'ignore' });
|
|
195
|
+
execSync('git add .', { cwd: targetDir, stdio: 'ignore' });
|
|
196
|
+
log.step('Initialized git repository');
|
|
197
|
+
} catch {
|
|
198
|
+
log.warn('Could not initialize git repository');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
console.log('');
|
|
202
|
+
log.success(`Project "${projectName}" created successfully!`);
|
|
203
|
+
|
|
204
|
+
console.log(`
|
|
205
|
+
${colors.bright}Next steps:${colors.reset}
|
|
206
|
+
|
|
207
|
+
${colors.cyan}cd ${projectName}${colors.reset}
|
|
208
|
+
|
|
209
|
+
${colors.dim}# Add your Z.AI API key${colors.reset}
|
|
210
|
+
${colors.cyan}nano .env${colors.reset}
|
|
211
|
+
|
|
212
|
+
${colors.dim}# Build and start the container${colors.reset}
|
|
213
|
+
${colors.cyan}npm run docker:build${colors.reset}
|
|
214
|
+
${colors.cyan}npm run docker:up${colors.reset}
|
|
215
|
+
|
|
216
|
+
${colors.dim}# Run Claude Code${colors.reset}
|
|
217
|
+
${colors.cyan}npm run claude:unsafe${colors.reset}
|
|
218
|
+
|
|
219
|
+
${colors.dim}Documentation: https://github.com/fishinthenet/create-claude-docker${colors.reset}
|
|
220
|
+
`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
main().catch((err) => {
|
|
224
|
+
log.error(err.message);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-claude-docker",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Create Docker-based Claude Code development environment with Z.AI GLM-4.7 support",
|
|
5
|
+
"author": "Szymon <szymon@fishinthenet.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/fishinthenet/create-claude-docker.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/fishinthenet/create-claude-docker/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/fishinthenet/create-claude-docker#readme",
|
|
15
|
+
"bin": {
|
|
16
|
+
"create-claude-docker": "./bin/create.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin",
|
|
20
|
+
"template"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude-code",
|
|
24
|
+
"docker",
|
|
25
|
+
"anthropic",
|
|
26
|
+
"z-ai",
|
|
27
|
+
"glm-4",
|
|
28
|
+
"boilerplate",
|
|
29
|
+
"create",
|
|
30
|
+
"cli"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"docker:build": "docker compose build",
|
|
37
|
+
"docker:up": "docker compose up -d",
|
|
38
|
+
"docker:down": "docker compose down",
|
|
39
|
+
"docker:logs": "docker compose logs -f",
|
|
40
|
+
"docker:shell": "docker compose exec claude bash",
|
|
41
|
+
"claude": "docker compose exec claude claude",
|
|
42
|
+
"claude:unsafe": "docker compose exec claude claude --dangerously-skip-permissions",
|
|
43
|
+
"test": "node bin/create.js --help"
|
|
44
|
+
}
|
|
45
|
+
}
|