@@ -85,6 +85,18 @@ enum Command {
8585 /// Override a model: --model embed|rerank|expand <uri>
8686 #[ arg( long, num_args = 2 , value_names = & [ "TYPE" , "URI" ] ) ]
8787 model : Option < Vec < String > > ,
88+
89+ /// Enable Obsidian CLI integration.
90+ #[ arg( long, conflicts_with = "disable_obsidian_cli" ) ]
91+ enable_obsidian_cli : bool ,
92+
93+ /// Disable Obsidian CLI integration.
94+ #[ arg( long, conflicts_with = "enable_obsidian_cli" ) ]
95+ disable_obsidian_cli : bool ,
96+
97+ /// Register with an AI agent: "claude-code", "cursor", or "windsurf".
98+ #[ arg( long) ]
99+ register : Option < String > ,
88100 } ,
89101
90102 /// Manage embedding models.
@@ -496,7 +508,7 @@ async fn main() -> Result<()> {
496508 println ! ( " Max folder depth: {}" , stats. folder_depth) ;
497509
498510 let vault_profile = profile:: VaultProfile {
499- vault_path,
511+ vault_path : vault_path . clone ( ) ,
500512 vault_type,
501513 structure,
502514 stats,
@@ -515,12 +527,105 @@ async fn main() -> Result<()> {
515527 cfg. intelligence = Some ( enable) ;
516528 cfg. save ( ) ?;
517529 }
530+
531+ // Obsidian CLI detection
532+ let obsidian_running = std:: process:: Command :: new ( "pgrep" )
533+ . args ( [ "-x" , "Obsidian" ] )
534+ . stdout ( std:: process:: Stdio :: null ( ) )
535+ . stderr ( std:: process:: Stdio :: null ( ) )
536+ . status ( )
537+ . map ( |s| s. success ( ) )
538+ . unwrap_or ( false ) ;
539+
540+ let obsidian_in_path = std:: process:: Command :: new ( "which" )
541+ . arg ( "obsidian" )
542+ . stdout ( std:: process:: Stdio :: null ( ) )
543+ . stderr ( std:: process:: Stdio :: null ( ) )
544+ . status ( )
545+ . map ( |s| s. success ( ) )
546+ . unwrap_or ( false ) ;
547+
548+ if obsidian_running && obsidian_in_path {
549+ eprint ! ( "\n Obsidian CLI detected. Enable integration? [Y/n] " ) ;
550+ io:: stderr ( ) . flush ( ) ?;
551+ let mut answer = String :: new ( ) ;
552+ io:: stdin ( ) . lock ( ) . read_line ( & mut answer) ?;
553+ let answer = answer. trim ( ) ;
554+ let enable = answer. is_empty ( ) || answer. eq_ignore_ascii_case ( "y" ) ;
555+ if enable {
556+ let vault_name = vault_path
557+ . file_name ( )
558+ . and_then ( |n| n. to_str ( ) )
559+ . unwrap_or ( "Personal" )
560+ . to_string ( ) ;
561+ cfg. obsidian . enabled = true ;
562+ cfg. obsidian . vault_name = Some ( vault_name. clone ( ) ) ;
563+ cfg. save ( ) ?;
564+ println ! ( "Obsidian CLI enabled (vault: {vault_name})." ) ;
565+ } else {
566+ println ! (
567+ "Obsidian CLI disabled. Enable later with: engraph configure --enable-obsidian-cli"
568+ ) ;
569+ }
570+ }
571+
572+ // AI agent detection
573+ let home = dirs:: home_dir ( ) . unwrap_or_default ( ) ;
574+ let agent_configs: & [ ( & str , & str , & str ) ] = & [
575+ (
576+ "Claude Code" ,
577+ "claude-code" ,
578+ ".claude/settings.json" ,
579+ ) ,
580+ ( "Cursor" , "cursor" , ".cursor/mcp.json" ) ,
581+ (
582+ "Windsurf" ,
583+ "windsurf" ,
584+ ".codeium/windsurf/mcp_config.json" ,
585+ ) ,
586+ ] ;
587+
588+ let mut detected: Vec < ( & str , & str , String ) > = Vec :: new ( ) ;
589+ for ( name, key, rel_path) in agent_configs {
590+ let full = home. join ( rel_path) ;
591+ if full. exists ( ) {
592+ detected. push ( ( name, key, format ! ( "~/{rel_path}" ) ) ) ;
593+ }
594+ }
595+
596+ if !detected. is_empty ( ) {
597+ println ! ( "\n AI agents detected:" ) ;
598+ for ( name, _key, path) in & detected {
599+ println ! ( " \u{2713} {name} ({path})" ) ;
600+ }
601+ println ! (
602+ "\n To register engraph as MCP server, add to your agent's config:\n \
603+ \" engraph\" : {{\n \
604+ \" command\" : \" engraph\" ,\n \
605+ \" args\" : [\" serve\" ]\n \
606+ }}"
607+ ) ;
608+
609+ // Record detected agents in config
610+ for ( _name, key, _path) in & detected {
611+ match * key {
612+ "claude-code" => cfg. agents . claude_code = true ,
613+ "cursor" => cfg. agents . cursor = true ,
614+ "windsurf" => cfg. agents . windsurf = true ,
615+ _ => { }
616+ }
617+ }
618+ cfg. save ( ) ?;
619+ }
518620 }
519621
520622 Command :: Configure {
521623 enable_intelligence,
522624 disable_intelligence,
523625 model,
626+ enable_obsidian_cli,
627+ disable_obsidian_cli,
628+ register,
524629 } => {
525630 let mut cfg = Config :: load ( ) ?;
526631
@@ -572,6 +677,54 @@ async fn main() -> Result<()> {
572677 }
573678 }
574679
680+ if enable_obsidian_cli {
681+ cfg. obsidian . enabled = true ;
682+ println ! ( "Obsidian CLI integration enabled." ) ;
683+ } else if disable_obsidian_cli {
684+ cfg. obsidian . enabled = false ;
685+ println ! ( "Obsidian CLI integration disabled." ) ;
686+ }
687+
688+ if let Some ( agent) = register {
689+ match agent. as_str ( ) {
690+ "claude-code" => {
691+ cfg. agents . claude_code = true ;
692+ println ! (
693+ "Registered Claude Code. Add to ~/.claude/settings.json:\n \
694+ \" engraph\" : {{\n \
695+ \" command\" : \" engraph\" ,\n \
696+ \" args\" : [\" serve\" ]\n \
697+ }}"
698+ ) ;
699+ }
700+ "cursor" => {
701+ cfg. agents . cursor = true ;
702+ println ! (
703+ "Registered Cursor. Add to ~/.cursor/mcp.json:\n \
704+ \" engraph\" : {{\n \
705+ \" command\" : \" engraph\" ,\n \
706+ \" args\" : [\" serve\" ]\n \
707+ }}"
708+ ) ;
709+ }
710+ "windsurf" => {
711+ cfg. agents . windsurf = true ;
712+ println ! (
713+ "Registered Windsurf. Add to ~/.codeium/windsurf/mcp_config.json:\n \
714+ \" engraph\" : {{\n \
715+ \" command\" : \" engraph\" ,\n \
716+ \" args\" : [\" serve\" ]\n \
717+ }}"
718+ ) ;
719+ }
720+ other => {
721+ anyhow:: bail!(
722+ "Unknown agent: {other}. Use: claude-code, cursor, or windsurf."
723+ ) ;
724+ }
725+ }
726+ }
727+
575728 cfg. save ( ) ?;
576729 println ! (
577730 "Configuration saved to {}" ,
0 commit comments