agentxchain 0.8.0 → 0.8.2
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 +54 -21
- package/package.json +1 -1
- package/src/adapters/cursor-local.js +53 -22
- package/src/commands/init.js +3 -9
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# agentxchain
|
|
2
2
|
|
|
3
|
-
CLI for multi-agent coordination in your IDE. Define a team of AI agents, let them take turns building your project
|
|
3
|
+
CLI for multi-agent coordination in your IDE. Define a team of AI agents, let them take turns building your project — each in its own IDE window.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -17,59 +17,92 @@ npx agentxchain init
|
|
|
17
17
|
## Quick start
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
# 1. Create a project (interactive template selection)
|
|
21
|
+
agentxchain init
|
|
22
|
+
|
|
23
|
+
# 2. Launch agents — opens a separate Cursor window per agent
|
|
24
|
+
cd my-project/
|
|
25
|
+
agentxchain start
|
|
26
|
+
|
|
27
|
+
# 3. For each window: paste the prompt (auto-copied to clipboard), select Agent mode, send
|
|
28
|
+
# The CLI walks you through one agent at a time.
|
|
29
|
+
|
|
30
|
+
# 4. Release the human lock — agents start claiming turns
|
|
31
|
+
agentxchain release
|
|
24
32
|
```
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
Each agent runs in its own Cursor window with a self-polling loop. Agents check `lock.json` every 60 seconds, claim when it's their turn, do their work, release, and go back to waiting. No external referee needed.
|
|
27
35
|
|
|
28
36
|
## Commands
|
|
29
37
|
|
|
30
38
|
| Command | What it does |
|
|
31
39
|
|---------|-------------|
|
|
32
|
-
| `init` | Create project folder with agents,
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `status` | Show lock, phase, agents |
|
|
36
|
-
| `claim` | Human takes control |
|
|
40
|
+
| `init` | Create project folder with agents, protocol files, and templates |
|
|
41
|
+
| `start` | Open a Cursor window per agent + copy prompts to clipboard |
|
|
42
|
+
| `generate` | Regenerate agent files from `agentxchain.json` |
|
|
43
|
+
| `status` | Show lock holder, phase, turn number, agents |
|
|
44
|
+
| `claim` | Human takes control (agents stop claiming) |
|
|
37
45
|
| `release` | Hand lock back to agents |
|
|
38
46
|
| `stop` | Terminate running Claude Code agent sessions |
|
|
39
|
-
| `watch` |
|
|
47
|
+
| `watch` | Optional: TTL safety net + status logging |
|
|
40
48
|
| `config` | View/edit config, add/remove agents, change rules |
|
|
41
49
|
| `update` | Self-update CLI from npm |
|
|
42
50
|
|
|
51
|
+
### IDE options
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
agentxchain start # Cursor (default) — one window per agent
|
|
55
|
+
agentxchain start --ide vscode # VS Code — uses .agent.md custom agents + hooks
|
|
56
|
+
agentxchain start --ide claude-code # Claude Code — spawns CLI processes
|
|
57
|
+
```
|
|
58
|
+
|
|
43
59
|
### Additional flags
|
|
44
60
|
|
|
45
61
|
```bash
|
|
62
|
+
agentxchain start --agent pm # launch only one specific agent
|
|
63
|
+
agentxchain start --dry-run # preview agents without launching
|
|
46
64
|
agentxchain watch --daemon # run watch in background
|
|
47
65
|
agentxchain release --force # force-release non-human holder lock
|
|
48
66
|
```
|
|
49
67
|
|
|
50
68
|
## How it works
|
|
51
69
|
|
|
52
|
-
|
|
70
|
+
### Cursor mode (default)
|
|
71
|
+
|
|
72
|
+
1. `agentxchain start` opens a **separate Cursor window** for each agent
|
|
73
|
+
2. Each window gets a unique prompt copied to clipboard
|
|
74
|
+
3. Agent prompts include a self-polling loop: read `lock.json` → check if it's my turn → claim → work → release → sleep 60s → repeat
|
|
75
|
+
4. Agents know their rotation order from `agentxchain.json` and only claim when the previous agent released
|
|
76
|
+
5. Human can `claim` to pause and `release` to resume anytime
|
|
77
|
+
|
|
78
|
+
### VS Code mode
|
|
79
|
+
|
|
80
|
+
1. `agentxchain init` generates `.github/agents/*.agent.md` (VS Code custom agents) and `.github/hooks/` (lifecycle hooks)
|
|
81
|
+
2. VS Code auto-discovers agents in the Chat dropdown
|
|
82
|
+
3. The `Stop` hook acts as referee — hands off to next agent automatically
|
|
53
83
|
|
|
54
|
-
|
|
55
|
-
- `.github/hooks/agentxchain.json` — lifecycle hooks (Stop = referee, SessionStart = context injection)
|
|
56
|
-
- `scripts/agentxchain-*.sh` — hook shell scripts
|
|
84
|
+
### Turn rotation
|
|
57
85
|
|
|
58
|
-
|
|
86
|
+
Agents follow a round-robin order defined in `agentxchain.json`:
|
|
87
|
+
- PM waits for: lock free + last released by `human`, `null`, or last agent in rotation
|
|
88
|
+
- Dev waits for: lock free + last released by `pm`
|
|
89
|
+
- QA waits for: lock free + last released by `dev`
|
|
90
|
+
- And so on...
|
|
59
91
|
|
|
60
92
|
## Key features
|
|
61
93
|
|
|
62
|
-
- **
|
|
63
|
-
- **
|
|
64
|
-
- **
|
|
94
|
+
- **One window per agent** — each agent has its own Cursor window and chat session
|
|
95
|
+
- **Self-polling coordination** — agents check `lock.json` every 60s, no external process needed
|
|
96
|
+
- **Works in Cursor, VS Code, Claude Code** — adapters for each IDE
|
|
65
97
|
- **User-defined teams** — any number of agents, any roles
|
|
66
98
|
- **No API keys or cloud required** — everything runs locally
|
|
67
99
|
- **Human-in-the-loop** — claim/release to intervene anytime
|
|
68
100
|
- **Team templates** — SaaS MVP, Landing Page, Bug Squad, API Builder, Refactor Team
|
|
101
|
+
- **Lock TTL** — `watch` can force-release stale locks as a safety net
|
|
69
102
|
|
|
70
103
|
## VS Code extension (optional)
|
|
71
104
|
|
|
72
|
-
For a richer UI
|
|
105
|
+
For a richer UI in VS Code:
|
|
73
106
|
|
|
74
107
|
```bash
|
|
75
108
|
code --install-extension cli/vscode-extension/agentxchain-0.1.0.vsix
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
|
-
import { writeFileSync } from 'fs';
|
|
2
|
+
import { writeFileSync, mkdirSync, existsSync, symlinkSync, lstatSync, unlinkSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
@@ -10,50 +10,83 @@ export async function launchCursorLocal(config, root, opts) {
|
|
|
10
10
|
const agentEntries = Object.entries(agents);
|
|
11
11
|
const total = agentEntries.length;
|
|
12
12
|
|
|
13
|
-
console.log(chalk.bold(`
|
|
13
|
+
console.log(chalk.bold(` Setting up ${total} agents: ${Object.keys(agents).join(', ')}`));
|
|
14
14
|
console.log('');
|
|
15
15
|
|
|
16
16
|
const promptDir = join(root, '.agentxchain-prompts');
|
|
17
|
-
|
|
17
|
+
mkdirSync(promptDir, { recursive: true });
|
|
18
|
+
|
|
19
|
+
// Save all prompts first
|
|
20
|
+
for (const [id, agent] of agentEntries) {
|
|
21
|
+
const prompt = generatePollingPrompt(id, agent, config);
|
|
22
|
+
writeFileSync(join(promptDir, `${id}.prompt.md`), prompt);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Create per-agent symlinked workspace folders so Cursor opens separate windows
|
|
26
|
+
const workspacesDir = join(root, '.agentxchain-workspaces');
|
|
27
|
+
mkdirSync(workspacesDir, { recursive: true });
|
|
18
28
|
|
|
19
29
|
for (let i = 0; i < agentEntries.length; i++) {
|
|
20
30
|
const [id, agent] = agentEntries[i];
|
|
21
31
|
const prompt = generatePollingPrompt(id, agent, config);
|
|
22
|
-
const promptFile = join(promptDir, `${id}.prompt.md`);
|
|
23
|
-
writeFileSync(promptFile, prompt);
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
// Create symlink: .agentxchain-workspaces/<id> -> project root
|
|
34
|
+
const agentWorkspace = join(workspacesDir, id);
|
|
35
|
+
try {
|
|
36
|
+
if (existsSync(agentWorkspace)) {
|
|
37
|
+
const stat = lstatSync(agentWorkspace);
|
|
38
|
+
if (stat.isSymbolicLink()) unlinkSync(agentWorkspace);
|
|
39
|
+
}
|
|
40
|
+
if (!existsSync(agentWorkspace)) {
|
|
41
|
+
symlinkSync(root, agentWorkspace, 'dir');
|
|
42
|
+
}
|
|
43
|
+
} catch {}
|
|
44
|
+
|
|
45
|
+
console.log(chalk.cyan(` ─── Agent ${i + 1}/${total}: ${chalk.bold(id)} — ${agent.name} ───`));
|
|
46
|
+
console.log('');
|
|
26
47
|
|
|
27
48
|
copyToClipboard(prompt);
|
|
28
|
-
console.log(chalk.green(`
|
|
29
|
-
console.log(chalk.dim(`
|
|
49
|
+
console.log(chalk.green(` ✓ Prompt copied to clipboard.`));
|
|
50
|
+
console.log(chalk.dim(` Saved to: .agentxchain-prompts/${id}.prompt.md`));
|
|
51
|
+
|
|
52
|
+
// Open a separate Cursor window using the symlinked path
|
|
53
|
+
openCursorWindow(agentWorkspace);
|
|
54
|
+
console.log(chalk.dim(` Cursor window opened for ${id}.`));
|
|
30
55
|
|
|
31
|
-
|
|
56
|
+
console.log('');
|
|
57
|
+
console.log(` ${chalk.bold('In the new Cursor window:')}`);
|
|
58
|
+
console.log(` 1. Open chat (${chalk.bold('Cmd+L')})`);
|
|
59
|
+
console.log(` 2. Paste the prompt (${chalk.bold('Cmd+V')})`);
|
|
60
|
+
console.log(` 3. ${chalk.bold('Select Agent mode')} (not Ask/Edit)`);
|
|
61
|
+
console.log(` 4. Send it (${chalk.bold('Enter')})`);
|
|
32
62
|
|
|
33
63
|
if (i < agentEntries.length - 1) {
|
|
34
64
|
console.log('');
|
|
35
65
|
await inquirer.prompt([{
|
|
36
66
|
type: 'input',
|
|
37
67
|
name: 'ready',
|
|
38
|
-
message:
|
|
68
|
+
message: ` Done? Press Enter to open next window (${agentEntries[i + 1][0]})...`
|
|
39
69
|
}]);
|
|
70
|
+
console.log('');
|
|
40
71
|
} else {
|
|
41
72
|
console.log('');
|
|
42
|
-
console.log(chalk.dim(`
|
|
73
|
+
console.log(chalk.dim(` Last agent. Paste and send, then come back here.`));
|
|
74
|
+
console.log('');
|
|
43
75
|
}
|
|
44
76
|
}
|
|
45
77
|
|
|
78
|
+
console.log(chalk.green(` ✓ All ${total} agents launched in separate Cursor windows.`));
|
|
46
79
|
console.log('');
|
|
47
|
-
console.log(chalk.
|
|
48
|
-
console.log('');
|
|
49
|
-
console.log(` ${chalk.cyan('Next:')}`);
|
|
80
|
+
console.log(` ${chalk.cyan('Now run:')}`);
|
|
50
81
|
console.log(` ${chalk.bold('agentxchain release')} ${chalk.dim('# release human lock — agents start claiming turns')}`);
|
|
51
|
-
console.log(
|
|
82
|
+
console.log('');
|
|
83
|
+
console.log(` ${chalk.dim('Other commands:')}`);
|
|
52
84
|
console.log(` ${chalk.bold('agentxchain status')} ${chalk.dim('# check who holds the lock')}`);
|
|
53
85
|
console.log(` ${chalk.bold('agentxchain claim')} ${chalk.dim('# pause agents and take control')}`);
|
|
86
|
+
console.log(` ${chalk.bold('agentxchain watch')} ${chalk.dim('# optional: TTL safety net')}`);
|
|
54
87
|
console.log('');
|
|
55
88
|
console.log(chalk.dim(' Agents self-coordinate via lock.json polling (sleep 60s between checks).'));
|
|
56
|
-
console.log(chalk.dim('
|
|
89
|
+
console.log(chalk.dim(' Re-paste a prompt: cat .agentxchain-prompts/<agent>.prompt.md | pbcopy'));
|
|
57
90
|
console.log('');
|
|
58
91
|
}
|
|
59
92
|
|
|
@@ -82,14 +115,12 @@ function copyToClipboard(text) {
|
|
|
82
115
|
return false;
|
|
83
116
|
}
|
|
84
117
|
|
|
85
|
-
function
|
|
118
|
+
function openCursorWindow(folderPath) {
|
|
86
119
|
try {
|
|
87
120
|
if (process.platform === 'darwin') {
|
|
88
|
-
execSync(`open -na "Cursor" --args "${
|
|
121
|
+
execSync(`open -na "Cursor" --args "${folderPath}"`, { stdio: 'ignore' });
|
|
89
122
|
return;
|
|
90
123
|
}
|
|
91
|
-
execSync(`cursor "${
|
|
92
|
-
} catch {
|
|
93
|
-
// Cursor not found or can't open — user will open manually
|
|
94
|
-
}
|
|
124
|
+
execSync(`cursor --new-window "${folderPath}"`, { stdio: 'ignore' });
|
|
125
|
+
} catch {}
|
|
95
126
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -207,7 +207,7 @@ export async function initCommand(opts) {
|
|
|
207
207
|
writeFileSync(join(dir, 'log.md'), `# ${project} — Agent Log\n\n## COMPRESSED CONTEXT\n\n(No compressed context yet.)\n\n## MESSAGE LOG\n\n(Agents append messages below this line.)\n`);
|
|
208
208
|
writeFileSync(join(dir, 'HUMAN_TASKS.md'), '# Human Tasks\n\n(Agents append tasks here when they need human action.)\n');
|
|
209
209
|
const gitignorePath = join(dir, '.gitignore');
|
|
210
|
-
const requiredIgnores = ['.env', '.agentxchain-trigger.json', '.agentxchain-prompts/'];
|
|
210
|
+
const requiredIgnores = ['.env', '.agentxchain-trigger.json', '.agentxchain-prompts/', '.agentxchain-workspaces/'];
|
|
211
211
|
if (!existsSync(gitignorePath)) {
|
|
212
212
|
writeFileSync(gitignorePath, requiredIgnores.join('\n') + '\n');
|
|
213
213
|
} else {
|
|
@@ -264,13 +264,7 @@ export async function initCommand(opts) {
|
|
|
264
264
|
console.log('');
|
|
265
265
|
console.log(` ${chalk.cyan('Next:')}`);
|
|
266
266
|
console.log(` ${chalk.bold(`cd ${folderName}`)}`);
|
|
267
|
-
console.log(` ${chalk.bold('
|
|
268
|
-
console.log(` ${chalk.bold('
|
|
269
|
-
console.log(` ${chalk.dim('(If "command not found": open IDE → Cmd+Shift+P → "Shell Command: Install")')}`);
|
|
270
|
-
console.log('');
|
|
271
|
-
console.log(` ${chalk.dim('In your IDE:')}`);
|
|
272
|
-
console.log(` ${chalk.dim(' 1. Open Chat (Cmd+L)')}`);
|
|
273
|
-
console.log(` ${chalk.dim(' 2. Select an agent from the dropdown (auto-discovered from .github/agents/)')}`);
|
|
274
|
-
console.log(` ${chalk.bold('agentxchain release')} ${chalk.dim('# release human lock to begin turns')}`);
|
|
267
|
+
console.log(` ${chalk.bold('agentxchain start')} ${chalk.dim('# opens Cursor windows + copies agent prompts')}`);
|
|
268
|
+
console.log(` ${chalk.bold('agentxchain release')} ${chalk.dim('# release human lock — agents start working')}`);
|
|
275
269
|
console.log('');
|
|
276
270
|
}
|