@kendoo.agentdesk/agentdesk 0.3.0 → 0.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # AgentDesk
2
2
 
3
- AI team orchestrator for [Claude Code](https://claude.ai/claude-code). Run collaborative agent sessions from your terminal and watch them live on [agentdesk.live](https://agentdesk.live).
3
+ AI team orchestrator. Run collaborative agent sessions from your terminal and watch them live on [agentdesk.live](https://agentdesk.live).
4
4
 
5
5
  AgentDesk spawns a team of 7 specialized AI agents that collaborate on your tasks:
6
6
 
@@ -22,36 +22,44 @@ AgentDesk spawns a team of 7 specialized AI agents that collaborate on your task
22
22
  npm i -g @kendoo.agentdesk/agentdesk
23
23
  ```
24
24
 
25
- Requires [Node.js](https://nodejs.org/) 18+ and [Claude Code](https://claude.ai/claude-code) installed.
25
+ Requires [Node.js](https://nodejs.org/) 18+.
26
26
 
27
- ### 2. Log in
27
+ ### 2. Sign in
28
28
 
29
29
  ```bash
30
30
  agentdesk login
31
31
  ```
32
32
 
33
- This opens your browser to [agentdesk.live](https://agentdesk.live) where you sign up or log in. Your API key is saved automatically to `~/.agentdesk/credentials.json`.
33
+ Opens your browser to [agentdesk.live](https://agentdesk.live) where you sign up or log in (email/password or Google). Your API key is saved automatically.
34
34
 
35
35
  ### 3. Set up your project
36
36
 
37
- Navigate to your project and run init:
38
-
39
37
  ```bash
40
38
  agentdesk init
41
39
  ```
42
40
 
41
+ This detects your project, asks which task tracker you use (Linear, Jira, GitHub Issues, or none), and saves the config to `.agentdesk.json`.
42
+
43
43
  ### 4. Run a team session
44
44
 
45
+ Work on an existing task:
46
+
45
47
  ```bash
46
48
  agentdesk team KEN-517
47
- agentdesk team BUG-42 -d "Fix the checkout total calculation"
49
+ ```
50
+
51
+ Or just describe what you want — a task is created automatically:
52
+
53
+ ```bash
54
+ agentdesk team -d "Fix the checkout total calculation"
55
+ agentdesk team -d "Add Google OAuth to the login page"
48
56
  ```
49
57
 
50
58
  Open [agentdesk.live](https://agentdesk.live) to watch the session live.
51
59
 
52
60
  ## Configuration
53
61
 
54
- Create `.agentdesk.json` in your project root to customize behavior:
62
+ `agentdesk init` creates `.agentdesk.json` in your project root. You can also edit it manually:
55
63
 
56
64
  ```json
57
65
  {
@@ -65,8 +73,9 @@ Create `.agentdesk.json` in your project root to customize behavior:
65
73
  | Tracker | Config |
66
74
  |---------|--------|
67
75
  | Linear | `{ "tracker": "linear", "linear": { "workspace": "..." } }` |
68
- | Jira | `{ "tracker": "jira", "jira": { "baseUrl": "https://yourcompany.atlassian.net" } }` |
76
+ | Jira | `{ "tracker": "jira", "jira": { "baseUrl": "https://company.atlassian.net" } }` |
69
77
  | GitHub Issues | `{ "tracker": "github", "github": { "repo": "owner/repo" } }` |
78
+ | None | No config needed — pass `-d "description"` when running a session |
70
79
 
71
80
  ### Declaring project agents
72
81
 
@@ -87,33 +96,31 @@ If your project has existing AI agents, bots, or automation, declare them so the
87
96
 
88
97
  AgentDesk also auto-discovers agents from `.claude/agents/`, `.claude/commands/`, `.mcp.json`, GitHub Actions workflows, Dependabot, and Renovate configs.
89
98
 
90
- ## Usage
99
+ ## Commands
91
100
 
92
101
  ```
93
- agentdesk login Log in to AgentDesk
94
- agentdesk logout Log out and remove credentials
95
- agentdesk init Detect project and show setup info
96
- agentdesk team <TASK-ID> Run a team session on a task
97
- agentdesk team <TASK-ID> -d "..." Run with a task description
102
+ agentdesk login Sign in to AgentDesk
103
+ agentdesk logout Sign out and remove credentials
104
+ agentdesk init Set up project and configure tracker
105
+ agentdesk team <TASK-ID> Run a team session on an existing task
106
+ agentdesk team -d "..." Describe what you want — task created automatically
98
107
  ```
99
108
 
100
109
  ### Options
101
110
 
102
111
  | Flag | Description |
103
112
  |------|-------------|
104
- | `--description`, `-d` | Task description (for projects without a task tracker) |
113
+ | `--description`, `-d` | Task description or requirements |
105
114
  | `--cwd` | Working directory (defaults to current) |
106
115
 
107
116
  ## How It Works
108
117
 
109
118
  1. You run `agentdesk team TASK-ID` in your project directory
110
119
  2. AgentDesk detects your project type, reads `CLAUDE.md`, and discovers existing agents
111
- 3. A Claude Code session starts with all 7 agents collaborating on your task
112
- 4. The team goes through structured phases: **Brainstorm** > **Planning** > **Execution** > **Review**
113
- 5. The session streams live to [agentdesk.live](https://agentdesk.live) where you can watch and send messages to the team
120
+ 3. 7 AI agents collaborate on your task in structured phases: **Brainstorm** > **Planning** > **Execution** > **Review**
121
+ 4. The session streams live to [agentdesk.live](https://agentdesk.live) where you can watch and send messages to the team
114
122
 
115
123
  ## Requirements
116
124
 
117
125
  - [Node.js](https://nodejs.org/) 18+
118
- - [Claude Code](https://claude.ai/claude-code) CLI installed and authenticated
119
126
  - An AgentDesk account at [agentdesk.live](https://agentdesk.live)
package/bin/agentdesk.mjs CHANGED
@@ -1,42 +1,42 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // AgentDesk CLI — AI team orchestrator for Claude Code
3
+ // AgentDesk CLI — AI team orchestrator
4
4
 
5
5
  const args = process.argv.slice(2);
6
6
  const command = args[0];
7
7
 
8
8
  if (!command || command === "help" || command === "--help") {
9
9
  console.log(`
10
- AgentDesk — AI team orchestrator for Claude Code
10
+ AgentDesk — AI team orchestrator
11
11
 
12
12
  Getting started:
13
- 1. Run: agentdesk login
14
- 2. Run: agentdesk init
15
- 3. Run: agentdesk team <TASK-ID>
13
+ 1. agentdesk login Sign in to your account
14
+ 2. agentdesk init Set up your project (choose tracker, save config)
15
+ 3. agentdesk team TASK-123 Run a team session
16
16
 
17
- Usage:
18
- agentdesk login Log in to AgentDesk
19
- agentdesk logout Log out and remove credentials
20
- agentdesk init Detect project and show setup info
21
- agentdesk team <TASK-ID> Run a team session on a task
22
- agentdesk team <TASK-ID> -d "..." Run with a task description
17
+ Commands:
18
+ agentdesk login Sign in to AgentDesk
19
+ agentdesk logout Sign out and remove credentials
20
+ agentdesk init Set up project and configure tracker
21
+ agentdesk team <TASK-ID> Run a team session on an existing task
22
+ agentdesk team -d "..." Create a task and run a session
23
23
 
24
24
  Options:
25
- --description, -d Task description (for projects without a task tracker)
25
+ --description, -d Task description or requirements
26
26
  --cwd Working directory (defaults to current)
27
27
 
28
- Configuration:
29
- Create .agentdesk.json in your project root:
30
- {
31
- "tracker": "linear", // "linear" | "jira" | "github"
32
- "linear": { "workspace": "..." } // for task links in the dashboard
33
- }
28
+ How it works:
29
+ With a tracker (Linear, Jira, GitHub Issues):
30
+ agentdesk team KEN-517 Work on an existing task
31
+ agentdesk team -d "Fix login bug" Create a new task, then work on it
32
+
33
+ Without a tracker:
34
+ agentdesk team -d "Add dark mode" Describe what you want
34
35
 
35
36
  Examples:
36
- agentdesk login
37
- agentdesk init
38
37
  agentdesk team KEN-517
39
- agentdesk team BUG-42 -d "Fix the checkout total calculation"
38
+ agentdesk team -d "Fix the checkout total calculation"
39
+ agentdesk team -d "Add Google OAuth to the login page"
40
40
 
41
41
  Dashboard: https://agentdesk.live
42
42
  `);
@@ -59,23 +59,28 @@ else if (command === "init") {
59
59
  }
60
60
 
61
61
  else if (command === "team") {
62
- const taskId = args[1];
63
- if (!taskId) {
64
- console.error("Usage: agentdesk team <TASK-ID>");
65
- process.exit(1);
66
- }
67
-
68
- // Parse options
62
+ // Parse options first to find -d and --cwd
69
63
  let description = "";
70
64
  let cwd = process.cwd();
71
- for (let i = 2; i < args.length; i++) {
72
- if ((args[i] === "--description" || args[i] === "-d") && args[i + 1]) {
73
- description = args[++i];
74
- } else if (args[i] === "--cwd" && args[i + 1]) {
75
- cwd = args[++i];
65
+ let taskId = null;
66
+ const remaining = args.slice(1);
67
+
68
+ for (let i = 0; i < remaining.length; i++) {
69
+ if ((remaining[i] === "--description" || remaining[i] === "-d") && remaining[i + 1]) {
70
+ description = remaining[++i];
71
+ } else if (remaining[i] === "--cwd" && remaining[i + 1]) {
72
+ cwd = remaining[++i];
73
+ } else if (!taskId && !remaining[i].startsWith("-")) {
74
+ taskId = remaining[i];
76
75
  }
77
76
  }
78
77
 
78
+ if (!taskId && !description) {
79
+ console.error("Usage: agentdesk team <TASK-ID>");
80
+ console.error(" or: agentdesk team -d \"description\"");
81
+ process.exit(1);
82
+ }
83
+
79
84
  const { runTeam } = await import("../cli/team.mjs");
80
85
  const code = await runTeam(taskId, { description, cwd });
81
86
  process.exit(code);
package/cli/init.mjs CHANGED
@@ -1,7 +1,8 @@
1
- // `agentdesk init` — detect project and register with AgentDesk server
1
+ // `agentdesk init` — interactive project setup with tracker configuration
2
2
 
3
- import { existsSync, readFileSync } from "fs";
3
+ import { existsSync, readFileSync, writeFileSync } from "fs";
4
4
  import { join } from "path";
5
+ import { createInterface } from "readline";
5
6
  import { detectProject } from "./detect.mjs";
6
7
  import { loadConfig } from "./config.mjs";
7
8
  import { getStoredApiKey } from "./login.mjs";
@@ -15,11 +16,34 @@ function loadApiKey(dir) {
15
16
  return match?.[1]?.trim() || getStoredApiKey();
16
17
  }
17
18
 
19
+ function ask(rl, question) {
20
+ return new Promise(resolve => rl.question(question, resolve));
21
+ }
22
+
23
+ async function selectOption(rl, prompt, options) {
24
+ console.log(` ${prompt}`);
25
+ console.log("");
26
+ options.forEach((opt, i) => {
27
+ console.log(` ${i + 1}) ${opt.label}`);
28
+ });
29
+ console.log("");
30
+
31
+ while (true) {
32
+ const answer = await ask(rl, ` Choose (1-${options.length}): `);
33
+ const num = parseInt(answer.trim(), 10);
34
+ if (num >= 1 && num <= options.length) return options[num - 1];
35
+ console.log(` Please enter a number between 1 and ${options.length}`);
36
+ }
37
+ }
38
+
18
39
  export async function runInit(cwd) {
19
40
  const project = detectProject(cwd);
20
- const config = loadConfig(cwd);
21
- const tracker = config.tracker || (project.hasLinear ? "linear" : null);
41
+ const existingConfig = loadConfig(cwd);
22
42
  const projectId = project.name || cwd.split("/").pop();
43
+ const configPath = join(cwd, ".agentdesk.json");
44
+ const hasConfig = existsSync(configPath);
45
+
46
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
23
47
 
24
48
  console.log("");
25
49
  console.log(" AgentDesk — Project Setup");
@@ -28,9 +52,8 @@ export async function runInit(cwd) {
28
52
  console.log(` Project: ${project.name || "unknown"}`);
29
53
  console.log(` Type: ${project.label}`);
30
54
  console.log(` Directory: ${project.dir}`);
31
- console.log(` Git: ${project.hasGit ? "" : ""}`);
32
- console.log(` CLAUDE.md: ${project.hasClaudeMd ? "" : " (recommended — run 'claude' to generate one)"}`);
33
- console.log(` Tracker: ${tracker || "— (none)"}`);
55
+ console.log(` Git: ${project.hasGit ? "yes" : "no"}`);
56
+ console.log(` CLAUDE.md: ${project.hasClaudeMd ? "yes" : "no (recommended)"}`);
34
57
  console.log("");
35
58
 
36
59
  if (project.testCommand) console.log(` Test: ${project.testCommand}`);
@@ -38,7 +61,68 @@ export async function runInit(cwd) {
38
61
  if (project.lintCommand) console.log(` Lint: ${project.lintCommand}`);
39
62
  if (project.testCommand || project.buildCommand || project.lintCommand) console.log("");
40
63
 
41
- // Register with AgentDesk server
64
+ // --- Tracker selection ---
65
+ const trackerOptions = [
66
+ { label: "Linear", value: "linear" },
67
+ { label: "Jira", value: "jira" },
68
+ { label: "GitHub Issues", value: "github" },
69
+ { label: "None (use descriptions only)", value: null },
70
+ ];
71
+
72
+ const selected = await selectOption(rl, "Task tracker:", trackerOptions);
73
+ const tracker = selected.value;
74
+ console.log("");
75
+
76
+ // Build config
77
+ const config = {};
78
+ if (tracker) config.tracker = tracker;
79
+
80
+ if (tracker === "linear") {
81
+ const current = existingConfig.linear?.workspace || "";
82
+ const answer = await ask(rl, ` Linear workspace slug${current ? ` (${current})` : ""}: `);
83
+ const ws = answer.trim() || current;
84
+ if (ws) config.linear = { workspace: ws };
85
+ console.log("");
86
+ }
87
+
88
+ if (tracker === "jira") {
89
+ const current = existingConfig.jira?.baseUrl || "";
90
+ const answer = await ask(rl, ` Jira base URL${current ? ` (${current})` : ""}: `);
91
+ const url = answer.trim() || current;
92
+ if (url) config.jira = { baseUrl: url };
93
+ console.log("");
94
+ }
95
+
96
+ if (tracker === "github") {
97
+ const current = existingConfig.github?.repo || "";
98
+ const answer = await ask(rl, ` GitHub repo${current ? ` (${current})` : ""} (owner/repo): `);
99
+ const r = answer.trim() || current;
100
+ if (r) config.github = { repo: r };
101
+ console.log("");
102
+ }
103
+
104
+ // --- Save .agentdesk.json ---
105
+ let merged = {};
106
+ if (hasConfig) {
107
+ try { merged = JSON.parse(readFileSync(configPath, "utf-8")); } catch {}
108
+ }
109
+
110
+ if (tracker) {
111
+ merged.tracker = tracker;
112
+ if (config.linear) merged.linear = config.linear;
113
+ if (config.jira) merged.jira = config.jira;
114
+ if (config.github) merged.github = config.github;
115
+ } else {
116
+ delete merged.tracker;
117
+ delete merged.linear;
118
+ delete merged.jira;
119
+ delete merged.github;
120
+ }
121
+
122
+ writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n");
123
+ console.log(` Saved .agentdesk.json`);
124
+
125
+ // --- Register with server ---
42
126
  try {
43
127
  const res = await fetch(`${SERVER}/api/projects`, {
44
128
  method: "POST",
@@ -55,24 +139,27 @@ export async function runInit(cwd) {
55
139
  }),
56
140
  });
57
141
  if (res.ok) {
58
- console.log(" Registered with AgentDesk server");
59
- } else {
60
- console.log(" ⚠ AgentDesk server not available — project will register on first session");
142
+ console.log(" Registered with agentdesk.live");
61
143
  }
62
144
  } catch {
63
- console.log(" ⚠ AgentDesk server not running — start it with: agentdesk server");
145
+ // Server not available
64
146
  }
65
147
 
66
148
  console.log("");
67
- console.log(" Ready. Run a team session with:");
149
+ console.log(" Ready! Run a team session:");
68
150
  console.log("");
69
- console.log(` agentdesk team TASK-123`);
70
- console.log(` agentdesk team TASK-123 --description "Fix the login bug"`);
151
+ if (tracker) {
152
+ console.log(` agentdesk team TASK-123`);
153
+ console.log(` agentdesk team TASK-123 -d "Optional extra context"`);
154
+ } else {
155
+ console.log(` agentdesk team my-feature -d "Add dark mode support"`);
156
+ }
71
157
  console.log("");
72
158
 
73
159
  if (!project.hasClaudeMd) {
74
- console.log(" Tip: Create a CLAUDE.md in your project root to help the agents");
75
- console.log(" understand your codebase conventions, architecture, and commands.");
160
+ console.log(" Tip: Create a CLAUDE.md to help the agents understand your codebase.");
76
161
  console.log("");
77
162
  }
163
+
164
+ rl.close();
78
165
  }
package/cli/team.mjs CHANGED
@@ -36,19 +36,44 @@ export async function runTeam(taskId, opts = {}) {
36
36
  // Detect project and load config
37
37
  const project = detectProject(cwd);
38
38
  const config = loadConfig(cwd);
39
- console.log(`Project: ${project.name || "unknown"} (${project.label})`);
40
- console.log(`Task: ${taskId}`);
41
-
42
- // Determine tracker and build task link
43
39
  const tracker = config.tracker || (project.hasLinear ? "linear" : null);
40
+
41
+ // If no task ID, handle based on tracker
42
+ let createTask = false;
43
+ if (!taskId) {
44
+ if (tracker) {
45
+ // Tracker configured but no task ID — agents will create a task
46
+ createTask = true;
47
+ taskId = `new-${Date.now().toString(36)}`;
48
+ console.log(`Project: ${project.name || "unknown"} (${project.label})`);
49
+ console.log(`Mode: Create new ${tracker} task from description`);
50
+ } else {
51
+ // No tracker — generate a label from description
52
+ taskId = description
53
+ .toLowerCase()
54
+ .replace(/[^a-z0-9\s-]/g, "")
55
+ .trim()
56
+ .replace(/\s+/g, "-")
57
+ .slice(0, 40) || `task-${Date.now().toString(36)}`;
58
+ console.log(`Project: ${project.name || "unknown"} (${project.label})`);
59
+ console.log(`Task: ${taskId}`);
60
+ }
61
+ } else {
62
+ console.log(`Project: ${project.name || "unknown"} (${project.label})`);
63
+ console.log(`Task: ${taskId}`);
64
+ }
65
+
66
+ // Build task link (only for existing tasks with a tracker)
44
67
  let taskLink = null;
45
- if (tracker === "linear" && config.linear?.workspace) {
46
- taskLink = `https://linear.app/${config.linear.workspace}/issue/${taskId}`;
47
- } else if (tracker === "jira" && config.jira?.baseUrl) {
48
- taskLink = `${config.jira.baseUrl}/browse/${taskId}`;
49
- } else if (tracker === "github") {
50
- const repo = config.github?.repo || "";
51
- if (repo) taskLink = `https://github.com/${repo}/issues/${taskId}`;
68
+ if (!createTask) {
69
+ if (tracker === "linear" && config.linear?.workspace) {
70
+ taskLink = `https://linear.app/${config.linear.workspace}/issue/${taskId}`;
71
+ } else if (tracker === "jira" && config.jira?.baseUrl) {
72
+ taskLink = `${config.jira.baseUrl}/browse/${taskId}`;
73
+ } else if (tracker === "github") {
74
+ const repo = config.github?.repo || "";
75
+ if (repo) taskLink = `https://github.com/${repo}/issues/${taskId}`;
76
+ }
52
77
  }
53
78
  if (tracker) console.log(`Tracker: ${tracker}`);
54
79
  if (taskLink) console.log(`Task: ${taskLink}`);
@@ -68,6 +93,20 @@ export async function runTeam(taskId, opts = {}) {
68
93
  prompt = prompt.replace(/\{\{#TASK_DESCRIPTION\}\}[\s\S]*?\{\{\/TASK_DESCRIPTION\}\}/g, "");
69
94
  }
70
95
 
96
+ // Create task instruction — when -d is used without a task ID and a tracker is configured
97
+ if (createTask && description) {
98
+ let createInstr = "\n\n## CREATE TASK\n\nNo task ID was provided. Before starting work, Jane MUST create a new task in the tracker:\n\n";
99
+ if (tracker === "linear") {
100
+ createInstr += `Create a Linear issue using the GraphQL API:\n- Endpoint: https://api.linear.app/graphql\n- Auth: Authorization: $LINEAR_API_KEY\n- Set the title based on the description below\n- After creation, use the returned identifier (e.g., KEN-530) as the task ID for the rest of the session\n`;
101
+ } else if (tracker === "jira") {
102
+ createInstr += `Create a Jira issue:\n- Endpoint: ${config.jira?.baseUrl || ""}/rest/api/3/issue\n- Auth: Basic auth with $JIRA_EMAIL and $JIRA_API_TOKEN\n- Set the summary based on the description below\n- After creation, use the returned key (e.g., PROJ-42) as the task ID for the rest of the session\n`;
103
+ } else if (tracker === "github") {
104
+ createInstr += `Create a GitHub issue:\n- Run: gh issue create --title "..." --body "..."\n- After creation, use the returned issue number as the task ID for the rest of the session\n`;
105
+ }
106
+ createInstr += `\nTask description: ${description}\n`;
107
+ prompt += createInstr;
108
+ }
109
+
71
110
  // Tracker integration — enable the matching section, strip the rest
72
111
  const trackers = ["LINEAR", "JIRA", "GITHUB"];
73
112
  for (const t of trackers) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kendoo.agentdesk/agentdesk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "AI team orchestrator for Claude Code — run collaborative agent sessions from your terminal",
5
5
  "type": "module",
6
6
  "bin": {