Skip to main content

ADR-009: CODI Command Interface (v4) - Part 2: Technical Implementation

Document Specification Block

Document: ADR-009-v4-codi-command-interface-part2-technical
Version: 1.0.0
Purpose: Provide complete technical implementation blueprint for CODI command interface
Audience: Engineering teams, AI agents implementing the system, architects
Date Created: 2025-08-27
Date Modified: 2025-08-31
Status: DRAFT

Table of Contents

8. Implementation Blueprint 🔴 REQUIRED

8.1 Architecture Diagram

8.2 Dependencies

# cargo.toml for CODI
[package]
name = "codi"
version = "1.0.0"
edition = "2021"

[dependencies]
clap = { version = "4.4", features = ["derive"] }
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
anyhow = "1.0"
dirs = "5.0"
rusqlite = { version = "0.30", features = ["bundled"] }
reqwest = { version = "0.11", features = ["json"] }
tracing = "0.1"
tracing-subscriber = "0.3"
uuid = { version = "1.6", features = ["v4"] }
chrono = { version = "0.4", features = ["serde"] }

# MCP support
mcp-sdk = "0.1" # Hypothetical - real crate TBD

8.3 Core Implementation

// src/main.rs - CODI entry point
use clap::{Parser, Subcommand};
use anyhow::Result;

#[derive(Parser)]
#[command(name = "codi")]
#[command(about = "CODI - Your friendly CODITECT assistant")]
struct Cli {
#[command(subcommand)]
command: Commands,

#[arg(long, global = true)]
verbose: bool,
}

#[derive(Subcommand)]
enum Commands {
/// Show help and available commands
Help {
#[arg(value_name = "COMMAND")]
command: Option<String>,
},

/// Log an entry using codi-log system
Log {
action: String,
message: String,
#[arg(long)]
impact: Option<String>,
#[arg(long)]
files: Option<String>,
},

/// Manage your CODITECT session
Session {
#[command(subcommand)]
action: SessionCommands,
},

/// Work with ADRs
Adr {
#[command(subcommand)]
action: AdrCommands,
},

/// Deploy your application
Deploy {
target: String,
#[arg(long)]
env: Option<String>,
},

/// AI agent operations
Agent {
#[command(subcommand)]
action: AgentCommands,
},
}

// src/lib.rs - Core CODI library
pub mod commands;
pub mod mcp;
pub mod state;
pub mod api;

use std::path::PathBuf;

pub struct Codi {
config: Config,
state_manager: state::StateManager,
api_client: api::ApiClient,
mcp_server: mcp::Server,
}

impl Codi {
pub fn new() -> Result<Self> {
let config_path = Self::find_codi_root()?.join("config.toml");
let config = Config::load(&config_path)?;

let state_manager = state::StateManager::new(&config.state_path)?;
let api_client = api::ApiClient::new(&config.api_endpoint)?;
let mcp_server = mcp::Server::new(&config.mcp)?;

Ok(Self {
config,
state_manager,
api_client,
mcp_server,
})
}

fn find_codi_root() -> Result<PathBuf> {
// Walk up directory tree looking for .codi/
let mut path = std::env::current_dir()?;
loop {
let codi_path = path.join(".codi");
if codi_path.exists() {
return Ok(codi_path);
}
if !path.pop() {
anyhow::bail!("Not in a CODITECT project (no .codi directory found)");
}
}
}
}

8.4 API Specification 🔴 REQUIRED for API changes

