@kendoo.agentdesk/agentdesk 0.1.0 → 0.2.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,119 @@
1
+ # AgentDesk
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).
4
+
5
+ AgentDesk spawns a team of 7 specialized AI agents that collaborate on your tasks:
6
+
7
+ | Agent | Role |
8
+ |-------|------|
9
+ | Jane | Product Lead — facilitates, clarifies requirements, coordinates the team |
10
+ | Luna | UX/UI Designer — visual consistency, accessibility, interaction patterns |
11
+ | Mark | Content Writer — copy, tone, user-facing text |
12
+ | Sam | Architecture Auditor — code structure, separation of concerns |
13
+ | Dennis | Senior Developer — implements the solution |
14
+ | Bart | QA Engineer — edge cases, risks, acceptance criteria |
15
+ | Vera | Test Engineer — unit tests, regression coverage |
16
+
17
+ ## Getting Started
18
+
19
+ ### 1. Install
20
+
21
+ ```bash
22
+ npm i -g @kendoo.agentdesk/agentdesk
23
+ ```
24
+
25
+ Requires [Node.js](https://nodejs.org/) 18+ and [Claude Code](https://claude.ai/claude-code) installed.
26
+
27
+ ### 2. Log in
28
+
29
+ ```bash
30
+ agentdesk login
31
+ ```
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`.
34
+
35
+ ### 3. Set up your project
36
+
37
+ Navigate to your project and run init:
38
+
39
+ ```bash
40
+ agentdesk init
41
+ ```
42
+
43
+ ### 4. Run a team session
44
+
45
+ ```bash
46
+ agentdesk team KEN-517
47
+ agentdesk team BUG-42 -d "Fix the checkout total calculation"
48
+ ```
49
+
50
+ Open [agentdesk.live](https://agentdesk.live) to watch the session live.
51
+
52
+ ## Configuration
53
+
54
+ Create `.agentdesk.json` in your project root to customize behavior:
55
+
56
+ ```json
57
+ {
58
+ "tracker": "linear",
59
+ "linear": { "workspace": "your-workspace" }
60
+ }
61
+ ```
62
+
63
+ ### Task trackers
64
+
65
+ | Tracker | Config |
66
+ |---------|--------|
67
+ | Linear | `{ "tracker": "linear", "linear": { "workspace": "..." } }` |
68
+ | Jira | `{ "tracker": "jira", "jira": { "baseUrl": "https://yourcompany.atlassian.net" } }` |
69
+ | GitHub Issues | `{ "tracker": "github", "github": { "repo": "owner/repo" } }` |
70
+
71
+ ### Declaring project agents
72
+
73
+ If your project has existing AI agents, bots, or automation, declare them so the team knows about them:
74
+
75
+ ```json
76
+ {
77
+ "projectAgents": [
78
+ {
79
+ "name": "ReviewBot",
80
+ "role": "Auto-reviews PRs for security issues",
81
+ "when": "Triggers on every PR creation",
82
+ "how": "Comment /review on a PR to re-trigger"
83
+ }
84
+ ]
85
+ }
86
+ ```
87
+
88
+ AgentDesk also auto-discovers agents from `.claude/agents/`, `.claude/commands/`, `.mcp.json`, GitHub Actions workflows, Dependabot, and Renovate configs.
89
+
90
+ ## Usage
91
+
92
+ ```
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
98
+ ```
99
+
100
+ ### Options
101
+
102
+ | Flag | Description |
103
+ |------|-------------|
104
+ | `--description`, `-d` | Task description (for projects without a task tracker) |
105
+ | `--cwd` | Working directory (defaults to current) |
106
+
107
+ ## How It Works
108
+
109
+ 1. You run `agentdesk team TASK-ID` in your project directory
110
+ 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
114
+
115
+ ## Requirements
116
+
117
+ - [Node.js](https://nodejs.org/) 18+
118
+ - [Claude Code](https://claude.ai/claude-code) CLI installed and authenticated
119
+ - An AgentDesk account at [agentdesk.live](https://agentdesk.live)
package/bin/agentdesk.mjs CHANGED
@@ -10,12 +10,13 @@ if (!command || command === "help" || command === "--help") {
10
10
  AgentDesk — AI team orchestrator for Claude Code
11
11
 
12
12
  Getting started:
13
- 1. Sign up at https://agentdesk.live and copy your API key from Settings
14
- 2. Add to your project's .env: AGENTDESK_API_KEY=<your-key>
15
- 3. Run: agentdesk init
16
- 4. Run: agentdesk team <TASK-ID>
13
+ 1. Run: agentdesk login
14
+ 2. Run: agentdesk init
15
+ 3. Run: agentdesk team <TASK-ID>
17
16
 
18
17
  Usage:
18
+ agentdesk login Log in to AgentDesk
19
+ agentdesk logout Log out and remove credentials
19
20
  agentdesk init Detect project and show setup info
20
21
  agentdesk team <TASK-ID> Run a team session on a task
21
22
  agentdesk team <TASK-ID> -d "..." Run with a task description
@@ -32,6 +33,7 @@ if (!command || command === "help" || command === "--help") {
32
33
  }
33
34
 
34
35
  Examples:
36
+ agentdesk login
35
37
  agentdesk init
36
38
  agentdesk team KEN-517
37
39
  agentdesk team BUG-42 -d "Fix the checkout total calculation"
@@ -41,7 +43,17 @@ if (!command || command === "help" || command === "--help") {
41
43
  process.exit(0);
42
44
  }
43
45
 
44
- if (command === "init") {
46
+ if (command === "login") {
47
+ const { runLogin } = await import("../cli/login.mjs");
48
+ await runLogin();
49
+ }
50
+
51
+ else if (command === "logout") {
52
+ const { runLogout } = await import("../cli/login.mjs");
53
+ await runLogout();
54
+ }
55
+
56
+ else if (command === "init") {
45
57
  const { runInit } = await import("../cli/init.mjs");
46
58
  await runInit(process.cwd());
47
59
  }
package/cli/init.mjs CHANGED
@@ -4,14 +4,15 @@ import { existsSync, readFileSync } from "fs";
4
4
  import { join } from "path";
5
5
  import { detectProject } from "./detect.mjs";
6
6
  import { loadConfig } from "./config.mjs";
7
+ import { getStoredApiKey } from "./login.mjs";
7
8
 
8
9
  const SERVER = process.env.AGENTDESK_SERVER || "https://agentdesk.live";
9
10
 
10
11
  function loadApiKey(dir) {
11
12
  const envPath = join(dir, ".env");
12
- if (!existsSync(envPath)) return null;
13
+ if (!existsSync(envPath)) return getStoredApiKey();
13
14
  const match = readFileSync(envPath, "utf-8").match(/AGENTDESK_API_KEY=(.+)/);
14
- return match?.[1]?.trim() || null;
15
+ return match?.[1]?.trim() || getStoredApiKey();
15
16
  }
16
17
 
17
18
  export async function runInit(cwd) {
package/cli/login.mjs ADDED
@@ -0,0 +1,129 @@
1
+ // `agentdesk login` — authenticate with AgentDesk and save API key
2
+
3
+ import { createServer } from "http";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
+ import { join } from "path";
6
+ import { randomUUID } from "crypto";
7
+
8
+ const AGENTDESK_SERVER = process.env.AGENTDESK_SERVER || "https://agentdesk.live";
9
+ const CONFIG_DIR = join(process.env.HOME || process.env.USERPROFILE, ".agentdesk");
10
+ const CREDENTIALS_PATH = join(CONFIG_DIR, "credentials.json");
11
+
12
+ export function getStoredApiKey() {
13
+ if (!existsSync(CREDENTIALS_PATH)) return null;
14
+ try {
15
+ const creds = JSON.parse(readFileSync(CREDENTIALS_PATH, "utf-8"));
16
+ return creds.apiKey || null;
17
+ } catch { return null; }
18
+ }
19
+
20
+ export async function runLogin() {
21
+ console.log("");
22
+ console.log(" AgentDesk — Login");
23
+ console.log(" ━━━━━━━━━━━━━━━━");
24
+ console.log("");
25
+
26
+ // Check if already logged in
27
+ const existing = getStoredApiKey();
28
+ if (existing) {
29
+ console.log(` Already logged in (key: ${existing.slice(0, 8)}...)`);
30
+ console.log("");
31
+ console.log(" To re-authenticate, run: agentdesk logout");
32
+ console.log("");
33
+ return;
34
+ }
35
+
36
+ const state = randomUUID();
37
+
38
+ // Start a local server to receive the API key callback
39
+ const server = createServer((req, res) => {
40
+ // Allow CORS from agentdesk.live
41
+ res.setHeader("Access-Control-Allow-Origin", "*");
42
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
43
+ if (req.method === "OPTIONS") { res.writeHead(200); res.end(); return; }
44
+
45
+ const url = new URL(req.url, `http://localhost`);
46
+
47
+ if (url.pathname === "/callback") {
48
+ const apiKey = url.searchParams.get("api_key");
49
+ const name = url.searchParams.get("name");
50
+ const returnedState = url.searchParams.get("state");
51
+
52
+ // CSRF check
53
+ if (returnedState !== state) {
54
+ res.writeHead(400, { "Content-Type": "text/html" });
55
+ res.end("<html><body><h2>Invalid state. Please try again.</h2></body></html>");
56
+ return;
57
+ }
58
+
59
+ if (apiKey) {
60
+ // Save credentials
61
+ if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true });
62
+ writeFileSync(CREDENTIALS_PATH, JSON.stringify({ apiKey, name, savedAt: Date.now() }, null, 2));
63
+
64
+ res.writeHead(200, { "Content-Type": "text/html" });
65
+ res.end(`<html><body style="background:#0f172a;color:#e2e8f0;font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0"><div style="text-align:center"><h2 style="color:#2dd4bf">Logged in to AgentDesk</h2><p>You can close this tab and return to your terminal.</p></div></body></html>`);
66
+
67
+ console.log(` Logged in as ${name || "user"}`);
68
+ console.log(` API key saved to ~/.agentdesk/credentials.json`);
69
+ console.log("");
70
+ console.log(" Next steps:");
71
+ console.log(" agentdesk init");
72
+ console.log(" agentdesk team TASK-123");
73
+ console.log("");
74
+
75
+ setTimeout(() => { server.close(); process.exit(0); }, 500);
76
+ } else {
77
+ res.writeHead(400, { "Content-Type": "text/html" });
78
+ res.end("<html><body><h2>Login failed. No API key received.</h2></body></html>");
79
+ }
80
+ return;
81
+ }
82
+
83
+ res.writeHead(404);
84
+ res.end();
85
+ });
86
+
87
+ // Find an available port
88
+ await new Promise((resolve) => {
89
+ server.listen(0, "127.0.0.1", resolve);
90
+ });
91
+ const port = server.address().port;
92
+
93
+ const loginUrl = `${AGENTDESK_SERVER}/cli-auth?port=${port}&state=${state}`;
94
+
95
+ console.log(` Opening browser to log in...`);
96
+ console.log("");
97
+ console.log(` If the browser doesn't open, visit:`);
98
+ console.log(` ${loginUrl}`);
99
+ console.log("");
100
+ console.log(" Waiting for authentication...");
101
+
102
+ // Open browser
103
+ const { exec } = await import("child_process");
104
+ const platform = process.platform;
105
+ const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
106
+ exec(`${cmd} "${loginUrl}"`);
107
+
108
+ // Timeout after 5 minutes
109
+ setTimeout(() => {
110
+ console.log("");
111
+ console.log(" Login timed out. Please try again.");
112
+ server.close();
113
+ process.exit(1);
114
+ }, 5 * 60 * 1000);
115
+ }
116
+
117
+ export async function runLogout() {
118
+ if (existsSync(CREDENTIALS_PATH)) {
119
+ const { unlinkSync } = await import("fs");
120
+ unlinkSync(CREDENTIALS_PATH);
121
+ console.log("");
122
+ console.log(" Logged out. Credentials removed.");
123
+ console.log("");
124
+ } else {
125
+ console.log("");
126
+ console.log(" Not logged in.");
127
+ console.log("");
128
+ }
129
+ }
package/cli/team.mjs CHANGED
@@ -9,6 +9,7 @@ import { randomUUID } from "crypto";
9
9
  import WebSocket from "ws";
