Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 4 additions & 21 deletions apps/cli/src/commands/import/claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ export const importClaudeCommand = command({
long: 'session-id',
description: 'UUID of the Claude Code session to import',
}),
discover: option({
type: optional(string),
long: 'discover',
description: 'Discovery mode: "latest" to import the most recent session',
}),
projectPath: option({
type: optional(string),
long: 'project-path',
Expand All @@ -44,7 +39,7 @@ export const importClaudeCommand = command({
description: 'List available sessions instead of importing',
}),
},
handler: async ({ sessionId, discover, projectPath, output, projectsDir, list }) => {
handler: async ({ sessionId, projectPath, output, projectsDir, list }) => {
if (list) {
const sessions = await discoverClaudeSessions({
projectPath,
Expand Down Expand Up @@ -81,22 +76,10 @@ export const importClaudeCommand = command({
process.exit(1);
}
sessionFilePath = sessions[0].filePath;
} else if (discover === 'latest') {
const sessions = await discoverClaudeSessions({
projectPath,
projectsDir,
latest: true,
});

if (sessions.length === 0) {
console.error('Error: no Claude Code sessions found.');
process.exit(1);
}
sessionFilePath = sessions[0].filePath;
sessionId = sessions[0].sessionId;
console.log(`Discovered latest session: ${sessionId}`);
} else {
console.error('Error: specify --session-id <uuid> or --discover latest to select a session.');
console.error(
'Error: specify --session-id <uuid> to select a session. Use --list to see available sessions.',
);
process.exit(1);
}

Expand Down
40 changes: 21 additions & 19 deletions apps/cli/src/commands/import/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export const importCodexCommand = command({
name: 'codex',
description: 'Import a Codex CLI session transcript for offline grading',
args: {
discover: option({
sessionId: option({
type: optional(string),
long: 'discover',
description: 'Discovery mode: "latest" to import the most recent session',
long: 'session-id',
description: 'UUID of the Codex CLI session to import',
}),
date: option({
type: optional(string),
Expand All @@ -38,7 +38,7 @@ export const importCodexCommand = command({
description: 'List available sessions instead of importing',
}),
},
handler: async ({ discover, date, output, sessionsDir, list }) => {
handler: async ({ sessionId, date, output, sessionsDir, list }) => {
if (list) {
const sessions = await discoverCodexSessions({
date,
Expand All @@ -59,25 +59,27 @@ export const importCodexCommand = command({
return;
}

if (discover !== 'latest') {
console.error('Error: specify --discover latest to select a session.');
process.exit(1);
}

const sessions = await discoverCodexSessions({
date,
sessionsDir,
latest: true,
});
let session: Awaited<ReturnType<typeof discoverCodexSessions>>[number];

if (sessions.length === 0) {
console.error('Error: no Codex CLI sessions found.');
if (sessionId) {
const sessions = await discoverCodexSessions({
date,
sessionsDir,
limit: 100,
});
const match = sessions.find((s) => s.sessionId === sessionId);
if (!match) {
console.error(`Error: session ${sessionId} not found.`);
process.exit(1);
}
session = match;
} else {
console.error(
'Error: specify --session-id <uuid> to select a session. Use --list to see available sessions.',
);
process.exit(1);
}

const session = sessions[0];
console.log(`Discovered latest session: ${session.filename}`);

// Parse the session
const rawJsonl = await readTranscriptFile(session.filePath);
const transcript = parseCodexSession(rawJsonl);
Expand Down
24 changes: 4 additions & 20 deletions apps/cli/src/commands/import/copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ export const importCopilotCommand = command({
long: 'session-id',
description: 'UUID of the Copilot CLI session to import',
}),
discover: option({
type: optional(string),
long: 'discover',
description: 'Discovery mode: "latest" to import the most recent session',
}),
output: option({
type: optional(string),
long: 'output',
Expand All @@ -34,7 +29,7 @@ export const importCopilotCommand = command({
description: 'List available sessions instead of importing',
}),
},
handler: async ({ sessionId, discover, output, sessionStateDir, list }) => {
handler: async ({ sessionId, output, sessionStateDir, list }) => {
if (list) {
const sessions = await discoverCopilotSessions({
sessionStateDir,
Expand Down Expand Up @@ -70,21 +65,10 @@ export const importCopilotCommand = command({
}
sessionDir = match.sessionDir;
resolvedSessionId = sessionId;
} else if (discover === 'latest') {
const sessions = await discoverCopilotSessions({
sessionStateDir,
limit: 1,
});

if (sessions.length === 0) {
console.error('Error: no Copilot CLI sessions found.');
process.exit(1);
}
sessionDir = sessions[0].sessionDir;
resolvedSessionId = sessions[0].sessionId;
console.log(`Discovered latest session: ${resolvedSessionId}`);
} else {
console.error('Error: specify --session-id <uuid> or --discover latest to select a session.');
console.error(
'Error: specify --session-id <uuid> to select a session. Use --list to see available sessions.',
);
process.exit(1);
}

Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/content/docs/docs/evaluation/running-evals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,9 @@ This is the same interface that agent-orchestrated evals use — the EVAL.yaml t
Grade existing agent sessions without re-running them. Import a transcript, then run deterministic evaluators:

```bash
# Import a Claude Code session
agentv import claude --discover latest
# List sessions and import one
agentv import claude --list
agentv import claude --session-id <uuid>

# Run evaluators against the imported transcript
agentv eval evals/my-eval.yaml --transcript .agentv/transcripts/claude-<id>.jsonl
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/content/docs/docs/guides/agent-skills-evals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ Grade existing agent sessions offline using `agentv import` to convert transcrip

```bash
# Import a Claude Code session transcript
agentv import claude --discover latest
agentv import claude --list
agentv import claude --session-id <uuid>

# Run deterministic evaluators against the imported transcript
agentv eval evals.json --target copilot-log
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ Or grade existing sessions offline (no API keys required):

```bash
# Import a Claude Code session transcript
agentv import claude --discover latest
agentv import claude --list
agentv import claude --session-id <uuid>

# Run deterministic evaluators against the imported transcript
agentv eval evals.json --target copilot-log
Expand Down
74 changes: 56 additions & 18 deletions apps/web/src/content/docs/docs/tools/import.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ The `import` command converts agent session transcripts into AgentV's `Message[]
| Provider | Command | Source |
|----------|---------|--------|
| Claude Code | `agentv import claude` | `~/.claude/projects/<path>/<uuid>.jsonl` |

Codex and Copilot importers are planned for future releases.
| Codex CLI | `agentv import codex` | `~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl` |
| Copilot CLI | `agentv import copilot` | `~/.copilot/session-state/<uuid>/events.jsonl` |

## `import claude`

Import a Claude Code session transcript.

### Discover available sessions
### List available sessions

```bash
agentv import claude --list
Expand All @@ -35,12 +35,6 @@ Found 5 session(s):
ed8b8c62-4414-49fb-8739-006d809c8588 3h ago -home-user-other-project
```

### Import latest session

```bash
agentv import claude --discover latest
```

### Import a specific session

```bash
Expand All @@ -50,27 +44,68 @@ agentv import claude --session-id 4c4f9e4e-e6f1-490b-a1b1-9aef543ebf22
### Filter by project path

```bash
agentv import claude --discover latest --project-path /home/user/myproject
agentv import claude --list --project-path /home/user/myproject
```

### Custom output path

```bash
agentv import claude --discover latest -o transcripts/my-session.jsonl
agentv import claude --session-id <uuid> -o transcripts/my-session.jsonl
```

Default output: `.agentv/transcripts/claude-<session-id-short>.jsonl`

## `import codex`

Import a Codex CLI session transcript.

### List available sessions

```bash
agentv import codex --list
```

### Import a specific session

```bash
agentv import codex --session-id 019d5cff-9f02-7bc3-8f98-2071ba17ef0e
```

## `import copilot`

Import a Copilot CLI session transcript.

### List available sessions

```bash
agentv import copilot --list
```

### Import a specific session

```bash
agentv import copilot --session-id 9ca6d90c-1d80-40d1-b805-c59ee31fc007
```

## Options

All three providers share the same core flags:

| Flag | Description |
|------|-------------|
| `--session-id <uuid>` | Import a specific session by UUID |
| `--discover latest` | Import the most recent session |
| `--project-path <path>` | Filter sessions by project path |
| `--output, -o <path>` | Custom output file path |
| `--projects-dir <dir>` | Override `~/.claude/projects` directory |
| `--list` | List available sessions instead of importing |
| `--output, -o <path>` | Custom output file path |

Provider-specific flags:

| Flag | Provider | Description |
|------|----------|-------------|
| `--project-path <path>` | Claude | Filter sessions by project path |
| `--projects-dir <dir>` | Claude | Override `~/.claude/projects` directory |
| `--date <YYYY-MM-DD>` | Codex | Filter sessions by date |
| `--sessions-dir <dir>` | Codex | Override `~/.codex/sessions` directory |
| `--session-state-dir <dir>` | Copilot | Override `~/.copilot/session-state` directory |

## Output Format

Expand Down Expand Up @@ -101,10 +136,13 @@ Token usage is aggregated from the final cumulative value per LLM request. Durat
Import a session, then run evaluators against it:

```bash
# 1. Import the latest Claude Code session
agentv import claude --discover latest
# 1. List sessions and pick one
agentv import claude --list

# 2. Import a session by ID
agentv import claude --session-id 4c4f9e4e-e6f1-490b-a1b1-9aef543ebf22

# 2. Run evaluators against the imported transcript
# 3. Run evaluators against the imported transcript
agentv eval evals/my-eval.yaml --transcript .agentv/transcripts/claude-4c4f9e4e.jsonl
```

Expand Down
6 changes: 0 additions & 6 deletions examples/features/import-claude/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ claude -p "List all TypeScript files in this project"

### 2. Import the session transcript

```bash
agentv import claude --discover latest -o transcripts/session.jsonl
```

Or import a specific session:

```bash
# List available sessions
agentv import claude --list
Expand Down
2 changes: 1 addition & 1 deletion plugins/agentv-dev/skills/agentv-eval-writer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ agentv eval <file.yaml> --otel-file traces/eval.otlp.json
agentv eval assert <grader-name> --agent-output "..." --agent-input "..."

# Import agent transcripts for offline grading
agentv import claude --discover latest
agentv import claude --session-id <uuid>

# Re-run only execution errors from a previous run
agentv eval <file.yaml> --retry-errors .agentv/results/runs/<timestamp>/index.jsonl
Expand Down
Loading