OverviewFilesCommitsIssuesDocsReleasesPeers

hyperident / index.js

2633 lines · javascript ref:
#!/usr/bin/env node
// Hyperident CLI - Identity management for hyperswarm applications
//
// Provides persistent, deterministic addressing through keet-identity-key integration.
// pgh provides P2P OTA updates (content-addressed) when installed via pgh.
//
// Usage: bare index.js <command> [options]
//        node index.js <command> [options]

import process from 'process'
if (typeof globalThis.process === 'undefined') globalThis.process = process
import { IdentityManager } from './lib/identity-manager.js'
import { DeviceLinkingManager } from './lib/device-linking-manager.js'
import { DeviceMeshManager } from './lib/device-mesh-manager.js'
import { DebugManager } from './lib/debug-manager.js'

/**
 * Display help message
 */
function showHelp() {
  console.log(`
🔑 Hyperident - Identity Manager for Hyperswarm

USAGE:
  hyperident <command> [options]

COMMANDS:
  init [--with-passphrase] [--device-name <name>] [--force]
                                                  Initialize new identity (--force: move an existing
                                                  vault to ~/.hyperident.bak-<time> first)
  create-profile <name> [desc]                     Create new profile
  list-profiles                                    List all profiles
  delete-profile <name>                            Delete profile
  address <profile> [--cached]                     Show hyperswarm address for profile
  refresh-addresses                                Refresh all cached addresses
  export-addresses [file] [--enhanced]             Export addresses for external programs
  sign <file>                                      Sign file with device identity
  verify <signature> <file>                       Verify signature against file
  export-signing-config                            Export signing config for applications
  device list                                      List device information
  device export [file]                             Export device bundle for sync
  device import <file> --device-name <name>       Import device bundle
  device verify                                    Verify device chain
  device bootstrap                                 Bootstrap as first node in network
  device create-network                            Create and start identity mesh network
  device share [--timeout <minutes>]              Share device for network linking
  device join <code> --device-name <name>         Join shared device over network
  device status                                    Show device mesh status
  device sync                                      Sync profiles across mesh
  device mesh join                                 Join identity mesh network
  device mesh leave                                Leave identity mesh network
  device revoke <device-id>                       Revoke device from identity
  debug inspect [--passphrase]                    Inspect identity and system state
  debug health                                     Run comprehensive health check
  debug network                                    Run network diagnostics
  debug trust                                      Verify trust relationships
  debug system                                     Show system information
  --help, -h                                       Show this help
  --version, -v                                    Show version

EXAMPLES:
  node index.js init                               # Create identity without passphrase
  node index.js init --with-passphrase            # Create identity with passphrase
  node index.js init --device-name "laptop"       # Create identity with device name
  node index.js create-profile work               # Create 'work' profile
  node index.js list-profiles                     # Show all profiles
  node index.js delete-profile work               # Delete 'work' profile
  node index.js address work                      # Show address for 'work' profile
  node index.js device export bundle.json         # Export for cross-device sync
  node index.js device import bundle.json --device-name "phone"  # Import on new device

For more information, visit: https://github.com/hyperident/hyperident
`)
}

/**
 * Display version information
 */
function showVersion() {
  console.log('hyperident v0.1.0')
}

/**
 * Handle init command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleInit(parsed) {
  try {
    // Check if identity already exists. --force moves it aside (never deletes it).
    const force = parsed.flags.includes('--force')
    if (IdentityManager.identityExists() && !force) {
      console.log('❌ Identity already exists!')
      console.log('💡 To create a new identity anyway, run: hyperident init --force')
      console.log('   The existing vault is moved to ~/.hyperident.bak-<time> first; nothing is deleted.')
      console.log('   Identity location: ~/.hyperident/')
      process.exit(1)
    }

    const withPassphrase = parsed.flags.includes('--with-passphrase')
    
    // Extract device name from flags
    let deviceName = 'default'
    const deviceNameIndex = parsed.flags.indexOf('--device-name')
    if (deviceNameIndex !== -1 && deviceNameIndex + 1 < parsed.flags.length) {
      deviceName = parsed.flags[deviceNameIndex + 1]
    }
    
    let passphrase = null

    if (withPassphrase) {
      // Import readline for passphrase input
      const readline = await import('readline')
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
      })

      // Helper function to get hidden input
      const getHiddenInput = (prompt) => {
        return new Promise((resolve) => {
          process.stdout.write(prompt)
          process.stdin.setRawMode(true)
          process.stdin.resume()
          process.stdin.setEncoding('utf8')
          
          let input = ''
          const onData = (char) => {
            if (char === '\u0003') { // Ctrl+C
              process.exit(1)
            } else if (char === '\r' || char === '\n') {
              process.stdin.setRawMode(false)
              process.stdin.pause()
              process.stdin.removeListener('data', onData)
              process.stdout.write('\n')
              resolve(input)
            } else if (char === '\u007f') { // Backspace
              if (input.length > 0) {
                input = input.slice(0, -1)
                process.stdout.write('\b \b')
              }
            } else {
              input += char
              process.stdout.write('*')
            }
          }
          
          process.stdin.on('data', onData)
        })
      }

      console.log('🔐 Creating encrypted identity...')
      passphrase = await getHiddenInput('Enter passphrase: ')
      
      if (!passphrase || passphrase.length < 8) {
        console.log('❌ Passphrase must be at least 8 characters long')
        process.exit(1)
      }

      const confirmPassphrase = await getHiddenInput('Confirm passphrase: ')
      
      if (passphrase !== confirmPassphrase) {
        console.log('❌ Passphrases do not match')
        process.exit(1)
      }

      rl.close()
    }

    console.log('🔑 Generating new identity with device chain...')
    
    // Generate and save the identity with device chain
    const identity = await IdentityManager.generateIdentity(passphrase, deviceName, { force })

    if (identity.backupPath) {
      console.log('📦 Previous identity moved to: ' + identity.backupPath)
    }
    console.log('✅ Identity created successfully!')
    console.log('')
    console.log('📋 Identity Details:')
    console.log(`   Public Key: ${identity.publicKey}`)
    console.log(`   Device Name: ${deviceName}`)
    console.log(`   Created: ${identity.created}`)
    console.log(`   Algorithm: ${identity.algorithm}`)
    console.log(`   Device Chain: ${identity.deviceChain ? 'Enabled' : 'Disabled'}`)
    console.log(`   Encrypted: ${withPassphrase ? 'Yes' : 'No'}`)
    console.log('')
    console.log('💾 Identity saved to: ~/.hyperident/')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Create profiles: node index.js create-profile <name>')
    console.log('   • List profiles: node index.js list-profiles')
    console.log('   • View device info: node index.js device list')
    console.log('   • Export for sync: node index.js device export')
    console.log('   • Get help: node index.js --help')
    
    if (withPassphrase) {
      console.log('')
      console.log('🔒 Important: Your identity is encrypted with a passphrase.')
      console.log('   Keep your passphrase safe - it cannot be recovered if lost!')
    }

  } catch (error) {
    console.error('❌ Failed to initialize identity:', error.message)
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle create-profile command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleCreateProfile(parsed) {
  try {
    const profileName = parsed.positional[0]
    const description = parsed.positional[1] || ''

    console.log(`📝 Creating profile '${profileName}'...`)
    
    // Create the profile using IdentityManager
    await IdentityManager.createProfile(profileName, description)
    
    console.log('✅ Profile created successfully!')
    console.log('')
    console.log('📋 Profile Details:')
    console.log(`   Name: ${profileName}`)
    console.log(`   Description: ${description || '(no description)'}`)
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • List all profiles: hyperident list-profiles')
    console.log('   • Delete profile: hyperident delete-profile ' + profileName)
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to create profile:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('already exists')) {
      console.error('💡 Choose a different profile name or delete the existing one first')
    } else if (error.message.includes('Invalid profile name')) {
      console.error('💡 Profile names must be 1-32 characters, alphanumeric and hyphens only')
      console.error('   Cannot start/end with hyphen or use reserved names')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle list-profiles command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleListProfiles(parsed) {
  try {
    console.log('📋 Listing profiles...')
    
    // Get all profiles using IdentityManager
    const profilesData = await IdentityManager.listProfiles()
    const profiles = Object.values(profilesData.profiles)
    
    if (profiles.length === 0) {
      console.log('📭 No profiles found')
      console.log('')
      console.log('🚀 Get started:')
      console.log('   • Create a profile: hyperident create-profile <name>')
      console.log('   • Get help: hyperident --help')
      return
    }
    
    console.log(`✅ Found ${profiles.length} profile${profiles.length === 1 ? '' : 's'}:`)
    console.log('')
    
    // Display each profile with details
    profiles.forEach((profile, index) => {
      console.log(`${index + 1}. 📁 ${profile.name}`)
      if (profile.description) {
        console.log(`   Description: ${profile.description}`)
      }
      console.log(`   Created: ${new Date(profile.created).toLocaleString()}`)
      if (profile.lastModified && profile.lastModified !== profile.created) {
        console.log(`   Modified: ${new Date(profile.lastModified).toLocaleString()}`)
      }
      console.log('')
    })
    
    console.log('🚀 Next steps:')
    console.log('   • Create profile: hyperident create-profile <name>')
    console.log('   • Delete profile: hyperident delete-profile <name>')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to list profiles:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle delete-profile command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeleteProfile(parsed) {
  try {
    const profileName = parsed.positional[0]

    console.log(`🗑️  Deleting profile '${profileName}'...`)
    
    // Delete the profile using IdentityManager
    await IdentityManager.deleteProfile(profileName)
    
    console.log('✅ Profile deleted successfully!')
    console.log('')
    console.log(`📋 Profile '${profileName}' has been removed`)
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • List remaining profiles: hyperident list-profiles')
    console.log('   • Create new profile: hyperident create-profile <name>')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to delete profile:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('not found')) {
      console.error('💡 Check available profiles with "hyperident list-profiles"')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle address command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleAddress(parsed) {
  try {
    const profileName = parsed.positional[0]
    const useCached = parsed.flags.includes('--cached')

    console.log(`🔍 Getting address for profile '${profileName}'...`)
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    if (!useCached) {
      try {
        const identityData = await IdentityManager.loadIdentity()
        // If we get here without error, identity is not encrypted
      } catch (error) {
        if (error.message.includes('encrypted but no passphrase provided')) {
          passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
        } else {
          throw error
        }
      }
    }
    
    // Get the hyperswarm address for the profile
    let address
    if (useCached) {
      address = await IdentityManager.getCachedProfileAddress(profileName, passphrase)
      console.log('✅ Cached address retrieved successfully!')
    } else {
      address = await IdentityManager.getProfileAddress(profileName, passphrase)
      console.log('✅ Address generated successfully!')
    }
    
    console.log('')
    console.log('📋 Profile Address:')
    console.log(`   Profile: ${profileName}`)
    console.log(`   Address: ${address}`)
    console.log(`   Source: ${useCached ? 'Cached' : 'Generated'}`)
    console.log('')
    console.log('🔗 Usage:')
    console.log('   This address can be used with hyperswarm applications')
    console.log('   The same profile will always generate the same address')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Use this address in hyperswarm applications')
    console.log('   • Create more profiles: hyperident create-profile <name>')
    console.log('   • List all profiles: hyperident list-profiles')

  } catch (error) {
    console.error('❌ Failed to get profile address:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('not found')) {
      console.error('💡 Check available profiles with "hyperident list-profiles"')
      console.error('   Or create the profile: hyperident create-profile ' + parsed.positional[0])
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle refresh-addresses command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleRefreshAddresses(parsed) {
  try {
    console.log('🔄 Refreshing all cached addresses...')
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Refresh all addresses
    await IdentityManager.refreshAllAddresses(passphrase)
    
    console.log('✅ All addresses refreshed successfully!')
    console.log('')
    console.log('📋 All profile addresses have been updated in cache')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • List profiles: hyperident list-profiles')
    console.log('   • Export addresses: hyperident export-addresses')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to refresh addresses:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle export-addresses command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleExportAddresses(parsed) {
  try {
    const outputFile = parsed.positional[0] || null
    const useEnhanced = parsed.flags.includes('--enhanced')

    console.log(`📤 Exporting addresses${useEnhanced ? ' (enhanced format)' : ''}...`)
    
    // Check if identity is encrypted and prompt for passphrase if needed (for enhanced export)
    let passphrase = null
    if (useEnhanced) {
      try {
        const identityData = await IdentityManager.loadIdentity()
        // If we get here without error, identity is not encrypted
      } catch (error) {
        if (error.message.includes('encrypted but no passphrase provided')) {
          passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
        } else {
          throw error
        }
      }
    }
    
    // Export addresses
    const addressesJSON = useEnhanced 
      ? await IdentityManager.exportAddressesEnhancedJSON(passphrase)
      : await IdentityManager.exportAddressesJSON()
    
    if (outputFile) {
      // Write to file
      const fs = await import('fs/promises')
      await fs.writeFile(outputFile, addressesJSON)
      console.log(`✅ Addresses exported to: ${outputFile}`)
    } else {
      // Output to console
      console.log('✅ Addresses exported:')
      console.log('')
      console.log(addressesJSON)
    }
    
    console.log('')
    if (useEnhanced) {
      console.log('📋 Enhanced Export Features:')
      console.log('   • Multiple format options (hex, buffer, base64)')
      console.log('   • Environment variable templates')
      console.log('   • Hyperswarm usage examples')
      console.log('   • JavaScript integration code')
      console.log('')
    }
    console.log('🚀 Next steps:')
    console.log('   • Use addresses in external programs')
    console.log('   • List profiles: hyperident list-profiles')
    if (!useEnhanced) {
      console.log('   • Try enhanced export: hyperident export-addresses --enhanced')
    }
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to export addresses:', error.message)
    
    // Provide specific guidance based on error type
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device list command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceList(parsed) {
  try {
    console.log('📱 Device Information:')
    
    // Check if device chain exists
    const deviceExists = await IdentityManager.deviceChainExists()
    if (!deviceExists) {
      console.log('❌ No device chain found')
      console.log('💡 This identity was created without device chain support')
      console.log('   Create a new identity with: node index.js init --device-name "device-name"')
      process.exit(1)
    }
    
    // Load device chain
    const deviceChain = await IdentityManager.loadDeviceChain()
    
    console.log('✅ Device chain found:')
    console.log('')
    console.log('📋 Device Details:')
    console.log(`   Name: ${deviceChain.metadata.name}`)
    console.log(`   Created: ${new Date(deviceChain.metadata.created).toLocaleString()}`)
    console.log(`   Public Key: ${deviceChain.metadata.publicKey}`)
    console.log(`   Version: ${deviceChain.metadata.version}`)
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Export for sync: node index.js device export')
    console.log('   • Verify chain: node index.js device verify')
    console.log('   • Get help: node index.js --help')

  } catch (error) {
    console.error('❌ Failed to list device information:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device export command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceExport(parsed) {
  try {
    const outputFile = parsed.positional[0] || null

    console.log('📤 Exporting device bundle...')
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Export device bundle
    const bundle = await IdentityManager.exportDeviceBundle(passphrase)
    const bundleJSON = JSON.stringify(bundle, null, 2)
    
    if (outputFile) {
      // Write to file
      const fs = await import('fs/promises')
      await fs.writeFile(outputFile, bundleJSON)
      console.log(`✅ Device bundle exported to: ${outputFile}`)
    } else {
      // Output to console
      console.log('✅ Device bundle exported:')
      console.log('')
      console.log(bundleJSON)
    }
    
    console.log('')
    console.log('🔗 Usage:')
    console.log('   Transfer this bundle to another device and import it with:')
    console.log('   node index.js device import <bundle-file> --device-name "new-device"')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Import on new device: node index.js device import <file> --device-name <name>')
    console.log('   • Get help: node index.js --help')

  } catch (error) {
    console.error('❌ Failed to export device bundle:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device import command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceImport(parsed) {
  try {
    const bundleFile = parsed.positional[1] // positional[0] is "import", positional[1] is the file
    
    if (!bundleFile) {
      console.error('❌ Bundle file is required')
      console.error('💡 Usage: node index.js device import <bundle-file> --device-name <name>')
      process.exit(1)
    }
    
    // Extract device name from flags
    let deviceName = null
    const deviceNameIndex = parsed.flags.indexOf('--device-name')
    if (deviceNameIndex !== -1 && deviceNameIndex + 1 < parsed.flags.length) {
      deviceName = parsed.flags[deviceNameIndex + 1]
    }
    
    if (!deviceName) {
      console.error('❌ Device name is required')
      console.error('💡 Usage: node index.js device import <bundle-file> --device-name <name>')
      process.exit(1)
    }

    console.log(`📥 Importing device bundle from: ${bundleFile}`)
    console.log(`📱 New device name: ${deviceName}`)
    
    // Check if identity already exists
    if (IdentityManager.identityExists()) {
      console.log('❌ Identity already exists!')
      console.log('💡 If you want to import a new identity, please backup and remove the existing one first.')
      console.log('   Identity location: ~/.hyperident/')
      process.exit(1)
    }
    
    // Read bundle file
    const fs = await import('fs/promises')
    const bundleJSON = await fs.readFile(bundleFile, 'utf8')
    const bundle = JSON.parse(bundleJSON)
    
    // Check if we need a passphrase for the imported identity
    let passphrase = null
    if (bundle.identity && bundle.identity.encrypted === true) {
      // Only prompt for passphrase if explicitly encrypted
      passphrase = await getPassphrase('🔐 Imported identity is encrypted. Please enter the passphrase.')
    }
    
    // Import device bundle
    await IdentityManager.importDeviceBundle(bundle, deviceName, passphrase)
    
    console.log('✅ Device bundle imported successfully!')
    console.log('')
    console.log('📋 Import Details:')
    console.log(`   Device Name: ${deviceName}`)
    console.log(`   Identity Public Key: ${bundle.identity.publicKey}`)
    console.log(`   Profiles Imported: ${Object.keys(bundle.profiles || {}).length}`)
    console.log('')
    console.log('💾 Identity saved to: ~/.hyperident/')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • List profiles: node index.js list-profiles')
    console.log('   • Verify device: node index.js device verify')
    console.log('   • Get help: node index.js --help')

  } catch (error) {
    console.error('❌ Failed to import device bundle:', error.message)
    
    if (error.message.includes('Invalid device bundle format')) {
      console.error('💡 Check that the bundle file is valid and not corrupted')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device bootstrap command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceBootstrap(parsed) {
  try {
    console.log('🚀 Bootstrapping as first node in network...')
    
    // Check if identity exists
    if (!IdentityManager.identityExists()) {
      console.log('❌ No identity found!')
      console.log('💡 Run "node index.js init --device-name <name>" first to create an identity')
      process.exit(1)
    }

    // Check if device chain exists
    const deviceExists = await IdentityManager.deviceChainExists()
    if (!deviceExists) {
      console.log('❌ No device chain found')
      console.log('💡 This identity was created without device chain support')
      console.log('   Create a new identity with: node index.js init --device-name "device-name"')
      process.exit(1)
    }

    // Load device chain and identity info
    const deviceChain = await IdentityManager.loadDeviceChain()
    const identity = await IdentityManager.loadIdentity()
    
    console.log('✅ Identity and device chain verified!')
    console.log('')
    console.log('📋 Bootstrap Details:')
    console.log(`   Identity: ${identity.publicKey}`)
    console.log(`   Device: ${deviceChain.metadata.name}`)
    console.log(`   Device Key: ${deviceChain.metadata.publicKey}`)
    console.log(`   Created: ${new Date(deviceChain.metadata.created).toLocaleString()}`)
    console.log('')
    console.log('🌐 Network Information:')
    console.log('   You are now the first node in your identity mesh network')
    console.log('   Other devices can sync with you using:')
    console.log('   • Device sharing: node index.js device share')
    console.log('   • Device export/import: node index.js device export')
    console.log('   • Mesh networking: node index.js device mesh join')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Create profiles: node index.js create-profile <name>')
    console.log('   • Start mesh network: node index.js device create-network')
    console.log('   • Share device: node index.js device share')
    console.log('   • Export bundle: node index.js device export')
    console.log('   • Get help: node index.js --help')

  } catch (error) {
    console.error('❌ Failed to bootstrap device:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device create-network command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceCreateNetwork(parsed) {
  try {
    console.log('🌐 Creating and starting identity mesh network...')
    
    // Check network availability
    const networkAvailable = await DeviceMeshManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Check if identity exists
    if (!IdentityManager.identityExists()) {
      console.log('❌ No identity found!')
      console.log('💡 Run "node index.js init --device-name <name>" first to create an identity')
      process.exit(1)
    }

    // Create device mesh manager
    const meshManager = new DeviceMeshManager()
    
    try {
      // Join the mesh as the first node
      await meshManager.joinMesh()
      
      console.log('✅ Identity mesh network created and started!')
      console.log('')
      console.log('📋 Network Details:')
      console.log('   Status: Active (First Node)')
      console.log('   Discovery: Identity-based mesh discovery active')
      console.log('   Sync: Real-time profile synchronization enabled')
      console.log('   Role: Bootstrap/Seed Node')
      console.log('')
      console.log('🔗 Network Features:')
      console.log('   • Automatic device discovery within identity')
      console.log('   • Real-time profile synchronization')
      console.log('   • Device status monitoring')
      console.log('   • Conflict resolution for profile changes')
      console.log('')
      console.log('📱 Adding Other Devices:')
      console.log('   Other devices can join this network using:')
      console.log('   1. Device sharing: node index.js device share')
      console.log('   2. Export/import: node index.js device export')
      console.log('   3. Direct mesh join: node index.js device mesh join')
      console.log('')
      console.log('🚀 Network is now running!')
      console.log('   • Check status: node index.js device status')
      console.log('   • Sync profiles: node index.js device sync')
      console.log('   • Share device: node index.js device share')
      console.log('')
      console.log('💡 The network will continue running in the background.')
      console.log('   Use Ctrl+C to stop or run "device mesh leave" to disconnect.')
      
      // Keep the process alive for mesh operations
      console.log('Press Ctrl+C to stop the network...')
      
      await new Promise((resolve) => {
        const cleanup = async () => {
          console.log('\n🛑 Stopping mesh network...')
          await meshManager.leaveMesh()
          console.log('✅ Network stopped')
          resolve()
        }
        
        process.on('SIGINT', cleanup)
        process.on('SIGTERM', cleanup)
      })
      
    } catch (error) {
      await meshManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to create network:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Already connected to mesh')) {
      console.error('💡 Already connected to mesh. Use "device status" to check status.')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device verify command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceVerify(parsed) {
  try {
    console.log('🔍 Verifying device chain...')
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Verify device chain
    const isValid = await IdentityManager.deviceChainExists(passphrase)
    
    if (isValid) {
      console.log('✅ Device chain verification successful!')
      console.log('')
      console.log('📋 Verification Results:')
      console.log('   Device chain is valid and properly attested')
      console.log('   Device is authorized for this identity')
      console.log('   Proof chain links back to root identity')
      console.log('')
      console.log('🚀 Next steps:')
      console.log('   • View device info: node index.js device list')
      console.log('   • Export for sync: node index.js device export')
      console.log('   • Get help: node index.js --help')
    } else {
      console.log('❌ Device chain verification failed!')
      console.log('')
      console.log('📋 Possible Issues:')
      console.log('   • Device chain files are missing or corrupted')
      console.log('   • Device is not properly attested')
      console.log('   • Proof chain does not link to root identity')
      console.log('')
      console.log('💡 Try recreating the identity or importing a valid device bundle')
      process.exit(1)
    }

  } catch (error) {
    console.error('❌ Failed to verify device chain:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle sign command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleSign(parsed) {
  try {
    const filePath = parsed.positional[0]
    
    if (!filePath) {
      console.error('❌ File path is required')
      console.error('💡 Usage: hyperident sign <file>')
      process.exit(1)
    }

    console.log(`🔏 Signing file: ${filePath}`)
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Read file to sign
    const fs = await import('fs/promises')
    const fileData = await fs.readFile(filePath)
    
    // Sign the file data
    const signature = await IdentityManager.signData(fileData, passphrase)
    
    // Create signature file
    const signatureFile = filePath + '.sig'
    const signatureData = {
      version: '1.0.0',
      algorithm: 'keet-identity-key',
      file: filePath,
      signature: signature.toString('hex'),
      signed: new Date().toISOString()
    }
    
    await fs.writeFile(signatureFile, JSON.stringify(signatureData, null, 2))
    
    console.log('✅ File signed successfully!')
    console.log('')
    console.log('📋 Signature Details:')
    console.log(`   File: ${filePath}`)
    console.log(`   Signature: ${signatureFile}`)
    console.log(`   Algorithm: ${signatureData.algorithm}`)
    console.log(`   Signed: ${signatureData.signed}`)
    console.log('')
    console.log('🚀 Next steps:')
    console.log(`   • Verify signature: hyperident verify ${signatureFile} ${filePath}`)
    console.log('   • Share signature file with others for verification')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to sign file:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    } else if (error.message.includes('ENOENT')) {
      console.error('💡 Check that the file exists and is readable')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle verify command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleVerify(parsed) {
  try {
    const signatureFile = parsed.positional[0]
    const originalFile = parsed.positional[1]
    
    if (!signatureFile || !originalFile) {
      console.error('❌ Both signature file and original file are required')
      console.error('💡 Usage: hyperident verify <signature-file> <original-file>')
      process.exit(1)
    }

    console.log(`🔍 Verifying signature...`)
    console.log(`   Signature: ${signatureFile}`)
    console.log(`   File: ${originalFile}`)
    
    // Read signature file
    const fs = await import('fs/promises')
    const signatureJSON = await fs.readFile(signatureFile, 'utf8')
    const signatureData = JSON.parse(signatureJSON)
    
    // Read original file
    const fileData = await fs.readFile(originalFile)
    
    // Convert signature from hex
    const signature = Buffer.from(signatureData.signature, 'hex')
    
    // Verify signature
    const verification = await IdentityManager.verifySignature(signature, fileData)
    
    if (verification) {
      console.log('✅ Signature verification successful!')
      console.log('')
      console.log('📋 Verification Results:')
      console.log(`   File: ${originalFile}`)
      console.log(`   Signature: ${signatureFile}`)
      console.log(`   Identity: ${verification.identityPublicKey.toString('hex')}`)
      console.log(`   Device: ${verification.devicePublicKey.toString('hex')}`)
      console.log(`   Algorithm: ${signatureData.algorithm}`)
      console.log(`   Signed: ${signatureData.signed}`)
      console.log('')
      console.log('🔒 This file was authentically signed by the specified identity')
    } else {
      console.log('❌ Signature verification failed!')
      console.log('')
      console.log('📋 Possible Issues:')
      console.log('   • File has been modified since signing')
      console.log('   • Signature file is corrupted or invalid')
      console.log('   • Wrong file being verified against signature')
      console.log('')
      console.log('⚠️  Do not trust this file - signature is invalid')
      process.exit(1)
    }

  } catch (error) {
    console.error('❌ Failed to verify signature:', error.message)
    
    if (error.message.includes('ENOENT')) {
      console.error('💡 Check that both signature and original files exist')
    } else if (error.message.includes('JSON')) {
      console.error('💡 Signature file appears to be corrupted or invalid')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device share command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceShare(parsed) {
  try {
    // Extract timeout from flags
    let timeoutMinutes = 5 // default
    const timeoutIndex = parsed.flags.indexOf('--timeout')
    if (timeoutIndex !== -1 && timeoutIndex + 1 < parsed.flags.length) {
      const timeoutValue = parseInt(parsed.flags[timeoutIndex + 1])
      if (!isNaN(timeoutValue) && timeoutValue > 0) {
        timeoutMinutes = timeoutValue
      }
    }

    console.log('🔗 Starting device sharing...')
    console.log(`⏱️  Timeout: ${timeoutMinutes} minutes`)
    
    // Check network availability
    const networkAvailable = await DeviceLinkingManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Create device linking manager
    const linkingManager = new DeviceLinkingManager()
    
    try {
      // Start sharing
      const sharingCode = await linkingManager.startSharing(timeoutMinutes)
      
      console.log('✅ Device sharing started successfully!')
      console.log('')
      console.log('📋 Sharing Details:')
      console.log(`   Identity Public Key: ${sharingCode}`)
      console.log(`   Timeout: ${timeoutMinutes} minutes`)
      console.log(`   Status: Waiting for connections...`)
      console.log('')
      console.log('🔗 Usage:')
      console.log('   On the new device, run:')
      console.log(`   node index.js device join ${sharingCode} --device-name "new-device"`)
      console.log('')
      console.log('⚠️  Security Notes:')
      console.log('   • This code expires automatically after the timeout')
      console.log('   • Only share this code with devices you trust')
      console.log('   • The code is only valid for this session')
      console.log('')
      console.log('Press Ctrl+C to stop sharing...')
      
      // Keep the process alive until timeout or Ctrl+C
      await new Promise((resolve) => {
        let cleanupCalled = false
        
        const cleanup = async () => {
          if (cleanupCalled) return
          cleanupCalled = true
          
          console.log('\n🛑 Stopping device sharing...')
          
          // Remove event listeners to prevent multiple calls
          process.removeListener('SIGINT', cleanup)
          process.removeListener('SIGTERM', cleanup)
          
          await linkingManager.stopSharing()
          console.log('✅ Device sharing stopped')
          resolve()
        }
        
        process.on('SIGINT', cleanup)
        process.on('SIGTERM', cleanup)
        
        // Auto-cleanup on timeout (handled by linkingManager)
        setTimeout(() => {
          if (!cleanupCalled) {
            console.log('\n⏱️  Sharing session timed out')
            cleanup()
          }
        }, timeoutMinutes * 60 * 1000 + 1000) // Add 1 second buffer
      })
      
    } catch (error) {
      await linkingManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to share device:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Already sharing')) {
      console.error('💡 Stop the current sharing session first')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device join command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceJoin(parsed) {
  try {
    const sharingCode = parsed.positional[1] // positional[0] is "join", positional[1] is the code
    
    if (!sharingCode) {
      console.error('❌ Sharing code is required')
      console.error('💡 Usage: node index.js device join <code> --device-name <name>')
      process.exit(1)
    }
    
    // Extract device name from flags
    let deviceName = null
    const deviceNameIndex = parsed.flags.indexOf('--device-name')
    if (deviceNameIndex !== -1 && deviceNameIndex + 1 < parsed.flags.length) {
      deviceName = parsed.flags[deviceNameIndex + 1]
    }
    
    if (!deviceName) {
      console.error('❌ Device name is required')
      console.error('💡 Usage: node index.js device join <code> --device-name <name>')
      process.exit(1)
    }

    console.log('🔗 Joining shared device...')
    console.log(`📱 Device name: ${deviceName}`)
    console.log(`🔑 Sharing code: ${sharingCode}`)
    
    // Check network availability
    const networkAvailable = await DeviceLinkingManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Check if identity already exists
    if (IdentityManager.identityExists()) {
      console.log('❌ Identity already exists!')
      console.log('💡 If you want to join a new identity, please backup and remove the existing one first.')
      console.log('   Identity location: ~/.hyperident/')
      process.exit(1)
    }

    // Create device linking manager
    const linkingManager = new DeviceLinkingManager()
    
    try {
      console.log('🔍 Searching for shared device...')
      
      // Join the shared device
      const success = await linkingManager.joinDevice(sharingCode, deviceName)
      
      if (success) {
        console.log('✅ Successfully joined shared device!')
        console.log('')
        console.log('📋 Join Details:')
        console.log(`   Device Name: ${deviceName}`)
        console.log(`   Sharing Code: ${sharingCode}`)
        console.log('')
        console.log('💾 Identity saved to: ~/.hyperident/')
        console.log('')
        console.log('🚀 Next steps:')
        console.log('   • List profiles: node index.js list-profiles')
        console.log('   • Verify device: node index.js device verify')
        console.log('   • View device info: node index.js device list')
        console.log('   • Get help: node index.js --help')
      } else {
        console.log('❌ Failed to join shared device')
        console.log('💡 Check the sharing code and try again')
        process.exit(1)
      }
      
    } catch (error) {
      await linkingManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to join device:', error.message)
    
    if (error.message.includes('Identity already exists')) {
      console.error('💡 Remove existing identity first or use a different device')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Connection timeout')) {
      console.error('💡 Check the sharing code and ensure the sharing device is online')
    } else if (error.message.includes('Invalid device bundle format')) {
      console.error('💡 The shared device data appears to be corrupted')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device status command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceStatus(parsed) {
  try {
    console.log('📊 Device Mesh Status:')
    
    // Check network availability
    const networkAvailable = await DeviceMeshManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Create device mesh manager
    const meshManager = new DeviceMeshManager()
    
    try {
      // Get mesh status
      const status = await meshManager.getMeshStatus()
      
      console.log('✅ Mesh status retrieved successfully!')
      console.log('')
      console.log('📋 Mesh Details:')
      console.log(`   Connected to Mesh: ${status.connected ? 'Yes' : 'No'}`)
      console.log(`   Connected Devices: ${status.connectedDevices}`)
      console.log(`   Identity: ${status.identityPublicKey}`)
      console.log(`   This Device: ${status.thisDevicePublicKey}`)
      console.log('')
      
      if (status.devices && status.devices.length > 0) {
        console.log('🔗 Connected Devices:')
        status.devices.forEach((device, index) => {
          console.log(`   ${index + 1}. ${device.name || 'Unknown'}`)
          console.log(`      Public Key: ${device.publicKey}`)
          console.log(`      Status: ${device.status || 'Unknown'}`)
          console.log(`      Last Seen: ${device.lastSeen ? new Date(device.lastSeen).toLocaleString() : 'Never'}`)
          console.log('')
        })
      } else {
        console.log('📭 No other devices connected to mesh')
      }
      
      console.log('🚀 Next steps:')
      console.log('   • Join mesh: node index.js device mesh join')
      console.log('   • Sync profiles: node index.js device sync')
      console.log('   • Get help: node index.js --help')
      
    } catch (error) {
      await meshManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to get device status:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device sync command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceSync(parsed) {
  try {
    console.log('🔄 Syncing profiles across mesh...')
    
    // Check network availability
    const networkAvailable = await DeviceMeshManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Create device mesh manager
    const meshManager = new DeviceMeshManager()
    
    try {
      // Perform sync
      const syncResult = await meshManager.syncProfiles()
      
      console.log('✅ Profile sync completed successfully!')
      console.log('')
      console.log('📋 Sync Results:')
      console.log(`   Profiles Synced: ${syncResult.profilesSynced || 0}`)
      console.log(`   Conflicts Resolved: ${syncResult.conflictsResolved || 0}`)
      console.log(`   Devices Contacted: ${syncResult.devicesContacted || 0}`)
      console.log('')
      
      if (syncResult.changes && syncResult.changes.length > 0) {
        console.log('📝 Changes Made:')
        syncResult.changes.forEach((change, index) => {
          console.log(`   ${index + 1}. ${change.type}: ${change.profile}`)
          console.log(`      ${change.description}`)
        })
        console.log('')
      }
      
      console.log('🚀 Next steps:')
      console.log('   • Check status: node index.js device status')
      console.log('   • List profiles: node index.js list-profiles')
      console.log('   • Get help: node index.js --help')
      
    } catch (error) {
      await meshManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to sync profiles:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Not connected to mesh')) {
      console.error('💡 Join the mesh first: node index.js device mesh join')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device mesh join command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceMeshJoin(parsed) {
  try {
    console.log('🔗 Joining identity mesh network...')
    
    // Check network availability
    const networkAvailable = await DeviceMeshManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Create device mesh manager
    const meshManager = new DeviceMeshManager()
    
    try {
      // Join the mesh
      await meshManager.joinMesh()
      
      console.log('✅ Successfully joined identity mesh!')
      console.log('')
      console.log('📋 Mesh Details:')
      console.log('   Status: Connected')
      console.log('   Discovery: Identity-based mesh discovery active')
      console.log('   Sync: Real-time profile synchronization enabled')
      console.log('')
      console.log('🔗 Features Available:')
      console.log('   • Automatic device discovery within identity')
      console.log('   • Real-time profile synchronization')
      console.log('   • Device status monitoring')
      console.log('   • Conflict resolution for profile changes')
      console.log('')
      console.log('🚀 Next steps:')
      console.log('   • Check status: node index.js device status')
      console.log('   • Sync profiles: node index.js device sync')
      console.log('   • Leave mesh: node index.js device mesh leave')
      console.log('')
      console.log('💡 The mesh will continue running in the background.')
      console.log('   Use Ctrl+C to stop or run "device mesh leave" to disconnect.')
      
      // Keep the process alive for mesh operations
      console.log('Press Ctrl+C to stop mesh networking...')
      
      await new Promise((resolve) => {
        const cleanup = async () => {
          console.log('\n🛑 Leaving mesh network...')
          await meshManager.leaveMesh()
          console.log('✅ Left mesh network')
          resolve()
        }
        
        process.on('SIGINT', cleanup)
        process.on('SIGTERM', cleanup)
      })
      
    } catch (error) {
      await meshManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to join mesh:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Already connected to mesh')) {
      console.error('💡 Already connected to mesh. Use "device status" to check status.')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device mesh leave command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceMeshLeave(parsed) {
  try {
    console.log('🔌 Leaving identity mesh network...')
    
    // Check network availability
    const networkAvailable = await DeviceMeshManager.isNetworkAvailable()
    if (!networkAvailable) {
      console.log('❌ Network dependencies not available')
      console.log('💡 Install network dependencies with:')
      console.log('   npm install hyperswarm hypercore-id-encoding b4a')
      process.exit(1)
    }

    // Create device mesh manager
    const meshManager = new DeviceMeshManager()
    
    try {
      // Leave the mesh
      await meshManager.leaveMesh()
      
      console.log('✅ Successfully left identity mesh!')
      console.log('')
      console.log('📋 Disconnection Details:')
      console.log('   Status: Disconnected')
      console.log('   Discovery: Stopped')
      console.log('   Sync: Disabled')
      console.log('')
      console.log('🚀 Next steps:')
      console.log('   • Join mesh again: node index.js device mesh join')
      console.log('   • Check status: node index.js device status')
      console.log('   • Get help: node index.js --help')
      
    } catch (error) {
      await meshManager.cleanup()
      throw error
    }

  } catch (error) {
    console.error('❌ Failed to leave mesh:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Network dependencies not available')) {
      console.error('💡 Install required dependencies:')
      console.error('   npm install hyperswarm hypercore-id-encoding b4a')
    } else if (error.message.includes('Not connected to mesh')) {
      console.error('💡 Not currently connected to mesh')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle device revoke command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDeviceRevoke(parsed) {
  try {
    const deviceId = parsed.positional[1] // positional[0] is "revoke", positional[1] is the device ID
    
    if (!deviceId) {
      console.error('❌ Device ID is required')
      console.error('💡 Usage: node index.js device revoke <device-id>')
      process.exit(1)
    }

    console.log(`🚫 Revoking device: ${deviceId}`)
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Revoke the device
    await IdentityManager.revokeDevice(deviceId, passphrase)
    
    console.log('✅ Device revoked successfully!')
    console.log('')
    console.log('📋 Revocation Details:')
    console.log(`   Device ID: ${deviceId}`)
    console.log(`   Status: Revoked`)
    console.log(`   Revoked: ${new Date().toISOString()}`)
    console.log('')
    console.log('⚠️  Security Notes:')
    console.log('   • The revoked device can no longer sign data for this identity')
    console.log('   • Existing signatures from this device remain valid')
    console.log('   • The device cannot join the mesh network')
    console.log('   • Profile sync will exclude the revoked device')
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Check device status: node index.js device status')
    console.log('   • Sync profiles: node index.js device sync')
    console.log('   • Get help: node index.js --help')

  } catch (error) {
    console.error('❌ Failed to revoke device:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "node index.js init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    } else if (error.message.includes('Device not found')) {
      console.error('💡 Check the device ID and try again')
    } else if (error.message.includes('Cannot revoke own device')) {
      console.error('💡 You cannot revoke the device you are currently using')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle export-signing-config command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleExportSigningConfig(parsed) {
  try {
    console.log('📤 Exporting signing configuration...')
    
    // Check if identity is encrypted and prompt for passphrase if needed
    let passphrase = null
    try {
      const identityData = await IdentityManager.loadIdentity()
      // If we get here without error, identity is not encrypted
    } catch (error) {
      if (error.message.includes('encrypted but no passphrase provided')) {
        passphrase = await getPassphrase('🔐 Identity is encrypted. Please enter your passphrase.')
      } else {
        throw error
      }
    }
    
    // Export signing configuration
    const signingConfig = await IdentityManager.exportSigningConfig(passphrase)
    const configJSON = JSON.stringify(signingConfig, null, 2)
    
    console.log('✅ Signing configuration exported:')
    console.log('')
    console.log(configJSON)
    console.log('')
    console.log('📋 Configuration Details:')
    console.log('   • identityPublicKey: Root identity public key')
    console.log('   • devicePublicKey: This device\'s public key')
    console.log('   • deviceSecretKey: This device\'s secret key (keep secure!)')
    console.log('   • bootstrapProof: Proof linking device to identity')
    console.log('')
    console.log('🔒 Security Warning:')
    console.log('   This configuration contains your device\'s secret key!')
    console.log('   Only share with trusted applications that need signing capability.')
    console.log('   Consider using environment variables or secure config files.')
    console.log('')
    console.log('🚀 Usage:')
    console.log('   Applications can use this config with keet-identity-key to:')
    console.log('   • Sign data with IdentityKey.attestData()')
    console.log('   • Verify signatures with IdentityKey.verify()')

  } catch (error) {
    console.error('❌ Failed to export signing configuration:', error.message)
    
    if (error.message.includes('Identity not found')) {
      console.error('💡 Run "hyperident init" first to create an identity')
    } else if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    } else if (error.message.includes('Device chain is not valid')) {
      console.error('💡 Run "hyperident device verify" to check device chain')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle debug inspect command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDebugInspect(parsed) {
  try {
    console.log('🔍 Inspecting identity and system state...')
    
    // Check if passphrase is provided via flag
    let passphrase = null
    if (parsed.flags.includes('--passphrase')) {
      passphrase = await getPassphrase('🔐 Enter passphrase for encrypted identity.')
    }
    
    // Run identity inspection
    const inspection = await DebugManager.inspectIdentity(passphrase)
    
    console.log('✅ Identity inspection completed!')
    console.log('')
    console.log('📋 Inspection Results:')
    console.log(JSON.stringify(inspection, null, 2))
    
    // Provide summary
    console.log('')
    console.log('📊 Summary:')
    console.log(`   Identity Found: ${inspection.identity ? 'Yes' : 'No'}`)
    console.log(`   Device Chain: ${inspection.deviceChain ? 'Yes' : 'No'}`)
    console.log(`   Profiles: ${inspection.profiles ? Object.keys(inspection.profiles).length : 0}`)
    console.log(`   Errors: ${inspection.errors.length}`)
    
    if (inspection.errors.length > 0) {
      console.log('')
      console.log('⚠️  Issues Found:')
      inspection.errors.forEach((error, index) => {
        console.log(`   ${index + 1}. ${error}`)
      })
    }
    
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Run health check: hyperident debug health')
    console.log('   • Check network: hyperident debug network')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to inspect identity:', error.message)
    
    if (error.message.includes('Invalid passphrase')) {
      console.error('💡 Please check your passphrase and try again')
    }
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle debug health command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDebugHealth(parsed) {
  try {
    console.log('🏥 Running comprehensive health check...')
    
    // Run health check
    const healthCheck = await DebugManager.healthCheck()
    
    console.log('✅ Health check completed!')
    console.log('')
    console.log('📋 Health Check Results:')
    console.log(JSON.stringify(healthCheck, null, 2))
    
    // Provide summary
    console.log('')
    console.log('📊 Health Summary:')
    console.log(`   Overall Status: ${healthCheck.status}`)
    console.log(`   Identity Health: ${healthCheck.identity?.status || 'Unknown'}`)
    console.log(`   Device Health: ${healthCheck.device?.status || 'Unknown'}`)
    console.log(`   Files Health: ${healthCheck.files?.status || 'Unknown'}`)
    console.log(`   System Health: ${healthCheck.system?.status || 'Unknown'}`)
    
    if (healthCheck.issues && healthCheck.issues.length > 0) {
      console.log('')
      console.log('⚠️  Health Issues:')
      healthCheck.issues.forEach((issue, index) => {
        console.log(`   ${index + 1}. ${issue.severity}: ${issue.message}`)
      })
    }
    
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Inspect identity: hyperident debug inspect')
    console.log('   • Check trust: hyperident debug trust')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to run health check:', error.message)
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle debug network command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDebugNetwork(parsed) {
  try {
    console.log('🌐 Running network diagnostics...')
    
    // Run network diagnostics
    const networkDiag = await DebugManager.runNetworkDiagnostics()
    
    console.log('✅ Network diagnostics completed!')
    console.log('')
    console.log('📋 Network Diagnostics Results:')
    console.log(JSON.stringify(networkDiag, null, 2))
    
    // Provide summary
    console.log('')
    console.log('📊 Network Summary:')
    console.log(`   Dependencies: ${networkDiag.dependencies?.status || 'Unknown'}`)
    console.log(`   Connectivity: ${networkDiag.connectivity?.status || 'Unknown'}`)
    console.log(`   DHT Status: ${networkDiag.dht?.status || 'Unknown'}`)
    console.log(`   Swarm Status: ${networkDiag.swarm?.status || 'Unknown'}`)
    
    if (networkDiag.issues && networkDiag.issues.length > 0) {
      console.log('')
      console.log('⚠️  Network Issues:')
      networkDiag.issues.forEach((issue, index) => {
        console.log(`   ${index + 1}. ${issue.severity}: ${issue.message}`)
      })
    }
    
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Check system info: hyperident debug system')
    console.log('   • Run health check: hyperident debug health')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to run network diagnostics:', error.message)
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle debug trust command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDebugTrust(parsed) {
  try {
    console.log('🔐 Verifying trust relationships...')
    
    // Run trust verification
    const trustVerification = await DebugManager.verifyTrust()
    
    console.log('✅ Trust verification completed!')
    console.log('')
    console.log('📋 Trust Verification Results:')
    console.log(JSON.stringify(trustVerification, null, 2))
    
    // Provide summary
    console.log('')
    console.log('📊 Trust Summary:')
    console.log(`   Identity Trust: ${trustVerification.identity?.status || 'Unknown'}`)
    console.log(`   Device Trust: ${trustVerification.device?.status || 'Unknown'}`)
    console.log(`   Chain Trust: ${trustVerification.chain?.status || 'Unknown'}`)
    console.log(`   Signature Trust: ${trustVerification.signatures?.status || 'Unknown'}`)
    
    if (trustVerification.issues && trustVerification.issues.length > 0) {
      console.log('')
      console.log('⚠️  Trust Issues:')
      trustVerification.issues.forEach((issue, index) => {
        console.log(`   ${index + 1}. ${issue.severity}: ${issue.message}`)
      })
    }
    
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Inspect identity: hyperident debug inspect')
    console.log('   • Run health check: hyperident debug health')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to verify trust:', error.message)
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Handle debug system command
 * @param {Object} parsed - Parsed command arguments
 */