// src/api/mod.rs - CODI API client
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct CommandRequest {
pub session_id: String,
pub command: String,
pub args: Vec<String>,
pub context: CommandContext,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CommandResponse {
pub success: bool,
pub output: String,
pub artifacts: Vec<Artifact>,
pub next_suggestions: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CommandContext {
pub user_id: String,
pub project_id: String,
pub workspace: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
}

pub trait CodiApi {
async fn execute_command(&self, req: CommandRequest) -> Result<CommandResponse>;
async fn get_suggestions(&self, partial: &str) -> Result<Vec<String>>;
async fn sync_state(&self, state: LocalState) -> Result<()>;
}

8.5 Data Models 🔴 REQUIRED for data changes

// src/models.rs - Core data structures
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};

#[derive(Debug, Serialize, Deserialize)]
pub struct Session {
pub id: Uuid,
pub started_at: DateTime<Utc>,
pub last_command: Option<DateTime<Utc>>,
pub commands_executed: u32,
pub current_context: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LogEntry {
pub timestamp: DateTime<Utc>,
pub session_id: Uuid,
pub action: String,
pub message: String,
pub impact: Option<String>,
pub files: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CodiConfig {
pub version: String,
pub api_endpoint: String,
pub session: SessionConfig,
pub mcp: McpConfig,
pub features: FeatureFlags,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct McpConfig {
pub enabled: bool,
pub server_port: u16,
pub allowed_tools: Vec<String>,
}

8.6 Configuration

# .codi/config.toml - Default configuration
[codi]
version = "1.0.0"
api_endpoint = "https://api.coditect.com/v1/codi"

[session]
auto_start = true
export_on_end = true
retention_days = 30

[mcp]
enabled = true
server_port = 3333
allowed_tools = ["*"] # or specific list

[features]
ai_suggestions = true
team_sync = true
auto_backup = true

[logging]
level = "info"
file = ".codi/logs/codi.log"

8.7 Logging Implementation Pattern 🔴 REQUIRED per v4.2

// src/logging.rs - CODI logging implementation
use tracing::{info, warn, error, debug, trace};
use serde::{Serialize, Deserialize};
use chrono::{DateTime, Utc};

#[derive(Debug, Serialize, Deserialize)]
pub struct LogEntry {
pub timestamp: DateTime<Utc>,
pub level: LogLevel,
pub component: String,
pub action: String,
pub message: String,
pub context: LogContext,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LogContext {
pub session_id: String,
pub user_id: Option<String>,
pub command: Option<String>,
pub duration_ms: Option<u64>,
pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
Fatal,
}

// Usage in CODI commands
impl Codi {
pub async fn execute_command(&self, cmd: &str) -> Result<CommandResponse> {
let start = std::time::Instant::now();

info!(
component = "codi.command",
action = "execute_start",
command = cmd,
session_id = %self.session_id,
"Starting command execution"
);

match self.router.route(cmd).await {
Ok(response) => {
info!(
component = "codi.command",
action = "execute_success",
command = cmd,
duration_ms = start.elapsed().as_millis() as u64,
"Command completed successfully"
);
Ok(response)
}
Err(e) => {
error!(
component = "codi.command",
action = "execute_error",
command = cmd,
error = %e,
duration_ms = start.elapsed().as_millis() as u64,
"Command execution failed"
);
Err(e)
}
}
}
}

// Structured logging for CODI-specific events
pub fn log_codi_event(action: &str, message: &str, impact: Option<&str>, files: Option<Vec<String>>) {
let entry = json!({
"timestamp": Utc::now().to_rfc3339(),
"severity": "INFO",
"sessionId": std::env::var("CLAUDE_SESSION_ID").unwrap_or_default(),
"actor": {
"type": "codi",
"id": "codi-cli",
"role": "command-interface"
},
"action": action,
"message": message,
"metadata": {
"impact": impact,
"files": files,
"environment": "development",
"version": "v4"
}
});

println!("{}", serde_json::to_string(&entry).unwrap());
}

8.8 Error Handling Pattern 🔴 REQUIRED per v4.2

// src/errors.rs - CODI error handling
use thiserror::Error;
use std::fmt;

#[derive(Error, Debug)]
pub enum CodiError {
#[error("Command not found: {0}")]
CommandNotFound(String),

#[error("Invalid arguments for command '{command}': {message}")]
InvalidArguments { command: String, message: String },

#[error("Authentication required. Please run 'codi auth login'")]
Unauthorized,

#[error("Network error: {0}")]
NetworkError(#[from] reqwest::Error),

#[error("Configuration error: {0}")]
ConfigError(String),

#[error("MCP tool error: {tool} - {message}")]
McpToolError { tool: String, message: String },

#[error("State management error: {0}")]
StateError(#[from] rusqlite::Error),

#[error("API error ({status}): {message}")]
ApiError { status: u16, message: String },
}

impl CodiError {
/// Get user-friendly error message with helpful suggestions
pub fn user_message(&self) -> String {
match self {
Self::CommandNotFound(cmd) => {
format!(
"Command '{}' not found. Try 'codi help' to see available commands.",
cmd
)
}
Self::InvalidArguments { command, .. } => {
format!(
"Invalid arguments for '{}'. Use 'codi help {}' for usage.",
command, command
)
}
Self::Unauthorized => {
"You need to log in first. Run 'codi auth login' to authenticate.".to_string()
}
Self::NetworkError(_) => {
"Network connection failed. Please check your internet connection and try again.".to_string()
}
Self::ConfigError(_) => {
"Configuration issue detected. Run 'codi doctor' to diagnose.".to_string()
}
Self::McpToolError { tool, .. } => {
format!(
"The '{}' tool encountered an error. Check 'codi tools status'.",
tool
)
}
Self::StateError(_) => {
"Local state corrupted. Run 'codi repair' to fix.".to_string()
}
Self::ApiError { status: 429, .. } => {
"Rate limit exceeded. Please wait a moment before trying again.".to_string()
}
Self::ApiError { .. } => {
"Server error occurred. If this persists, check 'codi status'.".to_string()
}
}
}

/// Get recovery suggestions for the error
pub fn recovery_hints(&self) -> Vec<String> {
match self {
Self::CommandNotFound(_) => vec![
"Run 'codi help' to see all commands".to_string(),
"Check spelling and try again".to_string(),
],
Self::Unauthorized => vec![
"Run 'codi auth login'".to_string(),
"Check your credentials with 'codi auth status'".to_string(),
],
Self::NetworkError(_) => vec![
"Check internet connection".to_string(),
"Try 'codi doctor network'".to_string(),
"Check proxy settings if behind firewall".to_string(),
],
_ => vec!["Run 'codi doctor' for diagnostics".to_string()],
}
}
}

// Error display for users
impl fmt::Display for CodiError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\n❌ {}\n", self.user_message())?;

let hints = self.recovery_hints();
if !hints.is_empty() {
write!(f, "\n💡 Suggestions:\n")?;
for hint in hints {
write!(f, " • {}\n", hint)?;
}
}

Ok(())
}
}

// Usage in main CLI
fn main() {
if let Err(e) = run_codi().await {
eprintln!("{}", e);
std::process::exit(1);
}
}

↑ Back to Top

9. Testing Strategy 🔴 REQUIRED

9.1 Unit Tests

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_command_parsing() {
let args = vec!["codi", "log", "WORKING_ON", "test"];
let cli = Cli::parse_from(args);

match cli.command {
Commands::Log { action, message, .. } => {
assert_eq!(action, "WORKING_ON");
assert_eq!(message, "test");
}
_ => panic!("Wrong command parsed"),
}
}

#[tokio::test]
async fn test_session_management() {
let codi = Codi::new().unwrap();
let session = codi.start_session("test session").await.unwrap();

assert!(session.id != Uuid::nil());
assert_eq!(session.commands_executed, 0);
}

#[test]
fn test_mcp_server_initialization() {
let config = McpConfig {
enabled: true,
server_port: 3333,
allowed_tools: vec!["git".to_string()],
};

let server = mcp::Server::new(&config).unwrap();
assert!(server.is_running());
}
}

9.2 Integration Tests

#[tokio::test]
async fn test_full_command_flow() {
// Start CODI
let codi = Codi::new().unwrap();

// Execute command
let result = codi.execute("deploy frontend --env=staging").await.unwrap();
assert!(result.success);

// Verify log entry created
let logs = codi.get_recent_logs(1).await.unwrap();
assert_eq!(logs[0].action, "DEPLOY");
}

#[tokio::test]
async fn test_mcp_tool_integration() {
let codi = Codi::new().unwrap();

// Register as MCP server
codi.mcp_server.start().await.unwrap();

// External tool connects
let client = mcp::Client::connect("localhost:3333").await.unwrap();
let tools = client.list_tools().await.unwrap();

assert!(tools.contains(&"codi-deploy".to_string()));
}

9.3 Test Coverage Requirements 🔴 REQUIRED

  • Unit Tests: ≥ 90% coverage for all CODI modules
  • Integration Tests: ≥ 80% coverage for API and MCP interactions
  • Critical Paths: 100% coverage for:
    • Authentication and authorization
    • Command routing and execution
    • Error handling and recovery
    • State management operations
  • Performance Tests: All commands must meet latency targets
  • Security Tests: Penetration testing for MCP connections

9.4 Test Data 🟡 OPTIONAL

{
"test_sessions": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"started_at": "2025-08-27T20:00:00Z",
"commands": [
"codi session start",
"codi log SESSION_START \"Testing CODI\"",
"codi deploy frontend"
]
}
]
}

↑ Back to Top

10. Security Considerations 🔴 REQUIRED

10.1 Authentication & Authorization

  • JWT Integration: Uses CODITECT platform JWT tokens
  • MCP Auth: Tool connections require signed certificates
  • Local Security: State files encrypted with user key

10.2 Data Protection

  • Encryption at rest: SQLite DB encrypted with SQLCipher
  • Encryption in transit: TLS 1.3 for all API calls
  • PII handling: No PII stored in logs or state

10.3 Threat Model 🟡 OPTIONAL (required for security-critical features)

#ThreatLikelihoodImpactMitigation
1Malicious MCP tool🟡 Medium🔴 HighTool allowlist + signatures
2State tampering🟢 Low🟡 MediumFile integrity checks
3API key exposure🟡 Medium🔴 HighSecure keyring storage

↑ Back to Top

11. Performance Characteristics 🔴 REQUIRED

11.1 Expected Metrics

MetricTargetMeasurement
Command Latency<100ms local, <500ms remoteTimer per command
Memory Usage<50MB residentProcess monitoring
Startup Time<200msTime to first prompt
MCP Throughput1000 msg/secLoad testing

11.2 Benchmarks 🟡 OPTIONAL

#[bench]
fn bench_command_routing(b: &mut Bencher) {
let router = CommandRouter::new();
b.iter(|| {
router.route("deploy frontend --env=prod")
});
}

↑ Back to Top

12. Operational Considerations 🔴 REQUIRED

12.1 Deployment

# Installation script
curl -sSf https://coditect.com/install-codi.sh | sh

# Or via package managers
brew install coditect/tap/codi
cargo install codi
npm install -g @coditect/codi

12.2 Monitoring

What to MonitorMetricAlert Threshold
Command failuresError rate>5%
API latencyp95 response time>1s
MCP connectionsActive connections>100

12.3 Rollback Plan

  1. Detect issue: Error rate spike in telemetry
  2. Verify impact: Check user reports
  3. Execute rollback: codi self-update --version=previous
  4. Validate: Run smoke tests

13. Migration Strategy 🔴 REQUIRED if changes existing system

13.1 Migration Steps

  • Step 1: Create .codi/ in existing projects (ETA: 1 day)
  • Step 2: Move .session/.codi/session/ (ETA: 1 day)
  • Step 3: Update all script references (ETA: 2 days)
  • Step 4: Deploy CODI binary (ETA: 1 day)
  • Step 5: Deprecation warnings for old commands (ETA: 1 day)

13.2 Compatibility Matrix

ComponentBackward CompatibleBreaking ChangesMigration Required
Commands✅ Yes (aliases)New syntaxNo (optional)
State files⚠️ PartialNew formatYes (automated)
API✅ YesNoneNo

↑ Back to Top

14. Appendix 🟡 OPTIONAL

14.1 Glossary

TermDefinition
CODICODITECT's friendly command interface and assistant persona
MCPModel Context Protocol - standard for AI tool integration
State ManagerComponent managing persistent local state

14.2 Command Reference

# Session Management
codi session start [name]
codi session end
codi session list

# Logging
codi log <ACTION> "message" [IMPACT: "..."] [FILES: "..."]

# Development
codi adr create "Title"
codi adr qa <adr-number>
codi deploy <target> [--env=<env>]

# AI Operations
codi agent start
codi agent task "description"
codi agent status

↑ Back to Top

15. Review & Approval 🔴 REQUIRED

Approval Signatures

RoleNameDateSignature
Technical Lead[Name]YYYY-MM-DD___________
Product Owner[Name]YYYY-MM-DD___________
Security Review[Name]YYYY-MM-DD___________
Architecture Board[Name]YYYY-MM-DD___________

Review History

VersionDateReviewerStatusComments
0.12025-08-27AI SystemDRAFTInitial draft

16. QA REVIEW BLOCK 🔴 REQUIRED

Reviewed By: [Reviewer Name]
Review Date: YYYY-MM-DD
ADR Document: ADR-009-v4-codi-command-interface
Version Reviewed: 1.0
Review Status: DRAFT
Overall Score: [XX/40] ([XX]%)

Scoring Breakdown

#SectionScoreMaxNotes
1Structure & OrganizationX5[Notes]
2Dual-Audience ContentX5[Notes]
3Visual RequirementsX5[Notes]
4Implementation BlueprintX5[Notes]
5Testing & ValidationX5[Notes]
6CODITECT RequirementsX5[Notes]
7Documentation QualityX5[Notes]
8Review ProcessX5[Notes]

✅ Strengths

  • [Key strength 1]
  • [Key strength 2]

🔧 Areas for Improvement

  • [Improvement 1]
  • [Improvement 2]

📝 Recommendation

Decision: DRAFT - Awaiting review


QA Reviewer Signature: ___________________ Date: _______________