@kendoo.agentdesk/agentdesk 0.9.19 → 0.9.21
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 +49 -1
- package/bin/agentdesk.mjs +35 -1
- package/cli/orchestrator.mjs +57 -13
- package/cli/prompt.mjs +82 -0
- package/cli/team.mjs +14 -1
- package/package.json +1 -1
- package/prompts/team.md +10 -0
package/README.md
CHANGED
|
@@ -69,6 +69,7 @@ agentdesk logout Sign out and remove credentials
|
|
|
69
69
|
agentdesk init Set up project and configure tracker
|
|
70
70
|
agentdesk team <TASK-ID> Run a team session on an existing task
|
|
71
71
|
agentdesk team -d "..." Describe what you want — task created automatically
|
|
72
|
+
agentdesk <agent> -d "..." Run a single agent (jane, dennis, sam, bart, vera, luna, mark)
|
|
72
73
|
agentdesk daemon Start daemon for remote sessions
|
|
73
74
|
agentdesk update Update to the latest version
|
|
74
75
|
```
|
|
@@ -113,6 +114,30 @@ You can also define them in `.agentdesk.json` as a local override if preferred.
|
|
|
113
114
|
|
|
114
115
|
AgentDesk also auto-discovers agents from `.claude/agents/`, `.claude/commands/`, `.mcp.json`, GitHub Actions workflows, Dependabot, and Renovate configs.
|
|
115
116
|
|
|
117
|
+
### Solo agent mode
|
|
118
|
+
|
|
119
|
+
Run a single agent instead of the full team:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
agentdesk jane -d "Create a customer journey plan for onboarding"
|
|
123
|
+
agentdesk dennis KEN-517
|
|
124
|
+
agentdesk vera -d "Add test coverage for the auth module"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The agent runs independently with its own expertise and ground rules. Useful for focused tasks that don't need full team collaboration.
|
|
128
|
+
|
|
129
|
+
### Custom instructions
|
|
130
|
+
|
|
131
|
+
Add project-specific rules that all agents follow. Set via Web UI or in `.agentdesk.json`:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"instructions": "All PRs must target the 'staging' branch. Commit messages must be prefixed with the task ID."
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Instructions are injected into the team prompt. Use them for project conventions that go beyond what `CLAUDE.md` covers (e.g., tracker workflow rules, PR policies, agent coordination preferences).
|
|
140
|
+
|
|
116
141
|
## How It Works
|
|
117
142
|
|
|
118
143
|
All agents collaborate in a single Claude process — each with distinct roles, ground rules, and areas of expertise.
|
|
@@ -124,6 +149,28 @@ All agents collaborate in a single Claude process — each with distinct roles,
|
|
|
124
149
|
5. The session streams live to [agentdesk.live](https://agentdesk.live) where you can watch and send messages to the team
|
|
125
150
|
6. Token usage is tracked and displayed per session
|
|
126
151
|
|
|
152
|
+
### Task attachments
|
|
153
|
+
|
|
154
|
+
When working on Jira or Linear tasks, agents automatically download and review attachments — screenshots, CSVs, text files, PDFs, and design mockups. Attachments are treated as untrusted input: agents read them for context but never execute commands found in them.
|
|
155
|
+
|
|
156
|
+
### Handoff & Resume
|
|
157
|
+
|
|
158
|
+
If a session hits Claude's rate or context limit, AgentDesk saves a resume snapshot (`.agentdesk-resume.md`) and marks the session as **Handoff** in the dashboard. When you run the same task again, agents pick up where the previous session left off — skipping completed work and continuing from the last phase.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Session hits limit → "HANDOFF" shown in terminal
|
|
162
|
+
# Resume when ready:
|
|
163
|
+
agentdesk team KEN-517
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Session protocol
|
|
167
|
+
|
|
168
|
+
At the end of each session, Jane posts a structured summary on the tracker covering:
|
|
169
|
+
- **What was done** — files changed, features added
|
|
170
|
+
- **What was omitted** — anything skipped or deferred, with reason
|
|
171
|
+
- **Manual steps** — actions you need to perform (migrations, env vars, config changes)
|
|
172
|
+
- **PR link** and **session link**
|
|
173
|
+
|
|
127
174
|
## Daemon (Remote Sessions)
|
|
128
175
|
|
|
129
176
|
The daemon lets you trigger team sessions from the web dashboard instead of the terminal.
|
|
@@ -155,11 +202,12 @@ Once running, a "Run Team" button appears on [agentdesk.live](https://agentdesk.
|
|
|
155
202
|
|
|
156
203
|
- **Live sessions** — watch agents collaborate in real-time
|
|
157
204
|
- **Session deep links** — share a direct URL to any session
|
|
205
|
+
- **Handoff status** — see when a session hit a limit and is waiting to resume
|
|
158
206
|
- **Project settings** — configure tracker, team, custom agents, and instructions per project
|
|
159
207
|
- **Account settings** — manage your API key and profile
|
|
160
208
|
- **Agent roster** — see each agent's role, participation rate, tag breakdown, and phase involvement
|
|
161
209
|
- **Token tracking** — input/output token counts per session
|
|
162
|
-
- **Auto-reconnect** — CLI reconnects automatically if the connection drops
|
|
210
|
+
- **Auto-reconnect** — CLI sends heartbeats and reconnects automatically if the connection drops
|
|
163
211
|
|
|
164
212
|
## Requirements
|
|
165
213
|
|
package/bin/agentdesk.mjs
CHANGED
|
@@ -64,6 +64,7 @@ if (!command || command === "help" || command === "--help") {
|
|
|
64
64
|
agentdesk init Set up project and configure tracker
|
|
65
65
|
agentdesk team <TASK-ID> Run a team session on an existing task
|
|
66
66
|
agentdesk team -d "..." Create a task and run a session
|
|
67
|
+
agentdesk <agent> -d "..." Run a single agent (jane, dennis, sam, etc.)
|
|
67
68
|
agentdesk daemon Start daemon for remote sessions
|
|
68
69
|
agentdesk update Update to the latest version
|
|
69
70
|
|
|
@@ -85,12 +86,45 @@ if (!command || command === "help" || command === "--help") {
|
|
|
85
86
|
agentdesk team -d "Fix the checkout total calculation"
|
|
86
87
|
agentdesk team -d "Add Google OAuth to the login page"
|
|
87
88
|
|
|
89
|
+
Resume:
|
|
90
|
+
If a session hits Claude's limit, it saves a handoff file.
|
|
91
|
+
Run the same task again to resume where it left off.
|
|
92
|
+
|
|
88
93
|
Dashboard: \x1b[36mhttps://agentdesk.live\x1b[0m
|
|
89
94
|
`);
|
|
90
95
|
process.exit(0);
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
|
|
98
|
+
// Single-agent mode — agentdesk jane -d "...", agentdesk dennis TASK-123, etc.
|
|
99
|
+
const AGENT_NAMES = ["jane", "dennis", "sam", "bart", "vera", "luna", "mark"];
|
|
100
|
+
if (AGENT_NAMES.includes(command?.toLowerCase())) {
|
|
101
|
+
let description = "";
|
|
102
|
+
let cwd = process.cwd();
|
|
103
|
+
let taskId = null;
|
|
104
|
+
const remaining = args.slice(1);
|
|
105
|
+
|
|
106
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
107
|
+
if ((remaining[i] === "--description" || remaining[i] === "-d") && remaining[i + 1]) {
|
|
108
|
+
description = remaining[++i];
|
|
109
|
+
} else if (remaining[i] === "--cwd" && remaining[i + 1]) {
|
|
110
|
+
cwd = remaining[++i];
|
|
111
|
+
} else if (!taskId && !remaining[i].startsWith("-")) {
|
|
112
|
+
taskId = remaining[i];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!taskId && !description) {
|
|
117
|
+
console.error(`Usage: agentdesk ${command} <TASK-ID>`);
|
|
118
|
+
console.error(` or: agentdesk ${command} -d "description"`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const { runTeam } = await import("../cli/team.mjs");
|
|
123
|
+
const code = await runTeam(taskId, { description, cwd, soloAgent: command.charAt(0).toUpperCase() + command.slice(1).toLowerCase() });
|
|
124
|
+
process.exit(code);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
else if (command === "login") {
|
|
94
128
|
const { runLogin } = await import("../cli/login.mjs");
|
|
95
129
|
await runLogin();
|
|
96
130
|
}
|
package/cli/orchestrator.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Orchestrator — runs a single Claude process with all agents as personas
|
|
2
2
|
|
|
3
|
-
import { spawn } from "child_process";
|
|
4
|
-
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { spawn, execSync } from "child_process";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
5
5
|
import { createInterface } from "readline";
|
|
6
6
|
import { join, dirname } from "path";
|
|
7
7
|
import { fileURLToPath } from "url";
|
|
8
|
-
import { buildPrompt } from "./prompt.mjs";
|
|
8
|
+
import { buildPrompt, buildSoloPrompt } from "./prompt.mjs";
|
|
9
9
|
import { createStreamParser } from "./stream-parser.mjs";
|
|
10
10
|
|
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -47,7 +47,7 @@ function timestamp() {
|
|
|
47
47
|
export async function runOrchestrator({
|
|
48
48
|
taskId, taskLink, description, createTask, tracker, config,
|
|
49
49
|
project, team, teamSections, inboxUrl, sessionUrl, cwd,
|
|
50
|
-
onEvent, apiKey, serverUrl,
|
|
50
|
+
onEvent, apiKey, serverUrl, soloAgent,
|
|
51
51
|
}) {
|
|
52
52
|
const trackerCreds = await fetchTrackerCredentials(project?.name, apiKey, serverUrl);
|
|
53
53
|
const env = { ...process.env, ...loadDotEnv(cwd), ...trackerCreds };
|
|
@@ -56,14 +56,16 @@ export async function runOrchestrator({
|
|
|
56
56
|
let totalOutputTokens = 0;
|
|
57
57
|
let totalSteps = 0;
|
|
58
58
|
|
|
59
|
+
let lastPhase = null;
|
|
60
|
+
|
|
59
61
|
function emit(event) {
|
|
62
|
+
if (event.type === "phase:change") lastPhase = event.phase;
|
|
60
63
|
onEvent?.({ ...event, timestamp: timestamp() });
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
const fullPrompt =
|
|
64
|
-
|
|
65
|
-
project, teamSections, inboxUrl, sessionUrl
|
|
66
|
-
});
|
|
66
|
+
const fullPrompt = soloAgent
|
|
67
|
+
? buildSoloPrompt({ agentName: soloAgent, taskId, description, tracker, config, project, sessionUrl })
|
|
68
|
+
: buildPrompt({ taskId, taskLink, description, createTask, tracker, config, project, teamSections, inboxUrl, sessionUrl });
|
|
67
69
|
|
|
68
70
|
emit({
|
|
69
71
|
type: "session:start",
|
|
@@ -71,11 +73,11 @@ export async function runOrchestrator({
|
|
|
71
73
|
title: description || taskId,
|
|
72
74
|
project: project?.name || null,
|
|
73
75
|
sessionNumber: 1,
|
|
74
|
-
agents: teamSections.names,
|
|
76
|
+
agents: soloAgent ? [soloAgent] : teamSections.names,
|
|
75
77
|
cliVersion: CLI_VERSION,
|
|
76
78
|
});
|
|
77
79
|
|
|
78
|
-
emit({ type: "phase:change", phase: "INTAKE" });
|
|
80
|
+
emit({ type: "phase:change", phase: soloAgent ? "EXECUTION" : "INTAKE" });
|
|
79
81
|
|
|
80
82
|
const child = spawn(
|
|
81
83
|
"claude",
|
|
@@ -108,10 +110,52 @@ export async function runOrchestrator({
|
|
|
108
110
|
parseLine(line);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
await new Promise(resolve => child.on("close", resolve));
|
|
113
|
+
const exitCode = await new Promise(resolve => child.on("close", resolve));
|
|
112
114
|
|
|
113
115
|
const duration = `${((Date.now() - startTime) / 1000).toFixed(1)}s`;
|
|
114
|
-
emit({ type: "session:end", duration, steps: totalSteps, inputTokens: totalInputTokens, outputTokens: totalOutputTokens });
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
// Detect limit/crash — non-zero exit without a clean session end
|
|
118
|
+
const isHandoff = exitCode !== 0;
|
|
119
|
+
|
|
120
|
+
if (isHandoff) {
|
|
121
|
+
// Write mechanical resume snapshot
|
|
122
|
+
let branch = "";
|
|
123
|
+
let diffStat = "";
|
|
124
|
+
try { branch = execSync("git branch --show-current", { cwd, encoding: "utf-8" }).trim(); } catch {}
|
|
125
|
+
try { diffStat = execSync("git diff --stat HEAD", { cwd, encoding: "utf-8" }).trim(); } catch {}
|
|
126
|
+
|
|
127
|
+
const resumePath = join(cwd, ".agentdesk-resume.md");
|
|
128
|
+
const resumeContent = [
|
|
129
|
+
`# AgentDesk Resume — ${taskId}`,
|
|
130
|
+
``,
|
|
131
|
+
`Session: ${sessionUrl}`,
|
|
132
|
+
`Date: ${new Date().toISOString()}`,
|
|
133
|
+
`Phase: ${lastPhase || "UNKNOWN"}`,
|
|
134
|
+
`Duration: ${duration}`,
|
|
135
|
+
`Steps: ${totalSteps}`,
|
|
136
|
+
`Exit code: ${exitCode}`,
|
|
137
|
+
``,
|
|
138
|
+
`## Branch`,
|
|
139
|
+
branch || "(no branch)",
|
|
140
|
+
``,
|
|
141
|
+
`## Uncommitted changes`,
|
|
142
|
+
diffStat || "(none)",
|
|
143
|
+
``,
|
|
144
|
+
`## Notes`,
|
|
145
|
+
`Session ended unexpectedly (likely Claude rate/context limit).`,
|
|
146
|
+
`Resume with: agentdesk team ${taskId}`,
|
|
147
|
+
``,
|
|
148
|
+
].join("\n");
|
|
149
|
+
try { writeFileSync(resumePath, resumeContent); } catch {}
|
|
150
|
+
|
|
151
|
+
emit({ type: "session:end", duration, steps: totalSteps, inputTokens: totalInputTokens, outputTokens: totalOutputTokens, status: "handoff" });
|
|
152
|
+
} else {
|
|
153
|
+
// Clean exit — remove stale resume file if present
|
|
154
|
+
const resumePath = join(cwd, ".agentdesk-resume.md");
|
|
155
|
+
try { if (existsSync(resumePath)) unlinkSync(resumePath); } catch {}
|
|
156
|
+
|
|
157
|
+
emit({ type: "session:end", duration, steps: totalSteps, inputTokens: totalInputTokens, outputTokens: totalOutputTokens });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { duration, steps: totalSteps, inputTokens: totalInputTokens, outputTokens: totalOutputTokens, handoff: isHandoff };
|
|
117
161
|
}
|
package/cli/prompt.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { readFileSync } from "fs";
|
|
|
4
4
|
import { resolve, dirname } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { generateContext } from "./detect.mjs";
|
|
7
|
+
import { BUILT_IN_AGENTS } from "./agents.mjs";
|
|
7
8
|
|
|
8
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const PROMPT_PATH = resolve(__dirname, "../prompts/team.md");
|
|
@@ -100,3 +101,84 @@ export function buildPrompt({ taskId, taskLink, description, createTask, tracker
|
|
|
100
101
|
|
|
101
102
|
return `${prompt}\n\n---\n\n## PROJECT CONTEXT\n\n${context}\n\n${timeInfo}`;
|
|
102
103
|
}
|
|
104
|
+
|
|
105
|
+
export function buildSoloPrompt({ agentName, taskId, description, tracker, config, project, sessionUrl }) {
|
|
106
|
+
const agent = BUILT_IN_AGENTS[agentName];
|
|
107
|
+
if (!agent) throw new Error(`Unknown agent: ${agentName}`);
|
|
108
|
+
|
|
109
|
+
const lines = [
|
|
110
|
+
`# ${agentName} — ${agent.role} (Solo Mode)`,
|
|
111
|
+
``,
|
|
112
|
+
`You are ${agentName}, ${agent.description}.`,
|
|
113
|
+
`You are working independently on this task — there is no team. You handle everything yourself.`,
|
|
114
|
+
``,
|
|
115
|
+
agent.groundRules ? `## Ground Rules\n\n${agent.groundRules}` : "",
|
|
116
|
+
agent.codePrinciple ? `## Code Principles\n\n${agent.codePrinciple}` : "",
|
|
117
|
+
``,
|
|
118
|
+
`## Task`,
|
|
119
|
+
``,
|
|
120
|
+
taskId ? `Task ID: ${taskId}` : "",
|
|
121
|
+
description ? `Description: ${description}` : "",
|
|
122
|
+
sessionUrl ? `Session: ${sessionUrl}` : "",
|
|
123
|
+
``,
|
|
124
|
+
`## Instructions`,
|
|
125
|
+
``,
|
|
126
|
+
`Work on this task independently. Follow CLAUDE.md conventions if present.`,
|
|
127
|
+
`Read and understand the codebase before making changes.`,
|
|
128
|
+
``,
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
if (agent.execution?.tasks) {
|
|
132
|
+
lines.push(`## Your responsibilities`, ``);
|
|
133
|
+
for (const t of agent.execution.tasks) {
|
|
134
|
+
lines.push(`- ${t}`);
|
|
135
|
+
}
|
|
136
|
+
lines.push(``);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Extract and include tracker integration from team prompt
|
|
140
|
+
if (tracker && taskId) {
|
|
141
|
+
let teamPrompt = readFileSync(PROMPT_PATH, "utf-8");
|
|
142
|
+
|
|
143
|
+
// Extract the matching tracker block
|
|
144
|
+
const trackerKey = tracker.toUpperCase();
|
|
145
|
+
const trackerRegex = new RegExp(`\\{\\{#${trackerKey}\\}\\}([\\s\\S]*?)\\{\\{\\/${trackerKey}\\}\\}`, "g");
|
|
146
|
+
let trackerSection = "";
|
|
147
|
+
let match;
|
|
148
|
+
while ((match = trackerRegex.exec(teamPrompt)) !== null) {
|
|
149
|
+
trackerSection += match[1] + "\n";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (trackerSection) {
|
|
153
|
+
// Substitute variables
|
|
154
|
+
trackerSection = trackerSection.replace(/\{\{TASK_ID\}\}/g, taskId);
|
|
155
|
+
trackerSection = trackerSection.replace(/\{\{SESSION_URL\}\}/g, sessionUrl || "");
|
|
156
|
+
if (config.jira?.baseUrl) {
|
|
157
|
+
trackerSection = trackerSection.replace(/\{\{JIRA_BASE_URL\}\}/g, config.jira.baseUrl.replace(/\/+$/, ""));
|
|
158
|
+
}
|
|
159
|
+
lines.push(trackerSection);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
lines.push(
|
|
163
|
+
`## Required tracker actions`,
|
|
164
|
+
``,
|
|
165
|
+
`1. Fetch the task — read summary, description, status, comments, attachments.`,
|
|
166
|
+
`2. Post a comment: "${agentName} working on this task (solo mode). Session: ${sessionUrl || ""}"`,
|
|
167
|
+
`3. Do your work.`,
|
|
168
|
+
`4. Post a final comment summarizing what was done, what was omitted, and any manual steps required.`,
|
|
169
|
+
``,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Add custom instructions
|
|
174
|
+
if (config?.instructions) {
|
|
175
|
+
lines.push(`## Additional Instructions`, ``, config.instructions, ``);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Add project context
|
|
179
|
+
const context = generateContext(project);
|
|
180
|
+
const now = new Date();
|
|
181
|
+
const timeInfo = `Current date/time: ${now.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })} ${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" })}`;
|
|
182
|
+
|
|
183
|
+
return lines.filter(Boolean).join("\n") + `\n\n---\n\n## PROJECT CONTEXT\n\n${context}\n\n${timeInfo}`;
|
|
184
|
+
}
|
package/cli/team.mjs
CHANGED
|
@@ -87,6 +87,10 @@ export async function runTeam(taskId, opts = {}) {
|
|
|
87
87
|
console.log(`Jira: ${cyan}${config.jira.baseUrl}${reset}`);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
if (opts.soloAgent) {
|
|
91
|
+
console.log(`Agent: ${opts.soloAgent} (solo mode)`);
|
|
92
|
+
}
|
|
93
|
+
|
|
90
94
|
// Resolve team and generate dynamic prompt sections
|
|
91
95
|
const team = resolveTeam(config);
|
|
92
96
|
const teamSections = generateTeamPrompt(team, { tracker, config });
|
|
@@ -206,11 +210,20 @@ export async function runTeam(taskId, opts = {}) {
|
|
|
206
210
|
onEvent: vizSend,
|
|
207
211
|
apiKey,
|
|
208
212
|
serverUrl: agentdeskServer,
|
|
213
|
+
soloAgent: opts.soloAgent || null,
|
|
209
214
|
});
|
|
210
215
|
|
|
211
216
|
clearInterval(heartbeatInterval);
|
|
212
217
|
|
|
213
|
-
|
|
218
|
+
if (result.handoff) {
|
|
219
|
+
const yellow = "\x1b[33m";
|
|
220
|
+
console.log(`\n━━━ ${yellow}HANDOFF${reset} ━━━`);
|
|
221
|
+
console.log(` Session paused — likely hit Claude rate/context limit.`);
|
|
222
|
+
console.log(` Resume file saved to .agentdesk-resume.md`);
|
|
223
|
+
console.log(` Resume with: ${cyan}agentdesk team ${taskId}${reset}\n`);
|
|
224
|
+
} else {
|
|
225
|
+
console.log(`\n━━━ DONE ━━━`);
|
|
226
|
+
}
|
|
214
227
|
const totalTokens = result.inputTokens + result.outputTokens;
|
|
215
228
|
console.log(` ${result.duration} | ${result.steps} steps${totalTokens ? ` | ${totalTokens.toLocaleString()} tokens` : ""}\n`);
|
|
216
229
|
|
package/package.json
CHANGED
package/prompts/team.md
CHANGED
|
@@ -309,6 +309,15 @@ Fetch the issue from GitHub — print title, body, state, existing comments.
|
|
|
309
309
|
Read the task description. If CLAUDE.md exists, read it.
|
|
310
310
|
{{/NO_TRACKER}}
|
|
311
311
|
|
|
312
|
+
### Resume check
|
|
313
|
+
|
|
314
|
+
Check if `.agentdesk-resume.md` exists in the project root. If it does, this is a **resumed session** — a previous session was interrupted (likely by a Claude rate/context limit). Read the file to understand:
|
|
315
|
+
- What phase the previous session reached
|
|
316
|
+
- What branch was being used
|
|
317
|
+
- What changes were already made
|
|
318
|
+
|
|
319
|
+
Use this context to skip completed work and continue from where the previous session left off. Delete `.agentdesk-resume.md` after reading it.
|
|
320
|
+
|
|
312
321
|
### Assess
|
|
313
322
|
|
|
314
323
|
1. Check for existing branches: `git branch -a | grep {{TASK_ID}}`
|
|
@@ -317,6 +326,7 @@ Read the task description. If CLAUDE.md exists, read it.
|
|
|
317
326
|
4. Check for project agents: `ls .claude/agents/ .claude/commands/ .github/workflows/ 2>/dev/null`; check if `.mcp.json` exists. If agents are found, Jane briefs the team and assigns usage.
|
|
318
327
|
|
|
319
328
|
Based on findings:
|
|
329
|
+
- Resume file exists → review previous progress, continue from where it left off
|
|
320
330
|
- Fresh task → PLAN phase
|
|
321
331
|
- Branch exists, no PR → review what's done, continue from EXECUTION
|
|
322
332
|
- PR exists → review PR status, continue accordingly
|