1# RFC: Session Import and Export
  2
  3## Summary
  4
  5This RFC proposes a comprehensive system for importing and exporting conversation sessions in Crush.
  6
  7## Background
  8
  9Crush manages conversations through a hierarchical session system where:
 10- Sessions contain metadata (title, token counts, cost, timestamps) 
 11- Sessions can have parent-child relationships (nested conversations)
 12- Messages within sessions have structured content parts (text, tool calls, reasoning, etc.)
 13- The current implementation provides export functionality but lacks import capabilities
 14
 15The latest commit introduced three key commands:
 16- `crush sessions list` - List sessions in various formats
 17- `crush sessions export` - Export all sessions and metadata  
 18- `crush sessions export-conversation <session-id>` - Export a single conversation with messages
 19
 20## Motivation
 21
 22Users need to:
 231. Share conversations with others
 242. Use conversation logs for debugging
 253. Archive and analyze conversation history
 264. Export data for external tools
 27
 28## Detailed Design
 29
 30### Core Data Model
 31
 32The session export format builds on the existing session structure:
 33
 34```go
 35type Session struct {
 36    ID               string  `json:"id"`
 37    ParentSessionID  string  `json:"parent_session_id,omitempty"`
 38    Title            string  `json:"title"`
 39    MessageCount     int64   `json:"message_count"`
 40    PromptTokens     int64   `json:"prompt_tokens"`
 41    CompletionTokens int64   `json:"completion_tokens"`
 42    Cost             float64 `json:"cost"`
 43    CreatedAt        int64   `json:"created_at"`
 44    UpdatedAt        int64   `json:"updated_at"`
 45    SummaryMessageID string  `json:"summary_message_id,omitempty"`
 46}
 47
 48type SessionWithChildren struct {
 49    Session
 50    Children []SessionWithChildren `json:"children,omitempty"`
 51}
 52```
 53
 54### Proposed Command Interface
 55
 56#### Export Commands (Already Implemented)
 57```bash
 58# List sessions in various formats
 59crush sessions list [--format text|json|yaml|markdown]
 60
 61# Export all sessions with metadata
 62crush sessions export [--format json|yaml|markdown]
 63
 64# Export single conversation with full message history
 65crush sessions export-conversation <session-id> [--format markdown|json|yaml]
 66```
 67
 68#### New Import Commands
 69
 70```bash
 71# Import sessions from a file
 72crush sessions import <file> [--format json|yaml] [--dry-run] 
 73
 74# Import a single conversation
 75crush sessions import-conversation <file> [--format json|yaml|markdown] 
 76
 77```
 78
 79#### Enhanced Inspection Commands
 80
 81```bash
 82# Search sessions by criteria
 83crush sessions search [--title <pattern>] [--text <text>] [--format text|json]
 84
 85# Show session statistics
 86crush sessions stats [--format text|json] [--group-by day|week|month]
 87
 88# Show statistics for a single session
 89crush sessions stats <session-id> [--format text|json] 
 90```
 91
 92### Import/Export Formats
 93
 94#### Full Export Format (JSON)
 95```json
 96{
 97  "version": "1.0",
 98  "exported_at": "2025-01-27T10:30:00Z",
 99  "total_sessions": 15,
100  "sessions": [
101    {
102      "id": "session-123",
103      "parent_session_id": "",
104      "title": "API Design Discussion",
105      "message_count": 8,
106      "prompt_tokens": 1250,
107      "completion_tokens": 890,
108      "cost": 0.0234,
109      "created_at": 1706356200,
110      "updated_at": 1706359800,
111      "children": [
112        {
113          "id": "session-124",
114          "parent_session_id": "session-123",
115          "title": "Implementation Details",
116          "message_count": 4,
117          "prompt_tokens": 650,
118          "completion_tokens": 420,
119          "cost": 0.0145,
120          "created_at": 1706359900,
121          "updated_at": 1706361200
122        }
123      ]
124    }
125  ]
126}
127```
128
129#### Conversation Export Format (JSON)
130```json
131{
132  "version": "1.0",
133  "session": {
134    "id": "session-123",
135    "title": "API Design Discussion",
136    "created_at": 1706356200,
137    "message_count": 3
138  },
139  "messages": [
140    {
141      "id": "msg-001",
142      "session_id": "session-123", 
143      "role": "user",
144      "parts": [
145        {
146          "type": "text",
147          "data": {
148            "text": "Help me design a REST API for user management"
149          }
150        }
151      ],
152      "created_at": 1706356200
153    },
154    {
155      "id": "msg-002",
156      "session_id": "session-123",
157      "role": "assistant",
158      "model": "gpt-4",
159      "provider": "openai",
160      "parts": [
161        {
162          "type": "text", 
163          "data": {
164            "text": "I'll help you design a REST API for user management..."
165          }
166        },
167        {
168          "type": "finish",
169          "data": {
170            "reason": "stop",
171            "time": 1706356230
172          }
173        }
174      ],
175      "created_at": 1706356220
176    }
177  ]
178}
179```
180
181### API Implementation
182
183#### Import Service Interface
184```go
185type ImportService interface {
186    // Import sessions from structured data
187    ImportSessions(ctx context.Context, data ImportData, opts ImportOptions) (ImportResult, error)
188    
189    // Import single conversation
190    ImportConversation(ctx context.Context, data ConversationData, opts ImportOptions) (Session, error)
191    
192    // Validate import data without persisting
193    ValidateImport(ctx context.Context, data ImportData) (ValidationResult, error)
194}
195
196type ImportOptions struct {
197    ConflictStrategy ConflictStrategy // skip, merge, replace
198    DryRun          bool
199    ParentSessionID string // For conversation imports
200    PreserveIDs     bool   // Whether to preserve original IDs
201}
202
203type ConflictStrategy string
204
205const (
206    ConflictSkip    ConflictStrategy = "skip"    // Skip existing sessions
207    ConflictMerge   ConflictStrategy = "merge"   // Merge with existing
208    ConflictReplace ConflictStrategy = "replace" // Replace existing
209)
210
211type ImportResult struct {
212    TotalSessions    int               `json:"total_sessions"`
213    ImportedSessions int               `json:"imported_sessions"`
214    SkippedSessions  int               `json:"skipped_sessions"`
215    Errors          []ImportError     `json:"errors,omitempty"`
216    SessionMapping  map[string]string `json:"session_mapping"` // old_id -> new_id
217}
218```
219
220#### Enhanced Export Service
221```go
222type ExportService interface {
223    // Export sessions with filtering
224    ExportSessions(ctx context.Context, opts ExportOptions) ([]SessionWithChildren, error)
225    
226    // Export conversation with full message history  
227    ExportConversation(ctx context.Context, sessionID string, opts ExportOptions) (ConversationExport, error)
228    
229    // Search and filter sessions
230    SearchSessions(ctx context.Context, criteria SearchCriteria) ([]Session, error)
231    
232    // Get session statistics
233    GetStats(ctx context.Context, opts StatsOptions) (SessionStats, error)
234}
235
236type ExportOptions struct {
237    Format          string    // json, yaml, markdown
238    IncludeMessages bool      // Include full message content
239    DateRange       DateRange // Filter by date range
240    SessionIDs      []string  // Export specific sessions
241}
242
243type SearchCriteria struct {
244    TitlePattern    string
245    DateRange       DateRange
246    MinCost         float64
247    MaxCost         float64
248    ParentSessionID string
249    HasChildren     *bool
250}
251```
252
253## Implementation Status
254
255The proposed session import/export functionality has been implemented as a prototype as of July 2025.
256
257### Implemented Commands
258
259All new commands have been added to `internal/cmd/sessions.go`:
260
261- **Import**: `crush sessions import <file> [--format json|yaml] [--dry-run]`
262  - Supports hierarchical session imports with parent-child relationships
263  - Generates new UUIDs to avoid conflicts
264  - Includes validation and dry-run capabilities
265
266- **Import Conversation**: `crush sessions import-conversation <file> [--format json|yaml]`
267  - Imports single conversations with full message history
268  - Preserves all message content parts and metadata
269
270- **Search**: `crush sessions search [--title <pattern>] [--text <text>] [--format text|json]`
271  - Case-insensitive title search and message content search
272  - Supports combined search criteria with AND logic
273
274- **Stats**: `crush sessions stats [--format text|json] [--group-by day|week|month]`
275  - Comprehensive usage statistics (sessions, messages, tokens, costs)
276  - Time-based grouping with efficient database queries
277
278### Database Changes
279
280Added new SQL queries in `internal/db/sql/sessions.sql`:
281- Search queries for title and message content filtering
282- Statistics aggregation queries with time-based grouping
283- All queries optimized for performance with proper indexing
284
285### Database Schema Considerations
286
287The current schema supports the import/export functionality. Additional indexes may be needed for search performance:
288
289```sql
290-- Optimize session searches by date and cost
291CREATE INDEX idx_sessions_created_at ON sessions(created_at);
292CREATE INDEX idx_sessions_cost ON sessions(cost);
293CREATE INDEX idx_sessions_title ON sessions(title COLLATE NOCASE);
294
295-- Optimize message searches by session
296CREATE INDEX idx_messages_session_created ON messages(session_id, created_at);
297```