10
10
  import { detectProject, generateContext } from "./detect.mjs";
11
11
  import { loadConfig } from "./config.mjs";
12
+ import { getStoredApiKey } from "./login.mjs";
12
13
 
13
14
  function loadDotEnv(dir) {
14
15
  const envPath = join(dir, ".env");
@@ -96,7 +97,7 @@ export async function runTeam(taskId, opts = {}) {
96
97
 
97
98
  // --- AgentDesk config ---
98
99
  const projectEnv = loadDotEnv(cwd);
99
- const apiKey = projectEnv.AGENTDESK_API_KEY || process.env.AGENTDESK_API_KEY || null;
100
+ const apiKey = projectEnv.AGENTDESK_API_KEY || process.env.AGENTDESK_API_KEY || getStoredApiKey() || null;
100
101
  const agentdeskServer = process.env.AGENTDESK_SERVER || "https://agentdesk.live";
101
102
  const baseUrl = process.env.AGENTDESK_URL || "wss://agentdesk.live/ws/agent";
102
103
  const AGENTDESK_URL = apiKey ? `${baseUrl}?api_key=${apiKey}` : baseUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kendoo.agentdesk/agentdesk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "AI team orchestrator for Claude Code — run collaborative agent sessions from your terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,7 +9,8 @@
9
9
  "files": [
10
10
  "bin/",
11
11
  "cli/",
12
- "prompts/"
12
+ "prompts/",
13
+ "README.md"
13
14
  ],
14
15
  "engines": {
15
16
  "node": ">=18"