@mattstratton/install-marketing-skills 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 +40 -0
- package/bin/install.js +369 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @mattstratton/install-marketing-skills
|
|
2
|
+
|
|
3
|
+
One-line installer for the **tigerdata-marketing-skills** Cowork (Claude Desktop) plugin.
|
|
4
|
+
|
|
5
|
+
Workaround for [anthropics/claude-code#40600](https://github.com/anthropics/claude-code/issues/40600) — Cowork's `RemotePluginManager` can wipe marketplace-installed plugins on restart. This installer writes directly to the `LocalPluginsReader` path, which persists.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install or update to the latest version
|
|
11
|
+
npx @mattstratton/install-marketing-skills
|
|
12
|
+
|
|
13
|
+
# Check if an update is available (doesn't install)
|
|
14
|
+
npx @mattstratton/install-marketing-skills --check
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
1. Fetches the latest release from [timescale/marketing-skills](https://github.com/timescale/marketing-skills/releases)
|
|
20
|
+
2. Downloads the plugin zip (no git clone needed)
|
|
21
|
+
3. Finds your Cowork installation(s)
|
|
22
|
+
4. Installs the plugin into `cowork_plugins/cache/` where it persists across restarts
|
|
23
|
+
5. Enables the plugin in `cowork_settings.json`
|
|
24
|
+
|
|
25
|
+
**Restart Claude Desktop after running** for changes to take effect.
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- Node.js 18+
|
|
30
|
+
- Claude Desktop installed (Cowork must have been opened at least once)
|
|
31
|
+
|
|
32
|
+
## Platforms
|
|
33
|
+
|
|
34
|
+
Works on macOS, Windows, and Linux.
|
|
35
|
+
|
|
36
|
+
On macOS, you can also use the shell script (no Node.js required):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
curl -fsSL https://raw.githubusercontent.com/timescale/marketing-skills/main/scripts/install.sh | bash
|
|
40
|
+
```
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// install.js — Cross-platform installer for tigerdata-marketing-skills
|
|
6
|
+
//
|
|
7
|
+
// Downloads the latest release zip from GitHub and installs it into the
|
|
8
|
+
// Cowork LocalPluginsReader path, which persists across restarts.
|
|
9
|
+
// Workaround for https://github.com/anthropics/claude-code/issues/40600
|
|
10
|
+
//
|
|
11
|
+
// Usage:
|
|
12
|
+
// npx @mattstratton/install-marketing-skills # Install or update
|
|
13
|
+
// npx @mattstratton/install-marketing-skills --check # Check if update available
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
const https = require('https');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const crypto = require('crypto');
|
|
21
|
+
const { execFileSync } = require('child_process');
|
|
22
|
+
|
|
23
|
+
// --- Configuration ---------------------------------------------------------
|
|
24
|
+
const REPO = 'timescale/marketing-skills';
|
|
25
|
+
const MARKETPLACE_NAME = 'tigerdata-marketing';
|
|
26
|
+
const PLUGIN_NAME = 'tigerdata-marketing-skills';
|
|
27
|
+
const PLUGIN_KEY = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
|
|
28
|
+
const MARKETPLACE_GITHUB = 'timescale/marketing-skills';
|
|
29
|
+
|
|
30
|
+
// --- Output helpers --------------------------------------------------------
|
|
31
|
+
const GREEN = '\x1b[32m';
|
|
32
|
+
const YELLOW = '\x1b[33m';
|
|
33
|
+
const RED = '\x1b[31m';
|
|
34
|
+
const BOLD = '\x1b[1m';
|
|
35
|
+
const NC = '\x1b[0m';
|
|
36
|
+
|
|
37
|
+
function info(msg) { console.log(`${GREEN}✓${NC} ${msg}`); }
|
|
38
|
+
function warn(msg) { console.log(`${YELLOW}!${NC} ${msg}`); }
|
|
39
|
+
function error(msg) { console.error(`${RED}✗${NC} ${msg}`); process.exit(1); }
|
|
40
|
+
|
|
41
|
+
// --- HTTP helpers (zero deps) ----------------------------------------------
|
|
42
|
+
function httpsGet(url, redirects = 0) {
|
|
43
|
+
if (redirects > 10) return Promise.reject(new Error('Too many redirects'));
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
https.get(url, { headers: { 'User-Agent': 'install-marketing-skills' } }, (res) => {
|
|
46
|
+
// Follow redirects
|
|
47
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
48
|
+
return httpsGet(res.headers.location, redirects + 1).then(resolve, reject);
|
|
49
|
+
}
|
|
50
|
+
if (res.statusCode !== 200) {
|
|
51
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
52
|
+
}
|
|
53
|
+
const chunks = [];
|
|
54
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
55
|
+
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
56
|
+
res.on('error', reject);
|
|
57
|
+
}).on('error', reject);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function fetchJSON(url) {
|
|
62
|
+
const buf = await httpsGet(url);
|
|
63
|
+
return JSON.parse(buf.toString('utf-8'));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function downloadFile(url, destPath) {
|
|
67
|
+
const buf = await httpsGet(url);
|
|
68
|
+
fs.writeFileSync(destPath, buf);
|
|
69
|
+
return buf.length;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- Platform detection ----------------------------------------------------
|
|
73
|
+
function getSessionsRoot() {
|
|
74
|
+
switch (os.platform()) {
|
|
75
|
+
case 'darwin':
|
|
76
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions');
|
|
77
|
+
case 'win32': {
|
|
78
|
+
const appdata = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
|
|
79
|
+
return path.join(appdata, 'Claude', 'local-agent-mode-sessions');
|
|
80
|
+
}
|
|
81
|
+
default: // linux
|
|
82
|
+
return path.join(os.homedir(), '.config', 'Claude', 'local-agent-mode-sessions');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// --- Zip extraction (platform-native, no deps) -----------------------------
|
|
87
|
+
function extractZip(zipPath, destDir) {
|
|
88
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
89
|
+
if (os.platform() === 'win32') {
|
|
90
|
+
// PowerShell's Expand-Archive
|
|
91
|
+
const escapedZip = zipPath.replace(/"/g, '`"');
|
|
92
|
+
const escapedDest = destDir.replace(/"/g, '`"');
|
|
93
|
+
execFileSync('powershell', [
|
|
94
|
+
'-NoProfile', '-Command',
|
|
95
|
+
`Expand-Archive -LiteralPath "${escapedZip}" -DestinationPath "${escapedDest}" -Force`,
|
|
96
|
+
], { stdio: 'pipe' });
|
|
97
|
+
} else {
|
|
98
|
+
execFileSync('unzip', ['-q', zipPath, '-d', destDir], { stdio: 'pipe' });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// --- JSON helpers ----------------------------------------------------------
|
|
103
|
+
function readJSON(filePath, defaultValue) {
|
|
104
|
+
try {
|
|
105
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
106
|
+
} catch {
|
|
107
|
+
return defaultValue !== undefined ? defaultValue : {};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function writeJSON(filePath, data) {
|
|
112
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// --- File hashing ----------------------------------------------------------
|
|
116
|
+
function sha256File(filePath) {
|
|
117
|
+
const content = fs.readFileSync(filePath);
|
|
118
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function collectFileHashes(dir) {
|
|
122
|
+
const hashes = {};
|
|
123
|
+
function walk(currentDir) {
|
|
124
|
+
for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) {
|
|
125
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
walk(fullPath);
|
|
128
|
+
} else if (!entry.name.includes('.DS_Store')) {
|
|
129
|
+
const rel = path.relative(dir, fullPath);
|
|
130
|
+
// Normalize to forward slashes for cross-platform consistency
|
|
131
|
+
hashes[rel.split(path.sep).join('/')] = sha256File(fullPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
walk(dir);
|
|
136
|
+
return hashes;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// --- Discovery -------------------------------------------------------------
|
|
140
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
141
|
+
|
|
142
|
+
function discoverInstallations(sessionsRoot) {
|
|
143
|
+
const results = [];
|
|
144
|
+
|
|
145
|
+
if (!fs.existsSync(sessionsRoot)) {
|
|
146
|
+
error(`Sessions directory not found: ${sessionsRoot}\nIs Claude Desktop installed and has Cowork been used at least once?`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (const acct of fs.readdirSync(sessionsRoot, { withFileTypes: true })) {
|
|
150
|
+
if (!acct.isDirectory() || !UUID_RE.test(acct.name)) continue;
|
|
151
|
+
const acctPath = path.join(sessionsRoot, acct.name);
|
|
152
|
+
|
|
153
|
+
for (const org of fs.readdirSync(acctPath, { withFileTypes: true })) {
|
|
154
|
+
if (!org.isDirectory() || org.name.startsWith('.')) continue;
|
|
155
|
+
const orgPath = path.join(acctPath, org.name);
|
|
156
|
+
const coworkPlugins = path.join(orgPath, 'cowork_plugins');
|
|
157
|
+
const coworkSettings = path.join(orgPath, 'cowork_settings.json');
|
|
158
|
+
|
|
159
|
+
// Create cowork_plugins structure if org dir has content
|
|
160
|
+
if (!fs.existsSync(coworkPlugins)) {
|
|
161
|
+
const contents = fs.readdirSync(orgPath);
|
|
162
|
+
if (contents.length > 0) {
|
|
163
|
+
console.log(` Creating cowork_plugins in ${org.name.slice(0, 8)}...`);
|
|
164
|
+
fs.mkdirSync(path.join(coworkPlugins, 'marketplaces'), { recursive: true });
|
|
165
|
+
fs.mkdirSync(path.join(coworkPlugins, 'cache'), { recursive: true });
|
|
166
|
+
fs.mkdirSync(path.join(coworkPlugins, '.install-manifests'), { recursive: true });
|
|
167
|
+
writeJSON(path.join(coworkPlugins, 'installed_plugins.json'), { version: 2, plugins: {} });
|
|
168
|
+
writeJSON(path.join(coworkPlugins, 'known_marketplaces.json'), {});
|
|
169
|
+
} else {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
results.push({ orgName: org.name, coworkPlugins, coworkSettings });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (results.length === 0) {
|
|
179
|
+
error('No Cowork installations found.\nIs Claude Desktop installed and has Cowork been used at least once?');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// --- Installation ----------------------------------------------------------
|
|
186
|
+
function installTo(coworkPlugins, coworkSettings, extractDir, version, tagName) {
|
|
187
|
+
const installedPluginsPath = path.join(coworkPlugins, 'installed_plugins.json');
|
|
188
|
+
const installedData = readJSON(installedPluginsPath, { version: 2, plugins: {} });
|
|
189
|
+
const entries = (installedData.plugins || {})[PLUGIN_KEY] || [];
|
|
190
|
+
const oldVersion = entries.length > 0 ? entries[0].version : null;
|
|
191
|
+
|
|
192
|
+
if (oldVersion === version) {
|
|
193
|
+
console.log(` Already up to date (v${version})`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.log(` Updating: v${oldVersion || 'none'} → v${version}`);
|
|
198
|
+
const now = new Date().toISOString().replace(/\.\d{3}Z$/, '.000Z');
|
|
199
|
+
|
|
200
|
+
// Step 1: Populate cache
|
|
201
|
+
const cacheDir = path.join(coworkPlugins, 'cache', MARKETPLACE_NAME, PLUGIN_NAME, version);
|
|
202
|
+
if (fs.existsSync(cacheDir)) {
|
|
203
|
+
fs.rmSync(cacheDir, { recursive: true, force: true });
|
|
204
|
+
}
|
|
205
|
+
fs.cpSync(extractDir, cacheDir, { recursive: true });
|
|
206
|
+
|
|
207
|
+
const fileHashes = collectFileHashes(cacheDir);
|
|
208
|
+
const fileCount = Object.keys(fileHashes).length;
|
|
209
|
+
console.log(` Cache: ${fileCount} files → ${cacheDir}`);
|
|
210
|
+
|
|
211
|
+
// Step 2: Install manifest
|
|
212
|
+
const manifestDir = path.join(coworkPlugins, '.install-manifests');
|
|
213
|
+
fs.mkdirSync(manifestDir, { recursive: true });
|
|
214
|
+
const manifestPath = path.join(manifestDir, `${PLUGIN_KEY}.json`);
|
|
215
|
+
|
|
216
|
+
let createdAt = now;
|
|
217
|
+
const oldManifest = readJSON(manifestPath, null);
|
|
218
|
+
if (oldManifest) {
|
|
219
|
+
createdAt = oldManifest.createdAt || now;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
writeJSON(manifestPath, {
|
|
223
|
+
pluginId: PLUGIN_KEY,
|
|
224
|
+
createdAt,
|
|
225
|
+
files: fileHashes,
|
|
226
|
+
});
|
|
227
|
+
console.log(` Manifest: ${fileCount} file hashes`);
|
|
228
|
+
|
|
229
|
+
// Step 3: Update installed_plugins.json
|
|
230
|
+
installedData.version = installedData.version || 2;
|
|
231
|
+
installedData.plugins = installedData.plugins || {};
|
|
232
|
+
const existing = installedData.plugins[PLUGIN_KEY] || [{}];
|
|
233
|
+
const entry = existing[0] || {};
|
|
234
|
+
entry.scope = 'user';
|
|
235
|
+
entry.installPath = cacheDir;
|
|
236
|
+
entry.version = version;
|
|
237
|
+
entry.lastUpdated = now;
|
|
238
|
+
entry.gitCommitSha = tagName;
|
|
239
|
+
entry.installedAt = entry.installedAt || now;
|
|
240
|
+
installedData.plugins[PLUGIN_KEY] = [entry];
|
|
241
|
+
writeJSON(installedPluginsPath, installedData);
|
|
242
|
+
console.log(' installed_plugins.json: updated');
|
|
243
|
+
|
|
244
|
+
// Step 4: Ensure cowork_settings.json
|
|
245
|
+
const settings = readJSON(coworkSettings);
|
|
246
|
+
const enabled = settings.enabledPlugins = settings.enabledPlugins || {};
|
|
247
|
+
if (!enabled[PLUGIN_KEY]) {
|
|
248
|
+
enabled[PLUGIN_KEY] = true;
|
|
249
|
+
writeJSON(coworkSettings, settings);
|
|
250
|
+
console.log(' cowork_settings.json: enabled plugin');
|
|
251
|
+
} else {
|
|
252
|
+
console.log(' cowork_settings.json: already enabled');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Step 5: Ensure known_marketplaces.json
|
|
256
|
+
const knownPath = path.join(coworkPlugins, 'known_marketplaces.json');
|
|
257
|
+
const known = readJSON(knownPath);
|
|
258
|
+
if (!known[MARKETPLACE_NAME]) {
|
|
259
|
+
known[MARKETPLACE_NAME] = {
|
|
260
|
+
source: { source: 'github', repo: MARKETPLACE_GITHUB },
|
|
261
|
+
installLocation: path.join(coworkPlugins, 'marketplaces', MARKETPLACE_NAME),
|
|
262
|
+
lastUpdated: now,
|
|
263
|
+
};
|
|
264
|
+
writeJSON(knownPath, known);
|
|
265
|
+
console.log(' known_marketplaces.json: added marketplace');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
console.log(` Installed v${version} (${fileCount} files)`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// --- Main ------------------------------------------------------------------
|
|
272
|
+
async function main() {
|
|
273
|
+
const checkOnly = process.argv.includes('--check');
|
|
274
|
+
|
|
275
|
+
console.log('');
|
|
276
|
+
console.log(`${BOLD}${PLUGIN_NAME} installer for Cowork${NC}`);
|
|
277
|
+
console.log('Workaround for github.com/anthropics/claude-code/issues/40600');
|
|
278
|
+
console.log('');
|
|
279
|
+
|
|
280
|
+
const sessionsRoot = getSessionsRoot();
|
|
281
|
+
console.log(`Platform: ${os.platform()}`);
|
|
282
|
+
console.log(`Sessions: ${sessionsRoot}`);
|
|
283
|
+
console.log('');
|
|
284
|
+
|
|
285
|
+
// Fetch latest release
|
|
286
|
+
console.log('Fetching latest release...');
|
|
287
|
+
let release;
|
|
288
|
+
try {
|
|
289
|
+
release = await fetchJSON(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
290
|
+
} catch (err) {
|
|
291
|
+
error(`Failed to fetch release info: ${err.message}`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const version = release.tag_name.replace(/^v/, '');
|
|
295
|
+
const tagName = release.tag_name;
|
|
296
|
+
const zipAsset = (release.assets || []).find((a) => a.name.endsWith('.zip'));
|
|
297
|
+
if (!zipAsset) {
|
|
298
|
+
error('No zip asset found in the latest release.');
|
|
299
|
+
}
|
|
300
|
+
info(`Latest release: v${version} (${tagName})`);
|
|
301
|
+
|
|
302
|
+
// Discover installations
|
|
303
|
+
const installations = discoverInstallations(sessionsRoot);
|
|
304
|
+
console.log(`Found ${installations.length} Cowork installation(s)`);
|
|
305
|
+
console.log('');
|
|
306
|
+
|
|
307
|
+
// Check-only mode
|
|
308
|
+
if (checkOnly) {
|
|
309
|
+
for (const inst of installations) {
|
|
310
|
+
const ipPath = path.join(inst.coworkPlugins, 'installed_plugins.json');
|
|
311
|
+
const data = readJSON(ipPath, { version: 2, plugins: {} });
|
|
312
|
+
const entries = (data.plugins || {})[PLUGIN_KEY] || [];
|
|
313
|
+
const installed = entries.length > 0 ? entries[0].version : null;
|
|
314
|
+
const short = inst.orgName.slice(0, 8);
|
|
315
|
+
|
|
316
|
+
if (!installed) {
|
|
317
|
+
console.log(` ${short}... Not installed. Run without --check to install.`);
|
|
318
|
+
} else if (installed === version) {
|
|
319
|
+
console.log(` ${short}... Up to date (v${installed})`);
|
|
320
|
+
} else {
|
|
321
|
+
console.log(` ${short}... Update available: v${installed} → v${version}`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
console.log('');
|
|
325
|
+
console.log('Done!');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Download zip
|
|
330
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'marketing-skills-'));
|
|
331
|
+
const cleanup = () => { try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch {} };
|
|
332
|
+
process.on('exit', cleanup);
|
|
333
|
+
process.on('SIGINT', () => { cleanup(); process.exit(1); });
|
|
334
|
+
|
|
335
|
+
const zipFile = path.join(tmpDir, 'plugin.zip');
|
|
336
|
+
console.log(`Downloading v${version}...`);
|
|
337
|
+
try {
|
|
338
|
+
const bytes = await downloadFile(zipAsset.browser_download_url, zipFile);
|
|
339
|
+
info(`Downloaded ${(bytes / 1024).toFixed(0)} KB zip`);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
error(`Failed to download: ${err.message}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Extract
|
|
345
|
+
const extractDir = path.join(tmpDir, 'extracted');
|
|
346
|
+
try {
|
|
347
|
+
extractZip(zipFile, extractDir);
|
|
348
|
+
info('Extracted plugin files');
|
|
349
|
+
} catch (err) {
|
|
350
|
+
error(`Failed to extract zip: ${err.message}`);
|
|
351
|
+
}
|
|
352
|
+
console.log('');
|
|
353
|
+
|
|
354
|
+
// Install to each location
|
|
355
|
+
let count = 0;
|
|
356
|
+
for (const inst of installations) {
|
|
357
|
+
console.log(`--- ${inst.orgName.slice(0, 8)}... ---`);
|
|
358
|
+
installTo(inst.coworkPlugins, inst.coworkSettings, extractDir, version, tagName);
|
|
359
|
+
count++;
|
|
360
|
+
console.log('');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
console.log(`Done! Installed to ${count} location(s).`);
|
|
364
|
+
console.log('Restart Claude Desktop for changes to take effect.');
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
main().catch((err) => {
|
|
368
|
+
error(err.message);
|
|
369
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mattstratton/install-marketing-skills",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "One-line installer for tigerdata-marketing-skills Cowork plugin. Workaround for github.com/anthropics/claude-code/issues/40600",
|
|
5
|
+
"bin": {
|
|
6
|
+
"install-marketing-skills": "./bin/install.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"claude",
|
|
13
|
+
"cowork",
|
|
14
|
+
"plugin",
|
|
15
|
+
"tigerdata",
|
|
16
|
+
"marketing"
|
|
17
|
+
],
|
|
18
|
+
"author": "Matt Stratton",
|
|
19
|
+
"license": "Apache-2.0",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/timescale/marketing-skills.git",
|
|
23
|
+
"directory": "packages/installer"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
}
|
|
28
|
+
}
|