Skip to content

Commit 1aa5e2b

Browse files
committed
feat: session continuation for claude adapter (--continue, --resume, --session-id)
opengap run -a claude previously had no way to continue a prior Claude Code conversation — every run started fresh. Adds three flags mapped to Claude Code's native session flags: - -c, --continue: continue the most recent session in the working directory (pairs with --workspace, which decides where the session is looked up) - --resume <sessionId>: reopen an exact session by ID - --session-id <uuid>: pin a new session to a known UUID so scripts can resume deterministically later Guards: --continue and --resume are mutually exclusive; --session-id must be a valid UUID; all three are rejected with a clear error for non-claude adapters instead of being silently ignored. Docs updated with a session- continuation section and examples.
1 parent e6fa391 commit 1aa5e2b

3 files changed

Lines changed: 63 additions & 1 deletion

File tree

docs.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,9 +633,14 @@ opengap run [options]
633633
| `--refresh` | `false` | Force re-clone (pull latest) |
634634
| `--no-cache` | `false` | Clone to temp dir, delete on exit |
635635
| `-p, --prompt <query>` || Initial prompt (non-interactive for some adapters) |
636+
| `-c, --continue` | `false` | Continue the most recent session in the working directory (claude adapter only) |
637+
| `--resume <sessionId>` || Resume a specific session by ID (claude adapter only) |
638+
| `--session-id <uuid>` || Start with a specific session ID so it can be resumed later (claude adapter only) |
636639

637640
Either `--repo` or `--dir` is required.
638641

642+
**Session continuation (claude adapter).** `--continue` resumes the most recent Claude Code conversation in the working directory — combine it with `--workspace` to pick which directory's session to continue. `--resume <sessionId>` reopens an exact session, and `--session-id <uuid>` pins a new session to a known ID so scripts can resume it deterministically later. `--continue` and `--resume` are mutually exclusive. These flags are rejected for non-claude adapters rather than silently ignored.
643+
639644
`--workspace` lets an agent definition live separately from the repository it operates on. It is honored by adapters that can safely set the spawned process working directory directly, including `claude`, `openai`, `crewai`, `openclaw`, and `nanobot`. Adapters that generate an isolated runtime workspace, such as `opencode`, `gemini`, and `gitclaw`, continue to run from that prepared workspace to avoid overwriting files such as `AGENTS.md`, `GEMINI.md`, or `agent.yaml` in the target repository.
640645

641646
**Available adapters:**
@@ -674,6 +679,13 @@ opengap run -d ./my-agent -p "Review my authentication code"
674679
# Run an agent definition against a separate target workspace
675680
opengap run -d ./agents/reviewer --workspace ~/code/my-app -a claude -p "Review this repository"
676681

682+
# Continue the most recent session in that workspace
683+
opengap run -d ./agents/reviewer --workspace ~/code/my-app -a claude -c -p "Now fix the issues you found"
684+
685+
# Pin a session ID on first run, resume it later
686+
opengap run -d ./my-agent --session-id 3f9f74a6-6b7c-4a3e-9e1d-2f1f0a9b8c7d -p "Start the audit"
687+
opengap run -d ./my-agent --resume 3f9f74a6-6b7c-4a3e-9e1d-2f1f0a9b8c7d -p "Continue the audit"
688+
677689
# Run a specific branch, force refresh
678690
opengap run -r https://github.com/user/agent -b develop --refresh
679691

src/commands/run.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ interface RunOptions {
2525
prompt?: string;
2626
dir?: string;
2727
workspace?: string;
28+
continue?: boolean;
29+
resume?: string;
30+
sessionId?: string;
2831
}
2932

3033
export const runCommand = new Command('run')
@@ -37,6 +40,9 @@ export const runCommand = new Command('run')
3740
.option('-p, --prompt <query>', 'Initial prompt to send to the agent')
3841
.option('-d, --dir <dir>', 'Use local directory instead of git URL')
3942
.option('-w, --workspace <dir>', 'Working directory for the spawned agent process')
43+
.option('-c, --continue', 'Continue the most recent session in the working directory (claude adapter)', false)
44+
.option('--resume <sessionId>', 'Resume a specific session by ID (claude adapter)')
45+
.option('--session-id <uuid>', 'Start with a specific session ID so it can be resumed later (claude adapter)')
4046
.action(async (options: RunOptions) => {
4147
let agentDir: string;
4248
let cleanup: (() => void) | undefined;
@@ -96,11 +102,24 @@ export const runCommand = new Command('run')
96102
}
97103
divider();
98104

105+
// Session flags are claude-adapter-only — warn instead of silently dropping
106+
if ((options.continue || options.resume || options.sessionId) && options.adapter !== 'claude') {
107+
error(`--continue / --resume / --session-id are only supported by the claude adapter (got: ${options.adapter})`);
108+
if (cleanup) cleanup();
109+
process.exit(1);
110+
}
111+
99112
// Run with selected adapter
100113
try {
101114
switch (options.adapter) {
102115
case 'claude':
103-
runWithClaude(agentDir, manifest, { prompt: options.prompt, workspace: options.workspace });
116+
runWithClaude(agentDir, manifest, {
117+
prompt: options.prompt,
118+
workspace: options.workspace,
119+
continue: options.continue,
120+
resume: options.resume,
121+
sessionId: options.sessionId,
122+
});
104123
break;
105124
case 'openai':
106125
runWithOpenAI(agentDir, manifest, { workspace: options.workspace });

src/runners/claude.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import { error, info, warn } from '../utils/format.js';
1212
export interface ClaudeRunOptions {
1313
prompt?: string;
1414
workspace?: string;
15+
/** Continue the most recent Claude Code conversation in the working directory. */
16+
continue?: boolean;
17+
/** Resume a specific Claude Code session by its session ID. */
18+
resume?: string;
19+
/** Start the conversation with a specific session ID (UUID) so it can be resumed later. */
20+
sessionId?: string;
1521
}
1622

1723
export function runWithClaude(agentDir: string, manifest: AgentManifest, options: ClaudeRunOptions = {}): void {
@@ -72,6 +78,31 @@ export function runWithClaude(agentDir: string, manifest: AgentManifest, options
7278
tmpFiles.push(settingsFile);
7379
}
7480

81+
// Session continuation — maps to Claude Code's native session flags.
82+
// --continue resumes the most recent conversation in the working directory,
83+
// so it pairs with --workspace: the session is looked up in runCwd.
84+
if (options.continue && options.resume) {
85+
error('--continue and --resume are mutually exclusive');
86+
process.exitCode = 1;
87+
return;
88+
}
89+
if (options.continue) {
90+
args.push('--continue');
91+
info('Continuing most recent Claude Code session in the working directory');
92+
}
93+
if (options.resume) {
94+
args.push('--resume', options.resume);
95+
info(`Resuming Claude Code session ${options.resume}`);
96+
}
97+
if (options.sessionId) {
98+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(options.sessionId)) {
99+
error(`--session-id must be a valid UUID, got: ${options.sessionId}`);
100+
process.exitCode = 1;
101+
return;
102+
}
103+
args.push('--session-id', options.sessionId);
104+
}
105+
75106
// Initial prompt (print mode)
76107
if (options.prompt) {
77108
args.push('-p', options.prompt);

0 commit comments

Comments
 (0)