create-max-framework 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # create-max-framework
2
+
3
+ Scaffold a new [MAX/MSP Claude Code Framework](https://github.com/taylorbrook/MAX-MSP_CC_Framework) project with a single command.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npx create-max-framework my-project
9
+ cd my-project
10
+ claude
11
+ ```
12
+
13
+ ## What it does
14
+
15
+ - Downloads the latest framework release from GitHub
16
+ - Sets up the project directory with all skills, commands, object database, and Python library
17
+ - Initializes a git repository and prints getting-started instructions
18
+
19
+ ## Prerequisites
20
+
21
+ - [Node.js](https://nodejs.org/) 16+ (for running this installer)
22
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (for using the framework)
23
+ - [MAX 9](https://cycling74.com/products/max) (for opening and testing generated patches)
24
+ - [Python 3.10+](https://www.python.org/) (for the validation and editing engine)
25
+
26
+ ## Links
27
+
28
+ - [Main repository](https://github.com/taylorbrook/MAX-MSP_CC_Framework)
29
+ - [Technical documentation](https://github.com/taylorbrook/MAX-MSP_CC_Framework/blob/main/TECHNICAL.md)
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const { spawn, execSync } = require('child_process');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const https = require('https');
9
+
10
+ const VERSION = '1.0.0';
11
+ const RELEASE_URL = 'https://github.com/taylorbrook/MAX-MSP_CC_Framework/releases/latest/download/framework.tar.gz';
12
+ const MAX_REDIRECTS = 5;
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Argument parsing
16
+ // ---------------------------------------------------------------------------
17
+
18
+ const args = process.argv.slice(2);
19
+
20
+ if (args.includes('--version') || args.includes('-v')) {
21
+ console.log(`create-max-framework v${VERSION}`);
22
+ process.exit(0);
23
+ }
24
+
25
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
26
+ printUsage();
27
+ process.exit(args.length === 0 ? 1 : 0);
28
+ }
29
+
30
+ const projectName = args[0];
31
+
32
+ if (projectName.startsWith('-')) {
33
+ console.error(`Error: Unknown flag "${projectName}".`);
34
+ printUsage();
35
+ process.exit(1);
36
+ }
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // Main
40
+ // ---------------------------------------------------------------------------
41
+
42
+ const targetDir = path.resolve(projectName);
43
+
44
+ if (fs.existsSync(targetDir)) {
45
+ console.error(`Error: Directory '${projectName}' already exists.`);
46
+ process.exit(1);
47
+ }
48
+
49
+ console.log(`\nCreating MAX/MSP Claude Code Framework in ${projectName}...\n`);
50
+
51
+ fs.mkdirSync(targetDir, { recursive: true });
52
+
53
+ downloadAndExtract(RELEASE_URL, targetDir)
54
+ .then(() => {
55
+ // Create patches directory and active-project config
56
+ const patchesDir = path.join(targetDir, 'patches');
57
+ if (!fs.existsSync(patchesDir)) {
58
+ fs.mkdirSync(patchesDir, { recursive: true });
59
+ }
60
+ fs.writeFileSync(
61
+ path.join(patchesDir, '.active-project.json'),
62
+ JSON.stringify({ active_project: null }, null, 2) + '\n'
63
+ );
64
+
65
+ // Initialize git repo
66
+ try {
67
+ execSync('git init', { cwd: targetDir, stdio: 'ignore' });
68
+ } catch (_) {
69
+ // git not available -- not critical
70
+ }
71
+
72
+ // Check Python version
73
+ checkPython();
74
+
75
+ // Success message
76
+ console.log(`Done! Your MAX/MSP Claude Code Framework project is ready.\n`);
77
+ console.log(`Next steps:`);
78
+ console.log(` cd ${projectName}`);
79
+ console.log(` claude`);
80
+ console.log(` /max-new my-first-patch\n`);
81
+ console.log(`Prerequisites:`);
82
+ console.log(` - Claude Code (https://docs.anthropic.com/en/docs/claude-code)`);
83
+ console.log(` - MAX 9 (https://cycling74.com/products/max)`);
84
+ console.log(` - Python 3.10+ (for the validation engine)\n`);
85
+ })
86
+ .catch((err) => {
87
+ console.error(`\nError: ${err.message || err}`);
88
+ // Clean up partial directory
89
+ try {
90
+ fs.rmSync(targetDir, { recursive: true, force: true });
91
+ } catch (_) {
92
+ // best effort cleanup
93
+ }
94
+ process.exit(1);
95
+ });
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // Helpers
99
+ // ---------------------------------------------------------------------------
100
+
101
+ function printUsage() {
102
+ console.log(`
103
+ Usage: npx create-max-framework <project-name>
104
+
105
+ Create a new MAX/MSP Claude Code Framework project.
106
+
107
+ Options:
108
+ -h, --help Show this help message
109
+ -v, --version Show version number
110
+
111
+ Examples:
112
+ npx create-max-framework my-synth
113
+ npx create-max-framework granular-sampler
114
+ `);
115
+ }
116
+
117
+ /**
118
+ * Download a URL, following up to MAX_REDIRECTS redirects,
119
+ * and pipe the response into tar to extract into targetDir.
120
+ */
121
+ function downloadAndExtract(url, dir) {
122
+ return new Promise((resolve, reject) => {
123
+ followRedirects(url, 0, (err, response) => {
124
+ if (err) return reject(err);
125
+
126
+ if (response.statusCode !== 200) {
127
+ response.resume(); // consume response to free memory
128
+ return reject(new Error(`Download failed with status ${response.statusCode}`));
129
+ }
130
+
131
+ const tar = spawn('tar', ['xz', '--strip-components=1', '-C', dir], {
132
+ stdio: ['pipe', 'inherit', 'pipe']
133
+ });
134
+
135
+ let tarStderr = '';
136
+ tar.stderr.on('data', (chunk) => { tarStderr += chunk.toString(); });
137
+
138
+ tar.on('close', (code) => {
139
+ if (code !== 0) {
140
+ return reject(new Error(`tar extraction failed (exit ${code}): ${tarStderr.trim()}`));
141
+ }
142
+ resolve();
143
+ });
144
+
145
+ tar.on('error', (spawnErr) => {
146
+ reject(new Error(`Failed to spawn tar: ${spawnErr.message}`));
147
+ });
148
+
149
+ response.pipe(tar.stdin);
150
+
151
+ response.on('error', (dlErr) => {
152
+ tar.kill();
153
+ reject(new Error(`Download error: ${dlErr.message}`));
154
+ });
155
+ });
156
+ });
157
+ }
158
+
159
+ /**
160
+ * Follow HTTP(S) redirects up to maxRedirects.
161
+ */
162
+ function followRedirects(url, count, callback) {
163
+ if (count >= MAX_REDIRECTS) {
164
+ return callback(new Error('Too many redirects'));
165
+ }
166
+
167
+ const protocol = url.startsWith('https') ? https : require('http');
168
+
169
+ protocol.get(url, (response) => {
170
+ const status = response.statusCode;
171
+
172
+ if (status === 301 || status === 302 || status === 303 || status === 307 || status === 308) {
173
+ const location = response.headers.location;
174
+ if (!location) {
175
+ return callback(new Error('Redirect with no Location header'));
176
+ }
177
+ response.resume(); // discard body
178
+ return followRedirects(location, count + 1, callback);
179
+ }
180
+
181
+ callback(null, response);
182
+ }).on('error', (err) => {
183
+ callback(err);
184
+ });
185
+ }
186
+
187
+ /**
188
+ * Check for Python 3.10+ and warn if missing or too old.
189
+ */
190
+ function checkPython() {
191
+ try {
192
+ const pyVersion = execSync('python3 --version', { encoding: 'utf8' }).trim();
193
+ const match = pyVersion.match(/Python\s+(\d+)\.(\d+)/);
194
+ if (match) {
195
+ const major = parseInt(match[1], 10);
196
+ const minor = parseInt(match[2], 10);
197
+ if (major < 3 || (major === 3 && minor < 10)) {
198
+ console.warn(`WARNING: Python 3.10+ required. Found: ${pyVersion}`);
199
+ }
200
+ }
201
+ } catch (_) {
202
+ console.warn('WARNING: Python 3 not found. The framework requires Python 3.10+ for the validation engine.');
203
+ }
204
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "create-max-framework",
3
+ "version": "1.0.0",
4
+ "description": "Create a MAX/MSP Claude Code Framework project",
5
+ "bin": {
6
+ "create-max-framework": "bin/create-max-framework.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "README.md"
11
+ ],
12
+ "keywords": [
13
+ "max",
14
+ "msp",
15
+ "maxmsp",
16
+ "claude",
17
+ "claude-code",
18
+ "audio",
19
+ "music",
20
+ "dsp"
21
+ ],
22
+ "author": "Taylor Brook",
23
+ "license": "MIT",
24
+ "engines": {
25
+ "node": ">=16.0.0"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/taylorbrook/MAX-MSP_CC_Framework.git",
30
+ "directory": "installer"
31
+ }
32
+ }