@@ -95,20 +95,23 @@ def launch_command(args: argparse.Namespace, claude_args: Optional[List[str]] =
9595 Returns:
9696 Exit code.
9797 """
98- # Handle backwards compatibility: Check for deprecated --use-graph-mem flag
99- use_graph_mem = getattr (args , "use_graph_mem " , False )
98+ # Handle graph backend selection (new unified approach)
99+ graph_backend = getattr (args , "graph_backend " , "auto" )
100100 enable_neo4j = getattr (args , "enable_neo4j_memory" , False )
101-
102- # Set environment variable for Neo4j opt-in (Why: Makes flag accessible to session hooks and launcher)
103- if use_graph_mem or enable_neo4j :
101+ use_graph_mem = getattr (args , "use_graph_mem" , False ) # Deprecated
102+
103+ # Set environment variable for graph backend selection
104+ if graph_backend != "auto" :
105+ os .environ ["AMPLIHACK_GRAPH_BACKEND" ] = graph_backend
106+ print (f"Graph backend set to: { graph_backend } " )
107+ elif enable_neo4j or use_graph_mem :
108+ os .environ ["AMPLIHACK_GRAPH_BACKEND" ] = "neo4j"
104109 os .environ ["AMPLIHACK_ENABLE_NEO4J_MEMORY" ] = "1"
105110 if use_graph_mem :
106111 print (
107- "WARNING: --use-graph-mem is deprecated. Please use --enable- neo4j-memory instead."
112+ "WARNING: --use-graph-mem is deprecated. Please use --graph-backend neo4j instead."
108113 )
109- print ("Neo4j graph memory enabled via --use-graph-mem flag (deprecated)" )
110- else :
111- print ("Neo4j graph memory enabled via --enable-neo4j-memory flag" )
114+ print ("Graph backend set to: neo4j" )
112115
113116 # Set container name if provided
114117 if getattr (args , "use_memory_db" , None ):
@@ -244,7 +247,9 @@ def handle_auto_mode(
244247 # Extract timeout from args
245248 query_timeout = getattr (args , "query_timeout_minutes" , 5.0 )
246249
247- auto = AutoMode (sdk , prompt , args .max_turns , ui_mode = ui_mode , query_timeout_minutes = query_timeout )
250+ auto = AutoMode (
251+ sdk , prompt , args .max_turns , ui_mode = ui_mode , query_timeout_minutes = query_timeout
252+ )
248253 return auto .run ()
249254
250255
@@ -427,6 +432,30 @@ def add_neo4j_args(parser: argparse.ArgumentParser) -> None:
427432 )
428433
429434
435+ def add_graph_backend_args (parser : argparse .ArgumentParser ) -> None :
436+ """Add graph backend selection arguments to a parser.
437+
438+ Args:
439+ parser: ArgumentParser to add arguments to.
440+ """
441+ parser .add_argument (
442+ "--graph-backend" ,
443+ choices = ["kuzu" , "neo4j" , "auto" ],
444+ default = "auto" ,
445+ metavar = "BACKEND" ,
446+ help = (
447+ "Select graph database backend for memory system. "
448+ "Options: kuzu (embedded, zero-config), neo4j (Docker), auto (default). "
449+ "Kùzu is auto-installed if needed."
450+ ),
451+ )
452+ parser .add_argument (
453+ "--enable-neo4j-memory" ,
454+ action = "store_true" ,
455+ help = "Enable Neo4j graph memory (alias for --graph-backend neo4j)." ,
456+ )
457+
458+
430459def create_parser () -> argparse .ArgumentParser :
431460 """Create the argument parser for amplihack CLI.
432461
@@ -469,25 +498,27 @@ def create_parser() -> argparse.ArgumentParser:
469498 add_claude_specific_args (launch_parser )
470499 add_auto_mode_args (launch_parser )
471500 add_neo4j_args (launch_parser )
501+ add_graph_backend_args (launch_parser )
472502 add_common_sdk_args (launch_parser )
473503 launch_parser .add_argument (
474504 "--profile" ,
475505 type = str ,
476506 default = None ,
477- help = "Profile URI to use for this launch (overrides configured profile)"
507+ help = "Profile URI to use for this launch (overrides configured profile)" ,
478508 )
479509
480510 # Claude command (alias for launch)
481511 claude_parser = subparsers .add_parser ("claude" , help = "Launch Claude Code (alias for launch)" )
482512 add_claude_specific_args (claude_parser )
483513 add_auto_mode_args (claude_parser )
484514 add_neo4j_args (claude_parser )
515+ add_graph_backend_args (claude_parser )
485516 add_common_sdk_args (claude_parser )
486517 claude_parser .add_argument (
487518 "--profile" ,
488519 type = str ,
489520 default = None ,
490- help = "Profile URI to use for this launch (overrides configured profile)"
521+ help = "Profile URI to use for this launch (overrides configured profile)" ,
491522 )
492523
493524 # Copilot command
@@ -547,7 +578,7 @@ def create_parser() -> argparse.ArgumentParser:
547578 "--profile" ,
548579 type = str ,
549580 default = None ,
550- help = "Profile URI to use for this install (overrides configured profile)"
581+ help = "Profile URI to use for this install (overrides configured profile)" ,
551582 )
552583
553584 return parser
@@ -610,7 +641,7 @@ def main(argv: Optional[List[str]] = None) -> int:
610641 # Find the amplihack package location
611642 import amplihack
612643
613- from . import copytree_manifest , ESSENTIAL_DIRS
644+ from . import ESSENTIAL_DIRS , copytree_manifest
614645
615646 amplihack_src = os .path .dirname (os .path .abspath (amplihack .__file__ ))
616647
@@ -625,21 +656,19 @@ def main(argv: Optional[List[str]] = None) -> int:
625656 if os .path .exists (claude_tools_path ):
626657 sys .path .insert (0 , claude_tools_path )
627658 from profile_management .staging import create_staging_manifest
659+
628660 manifest = create_staging_manifest (ESSENTIAL_DIRS , profile_uri )
629- if manifest .profile_name != "all" and not manifest .profile_name .endswith ("(fallback)" ):
661+ if manifest .profile_name != "all" and not manifest .profile_name .endswith (
662+ "(fallback)"
663+ ):
630664 print (f"📦 Using profile: { manifest .profile_name } " )
631665 except Exception as e :
632666 # Fall back to full staging on errors
633667 print (f"ℹ️ Profile loading failed ({ e } ), using full staging" )
634668
635669 # Copy .claude contents to temp .claude directory
636670 # Note: copytree_manifest copies TO the dst, not INTO dst/.claude
637- copied = copytree_manifest (
638- amplihack_src ,
639- temp_claude_dir ,
640- ".claude" ,
641- manifest = manifest
642- )
671+ copied = copytree_manifest (amplihack_src , temp_claude_dir , ".claude" , manifest = manifest )
643672
644673 # Smart PROJECT.md initialization for UVX mode
645674 if copied :
@@ -672,12 +701,12 @@ def main(argv: Optional[List[str]] = None) -> int:
672701 def replace_paths (obj ):
673702 if isinstance (obj , dict ):
674703 for key , value in obj .items ():
675- if key == "command" and isinstance (value , str ) and value .startswith (
676- ".claude/"
704+ if (
705+ key == "command"
706+ and isinstance (value , str )
707+ and value .startswith (".claude/" )
677708 ):
678- obj [key ] = value .replace (
679- ".claude/" , "$CLAUDE_PROJECT_DIR/.claude/"
680- )
709+ obj [key ] = value .replace (".claude/" , "$CLAUDE_PROJECT_DIR/.claude/" )
681710 else :
682711 replace_paths (value )
683712 elif isinstance (obj , list ):
@@ -761,21 +790,20 @@ def replace_paths(obj):
761790 # _local_install expects repo root, so pass package_dir (which contains .claude/)
762791 _local_install (str (package_dir ))
763792 return 0
764- else :
765- # Fallback: Clone from GitHub (for old installations)
766- import subprocess
767- import tempfile
768-
769- print ("⚠️ Package .claude/ not found, cloning from GitHub..." )
770- with tempfile .TemporaryDirectory () as tmp :
771- repo_url = "https://github.com/rysweet/MicrosoftHackathon2025-AgenticCoding"
772- try :
773- subprocess .check_call (["git" , "clone" , "--depth" , "1" , repo_url , tmp ])
774- _local_install (tmp )
775- return 0
776- except subprocess .CalledProcessError as e :
777- print (f"Failed to install: { e } " )
778- return 1
793+ # Fallback: Clone from GitHub (for old installations)
794+ import subprocess
795+ import tempfile
796+
797+ print ("⚠️ Package .claude/ not found, cloning from GitHub..." )
798+ with tempfile .TemporaryDirectory () as tmp :
799+ repo_url = "https://github.com/rysweet/MicrosoftHackathon2025-AgenticCoding"
800+ try :
801+ subprocess .check_call (["git" , "clone" , "--depth" , "1" , repo_url , tmp ])
802+ _local_install (tmp )
803+ return 0
804+ except subprocess .CalledProcessError as e :
805+ print (f"Failed to install: { e } " )
806+ return 1
779807
780808 elif args .command == "uninstall" :
781809 uninstall ()
0 commit comments