@@ -399,15 +399,21 @@ def _run_git_command(args: list[str], cwd: Path | None = None, *, env: dict[str,
399399 return subprocess .run (cmd , check = True , capture_output = True , text = True , env = env )
400400
401401
402- def sync_team_ai_directives (repo_url : str , project_root : Path , * , skip_tls : bool = False ) -> str :
403- """Clone or update the team-ai-directives repository under .specify/memory .
402+ def sync_team_ai_directives (repo_url : str , project_root : Path , * , skip_tls : bool = False ) -> tuple [ str , Path ] :
403+ """Clone or update the team-ai-directives repository.
404404
405- Returns a short status string describing the action performed.
405+ If repo_url is a local path, return it directly and skip cloning.
406+ Returns a tuple of (status, path_to_use).
406407 """
407408 repo_url = (repo_url or "" ).strip ()
408409 if not repo_url :
409410 raise ValueError ("Team AI directives repository URL cannot be empty" )
410411
412+ # Detect local path
413+ potential_path = Path (repo_url ).expanduser ()
414+ if potential_path .exists () and potential_path .is_dir ():
415+ return ("local" , potential_path .resolve ())
416+
411417 memory_root = project_root / ".specify" / "memory"
412418 memory_root .mkdir (parents = True , exist_ok = True )
413419 destination = memory_root / TEAM_DIRECTIVES_DIRNAME
@@ -432,14 +438,14 @@ def sync_team_ai_directives(repo_url: str, project_root: Path, *, skip_tls: bool
432438 _run_git_command (["remote" , "set-url" , "origin" , repo_url ], cwd = destination , env = git_env )
433439
434440 _run_git_command (["pull" , "--ff-only" ], cwd = destination , env = git_env )
435- return "updated"
441+ return ( "updated" , destination )
436442
437443 if destination .exists () and not any (destination .iterdir ()):
438444 shutil .rmtree (destination )
439445
440446 memory_root .mkdir (parents = True , exist_ok = True )
441447 _run_git_command (["clone" , repo_url , str (destination )], env = git_env )
442- return "cloned"
448+ return ( "cloned" , destination )
443449 except subprocess .CalledProcessError as exc :
444450 message = exc .stderr .strip () if exc .stderr else str (exc )
445451 raise RuntimeError (f"Git operation failed: { message } " ) from exc
@@ -1116,11 +1122,13 @@ def init(
11161122 suppress_warning = gateway_suppress_warning ,
11171123 )
11181124
1125+ resolved_team_directives : Path | None = None
11191126 if team_ai_directives and team_ai_directives .strip ():
11201127 tracker .start ("directives" , "syncing" )
11211128 try :
1122- directives_status = sync_team_ai_directives (team_ai_directives , project_path , skip_tls = skip_tls )
1123- tracker .complete ("directives" , directives_status )
1129+ status , resolved_path = sync_team_ai_directives (team_ai_directives , project_path , skip_tls = skip_tls )
1130+ resolved_team_directives = resolved_path
1131+ tracker .complete ("directives" , status )
11241132 except Exception as e :
11251133 tracker .error ("directives" , str (e ))
11261134 raise
@@ -1165,6 +1173,18 @@ def init(
11651173 # Final static tree (ensures finished state visible after Live context ends)
11661174 console .print (tracker .render ())
11671175 console .print ("\n [bold green]Project ready.[/bold green]" )
1176+
1177+ # Persist team directives path if available
1178+ if resolved_team_directives is None :
1179+ default_dir = project_path / ".specify" / "memory" / TEAM_DIRECTIVES_DIRNAME
1180+ if default_dir .exists ():
1181+ resolved_team_directives = default_dir
1182+
1183+ if resolved_team_directives is not None :
1184+ os .environ ["SPECIFY_TEAM_DIRECTIVES" ] = str (resolved_team_directives )
1185+ config_dir = project_path / ".specify" / "config"
1186+ config_dir .mkdir (parents = True , exist_ok = True )
1187+ (config_dir / "team_directives.path" ).write_text (str (resolved_team_directives ))
11681188
11691189 # Agent folder security notice
11701190 agent_folder_map = {
0 commit comments