How the Multi-Session Inbox and Archive Workflow Works in Craft Agents
The multi-session inbox and archive workflow in Craft Agents uses a dual-filter system combining sessionStatus categories and an isArchived boolean flag to separate active conversations from long-term storage.
Craft Agents OSS organizes every conversation into persistent session folders under a workspace directory. The workflow distinguishes between active work in the Inbox and long-term storage in the Archive using metadata flags stored in each session's header, enabling users to manage hundreds of conversations without clutter.
Session Storage Architecture
Each conversation ("session") resides in a dedicated folder at {workspaceRootPath}/sessions/{id}. This folder contains a session.jsonl file holding the transcript and a metadata header (see SessionStorage). The system tracks two critical pieces of metadata to power the inbox and archive views:
sessionStatus(string): A user-controlled status ID (e.g.,todo,done) defined inpackages/shared/src/statuses/types.tsisArchived(boolean): An explicit flag that moves a session to the Archive view, accompanied by anarchivedAttimestamp
The status configuration defines each status as either open or closed, and the helper getStatusCategory maps status IDs to these categories.
The Dual-Filter System
The UI distinguishes between Inbox and Archive through two orthogonal filters:
Status Category Filtering
The sessionStatus field determines whether a session is considered "active work" based on the workspace-wide status configuration. Statuses like todo or in-progress map to the open category, while done maps to closed.
Archive Flag Filtering
The isArchived boolean in packages/shared/src/sessions/types.ts (lines 80-82) explicitly moves sessions out of the active pool. When true, the session appears only in the Archive view regardless of its status category.
How Inbox and Archive Filtering Works
The core filtering functions live in packages/shared/src/sessions/storage.ts:
// Inbox – open category, excludes archived
export function listInboxSessions(workspaceRootPath: string): SessionMetadata[] {
return listActiveSessions(workspaceRootPath).filter(s => {
const category = getStatusCategory(workspaceRootPath, s.sessionStatus || 'todo');
return category === 'open';
});
}
// Archived – explicit flag
export function listArchivedSessions(workspaceRootPath: string): SessionMetadata[] {
return listSessions(workspaceRootPath).filter(s => s.isArchived === true);
}
The workflow follows this hierarchy:
listActiveSessionsfilters out any session whereisArchivedis true (lines 60-63 instorage.ts)listInboxSessionsfurther filters active sessions by theopencategory usinggetStatusCategory(lines 44-48)listArchivedSessionsretrieves only sessions whereisArchived === true
Archiving and Unarchiving Operations
When a user clicks "Archive" in the UI, the event processor handler in apps/electron/src/renderer/event-processor/handlers/session.ts updates the session header:
// Line 717 – Archiving a session
session: { ...session, isArchived: true, archivedAt: Date.now() },
To restore a session, the handler clears the flag at line 734:
// Line 734 – Unarchiving a session
session: { ...session, isArchived: false, archivedAt: undefined },
Because these flags are stored in the session header (SessionHeader), the archival state persists across application restarts. The UI component SessionList.tsx reads these lists via listInboxSessions and listArchivedSessions to render the appropriate views.
Practical Implementation
Here is how to interact with the inbox and archive workflow programmatically:
import { listInboxSessions, listArchivedSessions, setSessionStatus } from '@/shared/sessions';
// 1️⃣ Get the inbox for the current workspace
const inbox = listInboxSessions('/my/workspace');
console.log('Inbox sessions:', inbox.map(s => s.id));
// 2️⃣ Archive a session (e.g., user clicks “Archive”)
function archiveSession(workspace: string, sessionId: string) {
// Load the session header, modify the flag and write back
const header = readSessionHeader(workspace, sessionId);
header.isArchived = true;
header.archivedAt = Date.now();
writeSessionHeader(workspace, sessionId, header);
}
// 3️⃣ Move a session to a closed status (e.g., “done”)
async function closeSession(workspace: string, sessionId: string) {
await setSessionStatus(workspace, sessionId, 'done'); // “done” is a closed status
}
// 4️⃣ List all archived sessions
const archived = listArchivedSessions('/my/workspace');
console.log('Archived:', archived.map(s => s.id));
Summary
- Craft Agents stores sessions in
{workspaceRootPath}/sessions/{id}with metadata headers containingsessionStatusandisArchivedflags - The Inbox displays active sessions where
isArchivedis false and the status category isopen - The Archive displays only sessions where
isArchivedis true, regardless of status - Archiving sets
isArchived: trueand recordsarchivedAt, while unarchiving clears both fields - Status categories (open/closed) provide workflow organization within the active pool, while the archive flag provides long-term storage separation
Frequently Asked Questions
What determines if a session appears in the Inbox?
A session appears in the Inbox only if it is not archived (isArchived !== true) and its sessionStatus maps to the open category via the getStatusCategory function. This means sessions marked with statuses like todo or in-progress appear in the Inbox, while sessions with closed statuses or the isArchived flag set to true are excluded.
How does archiving differ from changing session status?
Changing a session status to a closed category (e.g., done) removes it from the Inbox but keeps it in the active sessions list, meaning it still appears in general session listings. Archiving sets the isArchived boolean to true, which removes the session from both the Inbox and active lists entirely, placing it exclusively in the Archive view with a recorded archivedAt timestamp.
Where is the archive state persisted?
The archive state is stored in the session's metadata header within the workspace directory structure. Specifically, the isArchived boolean and archivedAt timestamp are written to the session header file in {workspaceRootPath}/sessions/{id}, ensuring the state survives application restarts and workspace migrations.
Can archived sessions be restored to the Inbox?
Yes, archived sessions can be restored by clearing the isArchived flag. When the event processor handles an unarchive action (line 734 in apps/electron/src/renderer/event-processor/handlers/session.ts), it sets isArchived: false and archivedAt: undefined. The session then reappears in the Inbox if its status category is still open, or in the active sessions list if the status is closed.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →