1616
1717from rich .console import Console
1818
19+ from basic_memory .cli .commands .cloud .rclone_installer import is_rclone_installed
1920from basic_memory .utils import normalize_project_path
2021
2122console = Console ()
@@ -27,6 +28,21 @@ class RcloneError(Exception):
2728 pass
2829
2930
31+ def check_rclone_installed () -> None :
32+ """Check if rclone is installed and raise helpful error if not.
33+
34+ Raises:
35+ RcloneError: If rclone is not installed with installation instructions
36+ """
37+ if not is_rclone_installed ():
38+ raise RcloneError (
39+ "rclone is not installed.\n \n "
40+ "Install rclone by running: bm cloud setup\n "
41+ "Or install manually from: https://rclone.org/downloads/\n \n "
42+ "Windows users: Ensure you have a package manager installed (winget, chocolatey, or scoop)"
43+ )
44+
45+
3046@dataclass
3147class SyncProject :
3248 """Project configured for cloud sync.
@@ -124,8 +140,10 @@ def project_sync(
124140 True if sync succeeded, False otherwise
125141
126142 Raises:
127- RcloneError: If project has no local_sync_path configured
143+ RcloneError: If project has no local_sync_path configured or rclone not installed
128144 """
145+ check_rclone_installed ()
146+
129147 if not project .local_sync_path :
130148 raise RcloneError (f"Project { project .name } has no local_sync_path configured" )
131149
@@ -180,8 +198,10 @@ def project_bisync(
180198 True if bisync succeeded, False otherwise
181199
182200 Raises:
183- RcloneError: If project has no local_sync_path or needs --resync
201+ RcloneError: If project has no local_sync_path, needs --resync, or rclone not installed
184202 """
203+ check_rclone_installed ()
204+
185205 if not project .local_sync_path :
186206 raise RcloneError (f"Project { project .name } has no local_sync_path configured" )
187207
@@ -249,8 +269,10 @@ def project_check(
249269 True if files match, False if differences found
250270
251271 Raises:
252- RcloneError: If project has no local_sync_path configured
272+ RcloneError: If project has no local_sync_path configured or rclone not installed
253273 """
274+ check_rclone_installed ()
275+
254276 if not project .local_sync_path :
255277 raise RcloneError (f"Project { project .name } has no local_sync_path configured" )
256278
@@ -291,7 +313,10 @@ def project_ls(
291313
292314 Raises:
293315 subprocess.CalledProcessError: If rclone command fails
316+ RcloneError: If rclone is not installed
294317 """
318+ check_rclone_installed ()
319+
295320 remote_path = get_project_remote (project , bucket_name )
296321 if path :
297322 remote_path = f"{ remote_path } /{ path } "
0 commit comments