async function handleDebugSystem(parsed) {
  try {
    console.log('💻 Gathering system information...')
    
    // Get system information
    const systemInfo = await DebugManager.getSystemInfo()
    
    console.log('✅ System information gathered!')
    console.log('')
    console.log('📋 System Information:')
    console.log(JSON.stringify(systemInfo, null, 2))
    
    // Provide summary
    console.log('')
    console.log('📊 System Summary:')
    console.log(`   Platform: ${systemInfo.node?.platform || 'Unknown'}`)
    console.log(`   Node.js: ${systemInfo.node?.version || 'Unknown'}`)
    console.log(`   Architecture: ${systemInfo.node?.arch || 'Unknown'}`)
    console.log(`   Memory: ${systemInfo.memory ? `${Math.round(systemInfo.memory.heapUsed / 1024 / 1024)}MB used / ${Math.round(systemInfo.memory.heapTotal / 1024 / 1024)}MB total` : 'Unknown'}`)
    console.log(`   Hyperident: ${systemInfo.hyperident?.version || 'Unknown'}`)
    
    if (systemInfo.dependencies) {
      console.log('')
      console.log('📦 Dependencies:')
      Object.entries(systemInfo.dependencies).forEach(([name, info]) => {
        console.log(`   ${name}: ${info.status} ${info.version ? `(${info.version})` : ''}`)
      })
    }
    
    console.log('')
    console.log('🚀 Next steps:')
    console.log('   • Run network diagnostics: hyperident debug network')
    console.log('   • Run health check: hyperident debug health')
    console.log('   • Get help: hyperident --help')

  } catch (error) {
    console.error('❌ Failed to gather system information:', error.message)
    
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

/**
 * Helper function to get passphrase input
 * @param {string} prompt - Prompt message
 * @returns {Promise<string>} Entered passphrase
 */
async function getPassphrase(prompt) {
  // Import readline for passphrase input
  const readline = await import('readline')
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  })

  // Helper function to get hidden input
  const getHiddenInput = (promptText) => {
    return new Promise((resolve) => {
      process.stdout.write(promptText + '\nEnter passphrase: ')
      process.stdin.setRawMode(true)
      process.stdin.resume()
      process.stdin.setEncoding('utf8')
      
      let input = ''
      const onData = (char) => {
        if (char === '\u0003') { // Ctrl+C
          process.exit(1)
        } else if (char === '\r' || char === '\n') {
          process.stdin.setRawMode(false)
          process.stdin.pause()
          process.stdin.removeListener('data', onData)
          process.stdout.write('\n')
          resolve(input)
        } else if (char === '\u007f') { // Backspace
          if (input.length > 0) {
            input = input.slice(0, -1)
            process.stdout.write('\b \b')
          }
        } else {
          input += char
          process.stdout.write('*')
        }
      }
      
      process.stdin.on('data', onData)
    })
  }

  const passphrase = await getHiddenInput(prompt)
  rl.close()
  return passphrase
}

