@mandors/cli 0.0.16 → 0.0.18

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 CHANGED
@@ -69,48 +69,86 @@ Mandor provides:
69
69
 
70
70
  ## Installation
71
71
 
72
- Choose one of the following methods:
72
+ Mandor can be installed via curl, npm, or built from source.
73
73
 
74
- ### Option 1: curl (Recommended)
74
+ ### Option 1: curl (Recommended for macOS/Linux)
75
+
76
+ The fastest way to install Mandor on macOS or Linux:
75
77
 
76
78
  ```bash
77
- # Install latest stable version
79
+ # Install latest stable version (to ~/.local/bin)
78
80
  curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh
79
81
 
80
- # Or install to custom directory
81
- curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh -s -- --prefix ~/bin
82
+ # Install to custom directory
83
+ curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh -s -- --prefix /usr/local/bin
82
84
 
83
- # Install latest prerelease
85
+ # Install latest prerelease (beta versions)
84
86
  curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh -s -- --prerelease
85
87
 
86
88
  # Install specific version
87
- curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh -s -- --version v0.0.14
89
+ curl -fsSL https://raw.githubusercontent.com/sanxzy/mandor/main/scripts/install.sh | sh -s -- --version v0.0.16
88
90
  ```
89
91
 
90
- Default install location: `$HOME/.local/bin/mandor`
92
+ **Default install location:** `$HOME/.local/bin/mandor`
91
93
 
92
- Add to PATH if needed:
94
+ **Add to PATH:**
93
95
  ```bash
94
- export PATH="$HOME/.local/bin:$PATH"
96
+ # For bash
97
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
98
+
99
+ # For zsh
100
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
95
101
  ```
96
102
 
97
- ### Option 2: NPM
103
+ **Verify installation:**
104
+ ```bash
105
+ mandor --help
106
+ ```
107
+
108
+ ### Option 2: NPM (Cross-platform)
109
+
110
+ Install via npm for macOS, Linux, or Windows:
98
111
 
99
112
  ```bash
100
113
  # Install globally
101
114
  npm install -g @mandor/cli
102
115
 
103
- # Or use npx without installing
116
+ # Verify installation
117
+ mandor --help
118
+ ```
119
+
120
+ **Or use npx to run without installing:**
121
+ ```bash
104
122
  npx @mandor/cli init "My Project"
105
123
  ```
106
124
 
125
+ **Programmatic usage:**
126
+ ```javascript
127
+ const mandor = require('@mandor/cli');
128
+
129
+ const cli = new mandor.Mandor({ json: true, cwd: '/project/path' });
130
+ await cli.init('My Project');
131
+ await cli.projectCreate('api', { name: 'API Service' });
132
+ const tasks = await cli.taskList({ project: 'api', status: 'pending' });
133
+ ```
134
+
107
135
  ### Option 3: From Source
108
136
 
137
+ Build from Go source code:
138
+
109
139
  ```bash
140
+ # Clone repository
110
141
  git clone https://github.com/sanxzy/mandor.git
111
142
  cd mandor
143
+
144
+ # Build binary
112
145
  go build -o build/mandor ./cmd/mandor
146
+
147
+ # Install to system
113
148
  sudo mv build/mandor /usr/local/bin/
149
+
150
+ # Verify
151
+ mandor --help
114
152
  ```
115
153
 
116
154
  ### Platform Support
@@ -118,9 +156,35 @@ sudo mv build/mandor /usr/local/bin/
118
156
  | Method | macOS | Linux | Windows |
119
157
  |--------|-------|-------|---------|
120
158
  | curl | ✅ arm64, x64 | ✅ arm64, x64 | ❌ |
121
- | NPM | ✅ arm64, x64 | ✅ arm64, x64 | ✅ arm64, x64 |
159
+ | npm | ✅ arm64, x64 | ✅ arm64, x64 | ✅ arm64, x64 |
122
160
  | Source | ✅ | ✅ | ✅ |
123
161
 
