claude-code-templates 1.26.4 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Docker Sandbox Executor
5
+ * Runs inside Docker container using Claude Agent SDK
6
+ */
7
+
8
+ import { query } from '@anthropic-ai/claude-agent-sdk';
9
+ import fs from 'fs/promises';
10
+ import path from 'path';
11
+ import { spawn } from 'child_process';
12
+
13
+ // Parse command line arguments
14
+ const args = process.argv.slice(2);
15
+ const prompt = args[0] || 'Hello, Claude!';
16
+ const componentsToInstall = args[1] || '';
17
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
18
+
19
+ // Validate API key
20
+ if (!anthropicApiKey) {
21
+ console.error('āŒ Error: ANTHROPIC_API_KEY environment variable is required');
22
+ process.exit(1);
23
+ }
24
+
25
+ console.log('🐳 Docker Sandbox Executor');
26
+ console.log('═══════════════════════════════════════\n');
27
+
28
+ /**
29
+ * Install Claude Code components if specified
30
+ */
31
+ async function installComponents() {
32
+ if (!componentsToInstall || componentsToInstall.trim() === '') {
33
+ return true;
34
+ }
35
+
36
+ console.log('šŸ“¦ Installing components...');
37
+ console.log(` Components: ${componentsToInstall}\n`);
38
+
39
+ return new Promise((resolve) => {
40
+ const installCmd = `npx claude-code-templates@latest ${componentsToInstall} --yes`;
41
+
42
+ const child = spawn('sh', ['-c', installCmd], {
43
+ stdio: 'inherit',
44
+ env: process.env
45
+ });
46
+
47
+ child.on('close', (code) => {
48
+ if (code === 0) {
49
+ console.log('\nāœ… Components installed successfully\n');
50
+ resolve(true);
51
+ } else {
52
+ console.log('\nāš ļø Component installation had warnings (continuing...)\n');
53
+ resolve(true); // Continue even if installation has warnings
54
+ }
55
+ });
56
+
57
+ child.on('error', (error) => {
58
+ console.error(`āŒ Installation error: ${error.message}`);
59
+ resolve(false);
60
+ });
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Execute Claude Code query using Agent SDK
66
+ */
67
+ async function executeQuery() {
68
+ try {
69
+ console.log('šŸ¤– Executing Claude Code...');
70
+ console.log(` Prompt: "${prompt.substring(0, 80)}${prompt.length > 80 ? '...' : ''}"\n`);
71
+ console.log('─'.repeat(60));
72
+ console.log('šŸ“ CLAUDE OUTPUT:');
73
+ console.log('─'.repeat(60) + '\n');
74
+
75
+ // Enhance prompt with working directory context
76
+ const enhancedPrompt = `${prompt}\n\nNote: Your current working directory is /app. When creating files, save them in the current directory (/app) so they can be captured in the output.`;
77
+
78
+ // query() returns an async generator - we need to iterate it
79
+ const generator = query({
80
+ prompt: enhancedPrompt,
81
+ options: {
82
+ apiKey: anthropicApiKey,
83
+ model: 'claude-sonnet-4-5',
84
+ permissionMode: 'bypassPermissions', // Auto-allow all tool uses
85
+ }
86
+ });
87
+
88
+ let assistantResponses = [];
89
+ let messageCount = 0;
90
+
91
+ // Iterate through the async generator
92
+ for await (const message of generator) {
93
+ messageCount++;
94
+
95
+ if (message.type === 'assistant') {
96
+ // Extract text from assistant message content
97
+ if (message.message && message.message.content) {
98
+ const content = Array.isArray(message.message.content)
99
+ ? message.message.content
100
+ : [message.message.content];
101
+
102
+ content.forEach(block => {
103
+ if (block.type === 'text') {
104
+ console.log(block.text);
105
+ assistantResponses.push(block.text);
106
+ }
107
+ });
108
+ }
109
+ } else if (message.type === 'result') {
110
+ // Show final result metadata
111
+ console.log('\n' + '─'.repeat(60));
112
+ console.log(`āœ… Execution completed (${message.num_turns} turn${message.num_turns > 1 ? 's' : ''})`);
113
+ console.log(` Duration: ${message.duration_ms}ms`);
114
+ console.log(` Cost: $${message.total_cost_usd.toFixed(5)}`);
115
+ console.log('─'.repeat(60) + '\n');
116
+ }
117
+ }
118
+
119
+ // Show response summary
120
+ const responseText = assistantResponses.join('\n');
121
+ if (responseText) {
122
+ console.log('šŸ“„ Response Summary:');
123
+ console.log(` ${messageCount} message(s) received`);
124
+ console.log(` ${assistantResponses.length} assistant response(s)`);
125
+ console.log(` ${responseText.length} characters generated`);
126
+ console.log('');
127
+ }
128
+
129
+ return true;
130
+ } catch (error) {
131
+ console.error('\nāŒ Execution error:', error.message);
132
+ if (error.stack) {
133
+ console.error('\nStack trace:');
134
+ console.error(error.stack);
135
+ }
136
+ return false;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Find and copy generated files to output directory
142
+ */
143
+ async function copyGeneratedFiles() {
144
+ try {
145
+ console.log('šŸ“ Searching for generated files...\n');
146
+
147
+ // Common file extensions to look for
148
+ const extensions = [
149
+ 'js', 'jsx', 'ts', 'tsx',
150
+ 'py', 'html', 'css', 'scss',
151
+ 'json', 'md', 'yaml', 'yml',
152
+ 'txt', 'sh', 'bash'
153
+ ];
154
+
155
+ // Search for files in multiple directories
156
+ const { execSync } = await import('child_process');
157
+
158
+ const findPattern = extensions.map(ext => `-name "*.${ext}"`).join(' -o ');
159
+
160
+ // Search in /app and /tmp for generated files
161
+ const searchPaths = ['/app', '/tmp'];
162
+ let allFiles = [];
163
+
164
+ for (const searchPath of searchPaths) {
165
+ const findCmd = `find ${searchPath} -type f \\( ${findPattern} \\) ! -path "*/node_modules/*" ! -path "*/.npm/*" ! -path "/app/execute.js" ! -path "/app/package*.json" -newer /app/execute.js 2>/dev/null | head -50`;
166
+
167
+ try {
168
+ const output = execSync(findCmd, { encoding: 'utf8' });
169
+ const files = output.trim().split('\n').filter(f => f.trim());
170
+ allFiles = allFiles.concat(files);
171
+ } catch (error) {
172
+ // Continue to next search path
173
+ }
174
+ }
175
+
176
+ if (allFiles.length === 0) {
177
+ console.log('ā„¹ļø No generated files found\n');
178
+ return;
179
+ }
180
+
181
+ console.log(`šŸ“¦ Found ${allFiles.length} file(s):\n`);
182
+
183
+ // Copy files to output directory preserving structure
184
+ let copiedCount = 0;
185
+ for (const file of allFiles) {
186
+ try {
187
+ // Determine relative path based on source directory
188
+ let relativePath;
189
+ if (file.startsWith('/app/')) {
190
+ relativePath = file.replace('/app/', '');
191
+ } else if (file.startsWith('/tmp/')) {
192
+ relativePath = file.replace('/tmp/', '');
193
+ } else {
194
+ relativePath = path.basename(file);
195
+ }
196
+
197
+ const outputPath = path.join('/output', relativePath);
198
+
199
+ // Create directory structure
200
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
201
+
202
+ // Copy file
203
+ await fs.copyFile(file, outputPath);
204
+
205
+ console.log(` āœ… ${relativePath}`);
206
+ copiedCount++;
207
+ } catch (error) {
208
+ console.log(` āš ļø Failed to copy: ${file}`);
209
+ }
210
+ }
211
+
212
+ if (copiedCount > 0) {
213
+ console.log(`\nāœ… Copied ${copiedCount} file(s) to output directory\n`);
214
+ }
215
+ } catch (error) {
216
+ console.error('āŒ Error copying files:', error.message);
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Main execution flow
222
+ */
223
+ async function main() {
224
+ try {
225
+ // Step 1: Install components
226
+ const installSuccess = await installComponents();
227
+ if (!installSuccess) {
228
+ console.error('āŒ Component installation failed');
229
+ process.exit(1);
230
+ }
231
+
232
+ // Step 2: Execute Claude query
233
+ const executeSuccess = await executeQuery();
234
+ if (!executeSuccess) {
235
+ console.error('āŒ Query execution failed');
236
+ process.exit(1);
237
+ }
238
+
239
+ // Step 3: Copy generated files
240
+ await copyGeneratedFiles();
241
+
242
+ console.log('šŸŽ‰ Docker sandbox execution completed successfully!');
243
+ process.exit(0);
244
+ } catch (error) {
245
+ console.error('āŒ Fatal error:', error.message);
246
+ process.exit(1);
247
+ }
248
+ }
249
+
250
+ // Run main function
251
+ main();
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "claude-code-docker-sandbox",
3
+ "version": "1.0.0",
4
+ "description": "Docker sandbox for Claude Code execution with Claude Agent SDK",
5
+ "main": "docker-launcher.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "docker build -t claude-sandbox .",
9
+ "clean": "docker rmi claude-sandbox || true"
10
+ },
11
+ "dependencies": {
12
+ "@anthropic-ai/claude-agent-sdk": "^0.1.30"
13
+ },
14
+ "engines": {
15
+ "node": ">=18.0.0"
16
+ },
17
+ "keywords": [
18
+ "claude",
19
+ "docker",
20
+ "sandbox",
21
+ "ai",
22
+ "agent"
23
+ ],
24
+ "author": "Claude Code Templates",
25
+ "license": "MIT"
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.26.4",
3
+ "version": "1.28.0",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -94,6 +94,7 @@
94
94
  "src/",
95
95
  "components/sandbox/e2b/",
96
96
  "components/sandbox/cloudflare/",
97
+ "components/sandbox/docker/",
97
98
  "README.md"
98
99
  ],
99
100
  "devDependencies": {