use clap::{Parser, Subcommand};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Parser)]
#[command(name = "pcx")]
#[command(version = VERSION)]
#[command(about = "Post-Cortex - Intelligent conversation memory system")]
#[command(
long_about = "Post-Cortex unified MCP server supporting stdio and SSE transports.\n\n\
When run without arguments, starts in stdio mode (for MCP clients).\n\
The daemon is auto-started in background if not already running."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand)]
pub enum Commands {
Start {
#[arg(long)]
daemon: bool,
#[arg(long, short, default_value = "3737")]
port: u16,
#[arg(long, default_value = "127.0.0.1")]
host: String,
},
Status,
Stop,
Init,
#[command(long_about = "Interactive project setup wizard.\n\n\
Creates a session, workspace, and generates .claude/ configuration files\n\
(CLAUDE.md, settings.json, hooks) with the correct IDs.\n\n\
EXAMPLES:\n\n\
Interactive setup:\n\
$ pcx setup\n\n\
Non-interactive with defaults:\n\
$ pcx setup --name my-project --non-interactive")]
Setup {
#[arg(long)]
name: Option<String>,
#[arg(long)]
non_interactive: bool,
},
VectorizeAll,
Workspace {
#[command(subcommand)]
action: WorkspaceAction,
},
Session {
#[command(subcommand)]
action: SessionAction,
},
#[command(long_about = "Export sessions and workspaces to a JSON file.\n\n\
Supports optional compression (gzip, zstd) for smaller file sizes.\n\
The compression type is auto-detected from the file extension.\n\n\
EXAMPLES:\n\n\
Full export (all sessions and workspaces):\n\
$ pcx export --output backup.json\n\n\
Export with gzip compression:\n\
$ pcx export --output backup.json.gz\n\n\
Export with zstd compression (fastest):\n\
$ pcx export --output backup.json.zst\n\n\
Export specific session:\n\
$ pcx export --output session.json --session <uuid>\n\n\
Export workspace with all its sessions:\n\
$ pcx export --output workspace.json --workspace <uuid>\n\n\
Pretty-printed JSON for debugging:\n\
$ pcx export --output backup.json --pretty\n\n\
Force overwrite without asking:\n\
$ pcx export --output backup.json.gz --force")]
Export {
#[arg(short, long, value_name = "FILE")]
output: Option<String>,
#[arg(short, long, value_name = "TYPE")]
compress: Option<String>,
#[arg(long, value_name = "UUID")]
session: Option<Vec<String>>,
#[arg(long, value_name = "UUID")]
workspace: Option<String>,
#[arg(long)]
checkpoints: bool,
#[arg(long)]
pretty: bool,
#[arg(long, short = 'f')]
force: bool,
},
#[command(long_about = "Import sessions and workspaces from an export file.\n\n\
Supports automatic decompression based on file extension.\n\
Use --list to preview contents before importing.\n\n\
EXAMPLES:\n\n\
List contents without importing:\n\
$ pcx import --input backup.json --list\n\n\
Import everything:\n\
$ pcx import --input backup.json\n\n\
Import from compressed file:\n\
$ pcx import --input backup.json.gz\n\n\
Import specific session only:\n\
$ pcx import --input backup.json --session <uuid>\n\n\
Import and skip existing (no errors):\n\
$ pcx import --input backup.json --skip-existing\n\n\
Import and overwrite existing:\n\
$ pcx import --input backup.json --overwrite")]
Import {
#[arg(short, long, value_name = "FILE")]
input: String,
#[arg(long, value_name = "UUID")]
session: Option<Vec<String>>,
#[arg(long, value_name = "UUID")]
workspace: Option<String>,
#[arg(long)]
skip_existing: bool,
#[arg(long)]
overwrite: bool,
#[arg(long)]
list: bool,
},
#[cfg(feature = "surrealdb-storage")]
#[command(long_about = "Migrate data from one storage backend to another.\n\n\
Currently supports migration from RocksDB to SurrealDB (local or remote).\n\n\
EXAMPLES:\n\n\
Migrate to local SurrealDB:\n\
$ pcx migrate --from rocksdb --to surrealdb\n\n\
Migrate to remote SurrealDB (Docker):\n\
$ pcx migrate --from rocksdb --to surrealdb \\\n\
--remote-endpoint localhost:8000 \\\n\
--username root --password root\n\n\
Dry run (show what would be migrated):\n\
$ pcx migrate --from rocksdb --to surrealdb --dry-run")]
Migrate {
#[arg(long, value_name = "BACKEND")]
from: String,
#[arg(long, value_name = "BACKEND")]
to: String,
#[arg(long, value_name = "PATH")]
source_path: Option<String>,
#[arg(long, value_name = "PATH")]
target_path: Option<String>,
#[arg(long, value_name = "ENDPOINT")]
remote_endpoint: Option<String>,
#[arg(long, value_name = "USER")]
username: Option<String>,
#[arg(long, value_name = "PASS")]
password: Option<String>,
#[arg(long)]
dry_run: bool,
},
}
#[derive(Subcommand)]
pub enum WorkspaceAction {
#[command(
long_about = "Create a new workspace for organizing related sessions.\n\n\
EXAMPLES:\n\n\
$ pcx workspace create my-project \"Main project workspace\""
)]
Create {
#[arg(value_name = "NAME")]
name: String,
#[arg(default_value = "", value_name = "DESC")]
description: String,
},
#[command(long_about = "Delete a workspace by ID.\n\n\
Note: This does NOT delete the sessions in the workspace.\n\n\
EXAMPLES:\n\n\
$ pcx workspace delete <uuid>")]
Delete {
#[arg(value_name = "UUID")]
id: String,
},
#[command(long_about = "List all workspaces with their session counts.")]
List,
#[command(
long_about = "Attach a session to a workspace with a specific role.\n\n\
ROLES:\n\
- primary: Main session for this workspace\n\
- related: Related/peer session (default)\n\
- dependency: External dependency documentation\n\
- shared: Shared across multiple workspaces\n\n\
EXAMPLES:\n\n\
$ pcx workspace attach <workspace-uuid> <session-uuid>\n\
$ pcx workspace attach <workspace-uuid> <session-uuid> primary"
)]
Attach {
#[arg(value_name = "WORKSPACE_UUID")]
workspace_id: String,
#[arg(value_name = "SESSION_UUID")]
session_id: String,
#[arg(default_value = "related", value_name = "ROLE")]
role: String,
},
}
#[derive(Subcommand)]
pub enum SessionAction {
#[command(
long_about = "Create a new session for storing conversation context.\n\n\
EXAMPLES:\n\n\
$ pcx session create\n\
$ pcx session create my-session\n\
$ pcx session create my-session \"Session description\""
)]
Create {
#[arg(value_name = "NAME")]
name: Option<String>,
#[arg(value_name = "DESC")]
description: Option<String>,
},
#[command(long_about = "Delete a session and all its data.\n\n\
WARNING: This permanently deletes all context updates in the session.\n\n\
EXAMPLES:\n\n\
$ pcx session delete <uuid>")]
Delete {
#[arg(value_name = "UUID")]
id: String,
},
#[command(long_about = "List all sessions with their workspace associations.")]
List,
}