162
+ ### Troubleshooting
163
+
164
+ **curl: command not found**
165
+ Install curl: `brew install curl` (macOS) or `sudo apt install curl` (Linux)
166
+
167
+ **mandor: command not found**
168
+ Ensure the install directory is in your PATH (see above)
169
+
170
+ **Permission denied**
171
+ ```bash
172
+ # Fix permissions for ~/.local/bin
173
+ chmod +x ~/.local/bin/mandor
174
+ ```
175
+
176
+ **NPM permission errors**
177
+ ```bash
178
+ # Use npx (no install)
179
+ npx @mandor/cli init "My Project"
180
+
181
+ # Or fix npm global permissions
182
+ mkdir -p ~/.npm-global
183
+ npm config set prefix '~/.npm-global'
184
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
185
+ source ~/.bashrc
186
+ ```
187
+
124
188
  ---
125
189
 
126
190
  ## Quick Start
Binary file
Binary file
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * @fileoverview Post-install hook for Mandor CLI
3
- * @description Handles binary extraction during npm install
4
- * @version 0.0.2
3
+ * @description Downloads binary from GitHub releases during npm install
4
+ * @version 0.0.4
5
5
  */
6
6
 
7
7
  const fs = require('fs');
8
8
  const path = require('path');
9
9
  const os = require('os');
10
10
  const { execSync } = require('child_process');
11
+ const https = require('https');
11
12
 
12
13
  const REPO = 'sanxzy/mandor';
13
14
  const GITHUB_API = 'https://api.github.com';
14
- const BUNDLE_DIR = path.join(__dirname, '..', 'binaries');
15
15
  const CACHE_DIR = path.join(os.homedir(), '.mandor', 'bin');
16
16
 