/**
 * Parse command line arguments
 * @param {string[]} argv - Process arguments
 * @returns {Object} Parsed arguments
 */
function parseArgs(argv) {
  const args = argv.slice(2) // Remove 'node' and script name
  
  if (args.length === 0) {
    return { command: 'help', flags: [], positional: [], raw: [] }
  }

  const command = args[0]
  const flags = []
  const positional = []

  for (let i = 1; i < args.length; i++) {
    const arg = args[i]
    if (arg.startsWith('--') || arg.startsWith('-')) {
      flags.push(arg)
      
      // Check if this flag expects a value (like --device-name or --timeout)
      if ((arg === '--device-name' || arg === '--timeout') && i + 1 < args.length && !args[i + 1].startsWith('--')) {
        // Add the value as the next flag for easy extraction
        flags.push(args[i + 1])
        i++ // Skip the next argument since we consumed it
      }
    } else {
      positional.push(arg)
    }
  }

  return {
    command,
    flags,
    positional,
    raw: args
  }
}

/**
 * Validate command arguments
 * @param {Object} parsed - Parsed arguments
 * @returns {Object} Validation result
 */
function validateArgs(parsed) {
  const { command, flags, positional } = parsed

  switch (command) {
    case 'init':
      // Validate init command
      const validInitFlags = ['--with-passphrase', '--device-name']
      
      // Filter out device name values when validating flags
      const deviceNameIndex = flags.indexOf('--device-name')
      let flagsToValidate = [...flags]
      if (deviceNameIndex !== -1 && deviceNameIndex + 1 < flags.length) {
        // Remove the device name value from validation
        flagsToValidate.splice(deviceNameIndex + 1, 1)
      }
      
      const invalidFlags = flagsToValidate.filter(flag => !validInitFlags.includes(flag))
      if (invalidFlags.length > 0) {
        return { valid: false, error: `Invalid flag(s) for init: ${invalidFlags.join(', ')}` }
      }
      
      // Check if --device-name has a value
      if (deviceNameIndex !== -1) {
        if (deviceNameIndex + 1 >= flags.length || flags[deviceNameIndex + 1].startsWith('--')) {
          return { valid: false, error: '--device-name flag requires a value' }
        }
      }
      
      if (positional.length > 0) {
        return { valid: false, error: 'Init command does not accept positional arguments' }
      }
      break

    case 'create-profile':
      // Validate create-profile command
      if (positional.length === 0) {
        return { valid: false, error: 'Profile name is required for create-profile command' }
      }
      if (positional.length > 2) {
        return { valid: false, error: 'Too many arguments for create-profile command' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Create-profile command does not accept flags' }
      }
      break

    case 'list-profiles':
      // Validate list-profiles command
      if (positional.length > 0) {
        return { valid: false, error: 'List-profiles command does not accept arguments' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'List-profiles command does not accept flags' }
      }
      break

    case 'delete-profile':
      // Validate delete-profile command
      if (positional.length === 0) {
        return { valid: false, error: 'Profile name is required for delete-profile command' }
      }
      if (positional.length > 1) {
        return { valid: false, error: 'Too many arguments for delete-profile command' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Delete-profile command does not accept flags' }
      }
      break

    case 'address':
      // Validate address command
      if (positional.length === 0) {
        return { valid: false, error: 'Profile name is required for address command' }
      }
      if (positional.length > 1) {
        return { valid: false, error: 'Too many arguments for address command' }
      }
      const validAddressFlags = ['--cached']
      const invalidAddressFlags = flags.filter(flag => !validAddressFlags.includes(flag))
      if (invalidAddressFlags.length > 0) {
        return { valid: false, error: `Invalid flag(s) for address: ${invalidAddressFlags.join(', ')}` }
      }
      break

    case 'refresh-addresses':
      // Validate refresh-addresses command
      if (positional.length > 0) {
        return { valid: false, error: 'Refresh-addresses command does not accept arguments' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Refresh-addresses command does not accept flags' }
      }
      break

    case 'export-addresses':
      // Validate export-addresses command
      if (positional.length > 1) {
        return { valid: false, error: 'Too many arguments for export-addresses command' }
      }
      const validExportFlags = ['--enhanced']
      const invalidExportFlags = flags.filter(flag => !validExportFlags.includes(flag))
      if (invalidExportFlags.length > 0) {
        return { valid: false, error: `Invalid flag(s) for export-addresses: ${invalidExportFlags.join(', ')}` }
      }
      break

    case 'sign':
      // Validate sign command
      if (positional.length === 0) {
        return { valid: false, error: 'File path is required for sign command' }
      }
      if (positional.length > 1) {
        return { valid: false, error: 'Too many arguments for sign command' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Sign command does not accept flags' }
      }
      break

    case 'verify':
      // Validate verify command
      if (positional.length < 2) {
        return { valid: false, error: 'Both signature file and original file are required for verify command' }
      }
      if (positional.length > 2) {
        return { valid: false, error: 'Too many arguments for verify command' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Verify command does not accept flags' }
      }
      break

    case 'export-signing-config':
      // Validate export-signing-config command
      if (positional.length > 0) {
        return { valid: false, error: 'Export-signing-config command does not accept arguments' }
      }
      if (flags.length > 0) {
        return { valid: false, error: 'Export-signing-config command does not accept flags' }
      }
      break

    case 'device':
      // Validate device command
      if (positional.length === 0) {
        return { valid: false, error: 'Device subcommand is required (list, export, import, verify)' }
      }
      
      const deviceSubcommand = positional[0]
      const validDeviceSubcommands = ['list', 'export', 'import', 'verify', 'bootstrap', 'create-network', 'share', 'join', 'status', 'sync', 'mesh', 'revoke']
      
      if (!validDeviceSubcommands.includes(deviceSubcommand)) {
        return { valid: false, error: `Invalid device subcommand: ${deviceSubcommand}` }
      }
      
      // Validate device mesh specifically
      if (deviceSubcommand === 'mesh') {
        if (positional.length < 2) {
          return { valid: false, error: 'Device mesh requires a subcommand (join, leave)' }
        }
        
        const meshSubcommand = positional[1]
        const validMeshSubcommands = ['join', 'leave']
        
        if (!validMeshSubcommands.includes(meshSubcommand)) {
          return { valid: false, error: `Invalid mesh subcommand: ${meshSubcommand}` }
        }
      }
      
      // Validate device revoke specifically
      if (deviceSubcommand === 'revoke') {
        if (positional.length < 2) {
          return { valid: false, error: 'Device revoke requires a device ID' }
        }
      }
      
      // Validate device import specifically
      if (deviceSubcommand === 'import') {
        if (positional.length < 2) {
          return { valid: false, error: 'Device import requires a bundle file' }
        }
        
        // Check for --device-name flag
        const deviceNameIndex = flags.indexOf('--device-name')
        if (deviceNameIndex === -1) {
          return { valid: false, error: 'Device import requires --device-name flag' }
        }
        
        if (deviceNameIndex + 1 >= flags.length || flags[deviceNameIndex + 1].startsWith('--')) {
          return { valid: false, error: '--device-name flag requires a value' }
        }
      }
      
      // Validate device join specifically
      if (deviceSubcommand === 'join') {
        if (positional.length < 2) {
          return { valid: false, error: 'Device join requires a sharing code' }
        }
        
        // Check for --device-name flag
        const deviceNameIndex = flags.indexOf('--device-name')
        if (deviceNameIndex === -1) {
          return { valid: false, error: 'Device join requires --device-name flag' }
        }
        
        if (deviceNameIndex + 1 >= flags.length || flags[deviceNameIndex + 1].startsWith('--')) {
          return { valid: false, error: '--device-name flag requires a value' }
        }
      }
      
      // Validate device share specifically
      if (deviceSubcommand === 'share') {
        // Check for --timeout flag if present
        const timeoutIndex = flags.indexOf('--timeout')
        if (timeoutIndex !== -1) {
          if (timeoutIndex + 1 >= flags.length || flags[timeoutIndex + 1].startsWith('--')) {
            return { valid: false, error: '--timeout flag requires a value' }
          }
          
          const timeoutValue = parseInt(flags[timeoutIndex + 1])
          if (isNaN(timeoutValue) || timeoutValue <= 0) {
            return { valid: false, error: '--timeout value must be a positive number' }
          }
        }
      }
      break

    case 'debug':
      // Validate debug command
      if (positional.length === 0) {
        return { valid: false, error: 'Debug subcommand is required (inspect, health, network, trust, system)' }
      }
      
      const debugSubcommand = positional[0]
      const validDebugSubcommands = ['inspect', 'health', 'network', 'trust', 'system']
      
      if (!validDebugSubcommands.includes(debugSubcommand)) {
        return { valid: false, error: `Invalid debug subcommand: ${debugSubcommand}` }
      }
      
      // Validate debug inspect specifically
      if (debugSubcommand === 'inspect') {
        const validInspectFlags = ['--passphrase']
        const invalidInspectFlags = flags.filter(flag => !validInspectFlags.includes(flag))
        if (invalidInspectFlags.length > 0) {
          return { valid: false, error: `Invalid flag(s) for debug inspect: ${invalidInspectFlags.join(', ')}` }
        }
      } else {
        // Other debug commands don't accept flags
        if (flags.length > 0) {
          return { valid: false, error: `Debug ${debugSubcommand} command does not accept flags` }
        }
      }
      
      // Debug commands don't accept additional positional arguments
      if (positional.length > 1) {
        return { valid: false, error: `Too many arguments for debug ${debugSubcommand} command` }
      }
      break

    case 'help':
    case '--help':
    case '-h':
    case 'version':
    case '--version':
    case '-v':
      // These commands are always valid
      break

    default:
      return { valid: false, error: `Unknown command: ${command}` }
  }

  return { valid: true }
}

/**
 * Display error with helpful suggestions
 * @param {string} error - Error message
 * @param {string} command - Command that failed
 */
function displayError(error, command = null) {
  console.error(`❌ Error: ${error}`)
  
  // Provide helpful suggestions based on the error
  if (command) {
    switch (command) {
      case 'create-profile':
        console.error('💡 Usage: hyperident create-profile <name> [description]')
        console.error('   Example: hyperident create-profile work "Work profile"')
        break
      case 'delete-profile':
        console.error('💡 Usage: hyperident delete-profile <name>')
        console.error('   Example: hyperident delete-profile work')
        break
      case 'init':
        console.error('💡 Usage: hyperident init [--with-passphrase]')
        break
      default:
        console.error('💡 Use "hyperident --help" for usage information')
    }
  } else {
    console.error('💡 Use "hyperident --help" for usage information')
  }
}

// Background OTA via pgh — content-addressed store, NO Hyperdrive/blobs.
// `pgh app update <name>` resolves the latest release from package.json's
// pgh.upgrade, fetches any new tree closure into the content store, and
// ATOMICALLY materializes it into the install dir (scratch build + swap),
// safe to run while a command executes. This replaces the former pear-runtime
// Hyperdrive updater, which kept an unbounded append-only blob corestore under
// ~/.config/hyperident/pear-runtime (it grew on every release and — because
// initPearRuntime was called unconditionally — on every CLI invocation).
async function startBackgroundUpdate () {
  try {
    const fs = (await import('fs')).default
    const path = (await import('path')).default
    const os = (await import('os')).default
    const appDir = path.dirname(new URL(import.meta.url).pathname)
    const pkg = JSON.parse(fs.readFileSync(path.join(appDir, 'package.json'), 'utf-8'))
    const upgrade = pkg.pgh && pkg.pgh.upgrade
    if (!upgrade) return
    const appName = (pkg.pgh && pkg.pgh.bin) || pkg.name || 'hyperident'

    // Resolve the pgh CLI: prefer ~/.local/bin/pgh, else the store-installed
    // bare runtime + entry. Bail if pgh isn't on this machine (e.g. dev source).
    let argv = null
    const launcher = path.join(os.homedir(), '.local', 'bin', 'pgh')
    if (fs.existsSync(launcher)) argv = [launcher]
    else {
      const storeRoot = process.env.PGH_STORE_ROOT || path.join(os.homedir(), '.local', 'share', 'store')
      const bare = path.join(storeRoot, 'apps', 'pgh', 'runtime', 'bare')
      const entry = path.join(storeRoot, 'apps', 'pgh', 'bin', 'pgh.bare.js')
      if (fs.existsSync(bare) && fs.existsSync(entry)) argv = [bare, entry]
    }
    if (!argv) return

    // Cross-runtime spawn via the imports-map bridge: child_process → bare-subprocess
    // under bare (deployed installs), node's child_process under node (dev). Both
    // provide spawn(); failure here is caught and OTA is silently skipped.
    const subprocess = (await import('child_process')).default || (await import('child_process'))
    const proc = subprocess.spawn(argv[0], [...argv.slice(1), 'app', 'update', appName], {
      stdio: 'ignore',
      detached: true
    })
    proc.on('error', () => {})
    if (proc.unref) proc.unref()
  } catch {}
}

/**
 * Main CLI entry point
 */
async function main() {
  // Start background OTA via pgh (content-addressed, non-blocking, best-effort).
  // Gated so it never fires on `--no-updates`. Unlike the old pear-runtime path,
  // this no longer balloons a corestore — and it only spawns when pgh + a
  // pgh.upgrade link are both present (i.e. a real pgh install).
  if (!process.argv.includes('--no-updates')) startBackgroundUpdate()

  try {
    const parsed = parseArgs(process.argv)

    // Validate arguments before processing
    const validation = validateArgs(parsed)
    if (!validation.valid) {
      displayError(validation.error, parsed.command)
      process.exit(1)
    }
    
    switch (parsed.command) {
      case 'init':
        await handleInit(parsed)
        break
      
      case 'create-profile':
        await handleCreateProfile(parsed)
        break
      
      case 'list-profiles':
        await handleListProfiles(parsed)
        break
      
      case 'delete-profile':
        await handleDeleteProfile(parsed)
        break
      
      case 'address':
        await handleAddress(parsed)
        break
      
      case 'refresh-addresses':
        await handleRefreshAddresses(parsed)
        break
      
      case 'export-addresses':
        await handleExportAddresses(parsed)
        break
      
      case 'sign':
        await handleSign(parsed)
        break
      
      case 'verify':
        await handleVerify(parsed)
        break
      
      case 'export-signing-config':
        await handleExportSigningConfig(parsed)
        break
      
      case 'debug':
        // Handle debug subcommands
        const debugSubcommand = parsed.positional[0]
        switch (debugSubcommand) {
          case 'inspect':
            await handleDebugInspect(parsed)
            break
          case 'health':
            await handleDebugHealth(parsed)
            break
          case 'network':
            await handleDebugNetwork(parsed)
            break
          case 'trust':
            await handleDebugTrust(parsed)
            break
          case 'system':
            await handleDebugSystem(parsed)
            break
          default:
            displayError(`Unknown debug subcommand: ${debugSubcommand || '(none)'}`)
            console.error('💡 Available debug commands: inspect, health, network, trust, system')
            process.exit(1)
        }
        break
      
      case 'device':
        // Handle device subcommands
        const deviceSubcommand = parsed.positional[0]
        switch (deviceSubcommand) {
          case 'list':
            await handleDeviceList(parsed)
            break
          case 'export':
            await handleDeviceExport(parsed)
            break
          case 'import':
            await handleDeviceImport(parsed)
            break
          case 'verify':
            await handleDeviceVerify(parsed)
            break
          case 'bootstrap':
            await handleDeviceBootstrap(parsed)
            break
          case 'create-network':
            await handleDeviceCreateNetwork(parsed)
            break
          case 'share':
            await handleDeviceShare(parsed)
            break
          case 'join':
            await handleDeviceJoin(parsed)
            break
          case 'status':
            await handleDeviceStatus(parsed)
            break
          case 'sync':
            await handleDeviceSync(parsed)
            break
          case 'mesh':
            // Handle mesh subcommands
            const meshSubcommand = parsed.positional[1]
            switch (meshSubcommand) {
              case 'join':
                await handleDeviceMeshJoin(parsed)
                break
              case 'leave':
                await handleDeviceMeshLeave(parsed)
                break
              default:
                displayError(`Unknown mesh subcommand: ${meshSubcommand || '(none)'}`)
                console.error('💡 Available mesh commands: join, leave')
                process.exit(1)
            }
            break
          case 'revoke':
            await handleDeviceRevoke(parsed)
            break
          default:
            displayError(`Unknown device subcommand: ${deviceSubcommand || '(none)'}`)
            console.error('💡 Available device commands: list, export, import, verify, share, join, status, sync, mesh, revoke')
            process.exit(1)
        }
        break
      
      case '--help':
      case '-h':
      case 'help':
        showHelp()
        break
      
      case '--version':
      case '-v':
      case 'version':
        showVersion()
        break
      
      default:
        displayError(`Unknown command: ${parsed.command}`)
        process.exit(1)
    }
  } catch (error) {
    console.error('❌ Error:', error.message)
    if (process.env.DEBUG) {
      console.error(error.stack)
    }
    process.exit(2)
  }
}

// Run CLI if this file is executed directly
const argv = typeof process !== 'undefined' ? process.argv : (typeof Bare !== 'undefined' ? Bare.argv : [])
if (argv[1] && import.meta.url === `file://${argv[1]}`) {
  main()
} else if (typeof Bare !== 'undefined') {
  main()
}

export { main, parseArgs, validateArgs, displayError, showHelp, showVersion, handleInit, handleCreateProfile, handleListProfiles, handleDeleteProfile, handleAddress }