17
17
  function getPlatform() {
@@ -30,13 +30,39 @@ async function getLatestVersion(prerelease = false) {
30
30
  ? `${GITHUB_API}/repos/${REPO}/releases`
31
31
  : `${GITHUB_API}/repos/${REPO}/releases/latest`;
32
32
 
33
- const response = await fetch(url);
34
- if (!response.ok) {
35
- throw new Error(`Failed to fetch releases: ${response.statusText}`);
36
- }
37
- const data = await response.json();
38
- const tagName = Array.isArray(data) ? data[0].tag_name : data.tag_name;
39
- return tagName.replace(/^v/, '');
33
+ return new Promise((resolve, reject) => {
34
+ https.get(url, { headers: { 'User-Agent': 'Mandor-CLI' } }, (res) => {
35
+ let data = '';
36
+ res.on('data', chunk => data += chunk);
37
+ res.on('end', () => {
38
+ try {
39
+ const parsed = JSON.parse(data);
40
+ const tagName = Array.isArray(parsed) ? parsed[0].tag_name : parsed.tag_name;
41
+ resolve(tagName.replace(/^v/, ''));
42
+ } catch (e) {
43
+ reject(e);
44
+ }
45
+ });
46
+ }).on('error', reject);
47
+ });
48
+ }
49
+
50
+ function downloadFile(url, dest) {
51
+ return new Promise((resolve, reject) => {
52
+ const file = fs.createWriteStream(dest);
53
+ https.get(url, (res) => {
54
+ if (res.statusCode === 302 || res.statusCode === 301) {
55
+ return downloadFile(res.headers.location, dest).then(resolve).catch(reject);
56
+ }
57
+ res.pipe(file);
58
+ file.on('finish', () => {
59
+ file.close(resolve);
60
+ });
61
+ }).on('error', (err) => {
62
+ fs.unlink(dest, () => {});
63
+ reject(err);
64
+ });
65
+ });
40
66
  }
41
67
 
42
68
  async function install(options = {}) {
@@ -60,45 +86,19 @@ async function install(options = {}) {
60
86
  console.log('');
61
87
 
62
88
  const cachePath = path.join(CACHE_DIR, installVersion, osArch);
63
- const binaryPath = path.join(cachePath, 'mandor');
64
-
65
- if (platform === 'win32') {
66
- binaryPath = binaryPath + '.exe';
67
- }
89
+ const binaryPath = path.join(cachePath, platform === 'win32' ? 'mandor.exe' : 'mandor');
68
90
 
69
91
  if (fs.existsSync(binaryPath)) {
70
92
  console.log(`Using cached binary: ${binaryPath}`);
71
93
  return binaryPath;
72
94
  }
73
95
 
74
- const bundledPath = path.join(BUNDLE_DIR, assetName);
75
- if (fs.existsSync(bundledPath)) {
76
- console.log(`Using bundled binary: ${bundledPath}`);
77
- if (!fs.existsSync(cachePath)) {
78
- fs.mkdirSync(cachePath, { recursive: true });
79
- }
80
- execSync(`tar -xzf "${bundledPath}" -C "${cachePath}"`, { stdio: 'inherit' });
81
- fs.chmodSync(binaryPath, '755');
82
- console.log(`Installed: ${binaryPath}`);
83
- return binaryPath;
84
- }
85
-
86
96
  console.log('Downloading from GitHub releases...');
87
97
  const downloadUrl = `https://github.com/${REPO}/releases/download/v${installVersion}/${assetName}`;
88
98
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mandor-install-'));
89
99
  const tarball = path.join(tempDir, assetName);
90
100
 
91
- const response = await fetch(downloadUrl);
92
- if (!response.ok) {
93
- throw new Error(`Download failed: ${response.statusText} (${downloadUrl})`);
94
- }
95
-
96
- const file = fs.createWriteStream(tarball);
97
- await new Promise((resolve, reject) => {
98
- response.body.pipe(file);
99
- file.on('finish', resolve);
100
- file.on('error', reject);
101
- });
101
+ await downloadFile(downloadUrl, tarball);
102
102
 
103
103
  if (!fs.existsSync(cachePath)) {
104
104
  fs.mkdirSync(cachePath, { recursive: true });
@@ -114,7 +114,8 @@ async function install(options = {}) {
114
114
  }
115
115
 
116
116
  if (require.main === module || process.env.npm_lifecycle_event === 'postinstall') {
117
- install().catch(error => {
117
+ const prerelease = process.argv.includes('--prerelease') || process.argv.includes('-p');
118
+ install({ prerelease }).catch(error => {
118
119
  console.error('Failed to install Mandor:', error.message);
119
120
  process.exit(1);
120
121
  });
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview Cross-platform build script for Mandor binaries
3
3
  * @description Compiles Go binaries for all supported platforms and creates distribution archives
4
- * @version 0.0.1
4
+ * @version 0.0.2
5
5
  */
6
6
 
7
7
  const { execSync } = require('child_process');
@@ -9,13 +9,11 @@ const fs = require('fs');
9
9
  const path = require('path');
10
10
  const os = require('os');
11
11
 
12
- /**
13
- * @typedef {Object} PlatformConfig
14
- * @property {string} os - Operating system (darwin, linux, win32)
15
- * @property {string} arch - Architecture (x64, arm64)
16
- */
12
+ const ROOT_DIR = path.join(__dirname, '..', '..');
13
+ const BINARIES_DIR = path.join(ROOT_DIR, 'binaries');
14
+ const NPM_DIR = path.join(ROOT_DIR, 'npm');
15
+ const NPM_BINARIES_DIR = path.join(NPM_DIR, 'binaries');
17
16
 
18
- /** @type {PlatformConfig[]} All supported platform configurations */
19
17
  const PLATFORMS = [
20
18
  { os: 'darwin', arch: 'x64' },
21
19
  { os: 'darwin', arch: 'arm64' },
@@ -25,118 +23,105 @@ const PLATFORMS = [
25
23
  { os: 'win32', arch: 'arm64' }
26
24
  ];
27
25
 
28
- /**
29
- * Builds the Mandor binary for a specific platform
30
- * @param {PlatformConfig} platform - Platform configuration
31
- * @param {string} sourceDir - Source directory containing Go code
32
- * @returns {string|null} Path to the compiled binary, or null if unsupported
33
- * @example
34
- * const binaryPath = buildForPlatform({ os: 'darwin', arch: 'arm64' }, './cmd/mandor');
35
- */
36
- function buildForPlatform(platform, sourceDir) {
26
+ function buildForPlatform(platform) {
37
27
  const { os, arch } = platform;
38
- const outputDir = path.join(__dirname, '..', 'binaries', `${os}-${arch}`);
39
- const outputPath = path.join(outputDir, os === 'win32' ? 'mandor.exe' : 'mandor');
28
+ const outputDir = path.join(BINARIES_DIR, `${os}-${arch}`);
29
+ const binaryName = os === 'win32' ? 'mandor.exe' : 'mandor';
30
+ const outputPath = path.join(outputDir, binaryName);
40
31
 
41
32
  fs.mkdirSync(outputDir, { recursive: true });
42
33
 
43
34
  console.log(`Building for ${os}-${arch}...`);
44
35
 
45
36
  try {
46
- execSync(`GOOS=${os} GOARCH=${arch} go build -o "${outputPath}" ${sourceDir}`, {
37
+ execSync(`GOOS=${os} GOARCH=${arch} go build -o "${outputPath}" ./cmd/mandor`, {
47
38
  stdio: 'pipe',
48
39
  shell: process.platform === 'win32'
49
40
  });
50
41
  return outputPath;
51
42
  } catch (error) {
52
- // Check stderr for unsupported pair message
53
43
  const stderr = error.stderr ? error.stderr.toString() : '';
54
44
  if (stderr.includes('unsupported GOOS/GOARCH pair')) {
55
- console.log(` Not supported on this system`);
45
+ console.log(` Not supported on this system`);
56
46
  return null;
57
47
  }
58
- console.error(` Build failed:`, error.message);
48
+ console.error(` Build failed:`, error.message);
59
49
  throw error;
60
50
  }
61
51
  }
62
52
 
63
- /**
64
- * Creates a distribution archive for a platform
65
- * @param {PlatformConfig} platform - Platform configuration
66
- * @returns {string|null} Path to the archive file, or null if binary doesn't exist
67
- * @example
68
- * const archivePath = createArchive({ os: 'linux', arch: 'x64' });
69
- */
70
53
  function createArchive(platform) {
71
54
  const { os, arch } = platform;
72
- const sourceDir = path.join(__dirname, '..', 'binaries', `${os}-${arch}`);
55
+ const sourceDir = path.join(BINARIES_DIR, `${os}-${arch}`);
56
+ const binaryName = os === 'win32' ? 'mandor.exe' : 'mandor';
73
57
 
74
- // Check if binary exists
75
- const binaryExists = fs.existsSync(path.join(sourceDir, os === 'win32' ? 'mandor.exe' : 'mandor'));
76
- if (!binaryExists) {
58
+ if (!fs.existsSync(path.join(sourceDir, binaryName))) {
77
59
  return null;
78
60
  }
79
61
 
80
- const archivePath = path.join(__dirname, '..', 'binaries', `${os}-${arch}.tar.gz`);
62
+ const archivePath = path.join(BINARIES_DIR, `${os}-${arch}.tar.gz`);
63
+
64
+ try {
65
+ execSync(`tar -czf "${archivePath}" -C "${sourceDir}" .`, {
66
+ stdio: 'pipe',
67
+ shell: true
68
+ });
69
+ return archivePath;
70
+ } catch (error) {
71
+ console.error(` Failed to create archive:`, error.message);
72
+ return null;
73
+ }
74
+ }
81
75
 
82
- console.log(`Creating archive for ${os}-${arch}...`);
76
+ function copyToNpm() {
77
+ fs.mkdirSync(NPM_BINARIES_DIR, { recursive: true });
83
78
 
84
- execSync(`tar -czf "${archivePath}" -C "${sourceDir}" .`, {
85
- stdio: 'inherit',
86
- shell: true
87
- });
79
+ for (const platform of PLATFORMS) {
80
+ const { os, arch } = platform;
81
+ const archivePath = path.join(BINARIES_DIR, `${os}-${arch}.tar.gz`);
82
+ const destPath = path.join(NPM_BINARIES_DIR, `${os}-${arch}.tar.gz`);
88
83
 
89
- return archivePath;
84
+ if (fs.existsSync(archivePath)) {
85
+ fs.cpSync(archivePath, destPath);
86
+ console.log(`Copied ${os}-${arch}.tar.gz to npm/`);
87
+ }
88
+ }
90
89
  }
91
90
 
92
- /**
93
- * Main build function - attempts to build all platforms
94
- * @returns {Object[]} Build results for each successfully built platform
95
- * @example
96
- * const results = mainBuild();
97
- * console.log(`Built ${results.length} platforms`);
98
- */
99
- function mainBuild() {
100
- const sourceDir = path.join(__dirname, '..', '..', 'cmd', 'mandor');
101
- const results = [];
102
- const unsupported = [];
91
+ function cleanBuildDirs() {
92
+ if (fs.existsSync(BINARIES_DIR)) {
93
+ for (const entry of fs.readdirSync(BINARIES_DIR)) {
94
+ if (entry.endsWith('.tar.gz')) {
95
+ fs.unlinkSync(path.join(BINARIES_DIR, entry));
96
+ }
97
+ }
98
+ }
99
+ }
103
100
 
101
+ function mainBuild() {
104
102
  console.log(`Running on: ${os.platform()}/${os.arch()}`);
105
103
  console.log('Building cross-platform binaries...\n');
106
104
 
107
- // Build all platforms
105
+ cleanBuildDirs();
106
+ fs.mkdirSync(NPM_BINARIES_DIR, { recursive: true });
107
+
108
+ const results = [];
109
+ const unsupported = [];
110
+
108
111
  for (const platform of PLATFORMS) {
109
- const binaryPath = buildForPlatform(platform, sourceDir);
112
+ const binaryPath = buildForPlatform(platform);
110
113
  if (binaryPath) {
111
- results.push({
112
- platform: platform.os,
113
- arch: platform.arch,
114
- binaryPath,
115
- status: 'built'
116
- });
117
- console.log(` ✓ Built successfully\n`);
114
+ results.push({ platform: platform.os, arch: platform.arch, binaryPath, status: 'built' });
115
+ console.log(` Built successfully\n`);
118
116
  } else {
119
- unsupported.push({
120
- platform: platform.os,
121
- arch: platform.arch,
122
- status: 'unsupported'
123
- });
117
+ unsupported.push({ platform: platform.os, arch: platform.arch, status: 'unsupported' });
124
118
  }
125
119
  }
126
120
 
127
- // Create archives for successfully built platforms
128
- const archiveResults = [];
129
121
  for (const platform of PLATFORMS) {
130
122
  const archivePath = createArchive(platform);
131
123
  if (archivePath) {
132
124
  const stats = fs.statSync(archivePath);
133
- archiveResults.push({
134
- platform: platform.os,
135
- arch: platform.arch,
136
- archivePath,
137
- archiveSize: stats.size
138
- });
139
-
140
125
  const existing = results.find(r => r.platform === platform.os && r.arch === platform.arch);
141
126
  if (existing) {
142
127
  existing.archivePath = archivePath;
@@ -145,10 +130,12 @@ function mainBuild() {
145
130
  }
146
131
  }
147
132
 
148
- // Summary
133
+ console.log('Copying archives to npm/binaries/ for npm package...');
134
+ copyToNpm();
135
+
149
136
  console.log('─'.repeat(50));
150
137
  console.log(`Build complete!`);
151
- console.log(` Built: ${archiveResults.length} platforms`);
138
+ console.log(` Built: ${results.length} platforms`);
152
139
  console.log(` Unsupported: ${unsupported.length} platforms`);
153
140
 
154
141
  if (unsupported.length > 0) {
@@ -158,10 +145,12 @@ function mainBuild() {
158
145
  });
159
146
  }
160
147
 
161
- return archiveResults;
148
+ console.log(`\nArchives location: ${BINARIES_DIR}/`);
149
+ console.log(`NPM package binaries: ${NPM_BINARIES_DIR}/`);
150
+
151
+ return results;
162
152
  }
163
153
 
164
- // Run if executed directly
165
154
  if (require.main === module) {
166
155
  const results = mainBuild();
167
156
  if (results.length > 0) {
@@ -170,14 +159,7 @@ if (require.main === module) {
170
159
  Platform: `${r.platform}/${r.arch}`,
171
160
  'Archive Size': `${(r.archiveSize / 1024).toFixed(1)} KB`
172
161
  })));
173
-
174
- console.log('Archives location: npm/binaries/');
175
162
  }
176
163
  }
177
164
 
178
- module.exports = {
179
- PLATFORMS,
180
- buildForPlatform,
181
- createArchive,
182
- mainBuild
183
- };
165
+ module.exports = { PLATFORMS, buildForPlatform, createArchive, mainBuild, copyToNpm };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandors/cli",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Event-based task manager CLI for AI agent workflows",
5
5
  "main": "npm/lib/index.js",
6
6
  "bin": {
@@ -19,9 +19,7 @@
19
19
  "node": ">=16.0.0"
20
20
  },
21
21
  "scripts": {
22
- "postinstall": "node npm/lib/install.js",
23
- "prepublishOnly": "npm run build",
24
- "preversion": "npm run build",
22
+ "postinstall": "node npm/lib/install.js --prerelease",
25
23
  "build": "node npm/scripts/build.js",
26
24
  "build:darwin:x64": "GOOS=darwin GOARCH=x64 go build -o binaries/darwin-x64/mandor ./cmd/mandor",
27
25
  "build:darwin:arm64": "GOOS=darwin GOARCH=arm64 go build -o binaries/darwin-arm64/mandor ./cmd/mandor",
Binary file
Binary file