diff --git a/packages/claude-code-plugin/hooks/lib/stats.py b/packages/claude-code-plugin/hooks/lib/stats.py index 30717dbe..275552ec 100644 --- a/packages/claude-code-plugin/hooks/lib/stats.py +++ b/packages/claude-code-plugin/hooks/lib/stats.py @@ -40,7 +40,13 @@ def __init__(self, session_id: str, data_dir: Optional[str] = None, flush_interv self.data_dir = data_dir os.makedirs(self.data_dir, mode=0o700, exist_ok=True) # Fix permissions if dir already existed - os.chmod(self.data_dir, 0o700) + try: + os.chmod(self.data_dir, 0o700) + except OSError: + import sys + sys.stderr.write( + f"[codingbuddy] Warning: could not set permissions on {self.data_dir}\n" + ) self.stats_file = os.path.join(self.data_dir, f"{session_id}.json") diff --git a/packages/claude-code-plugin/tests/test_stats.py b/packages/claude-code-plugin/tests/test_stats.py index 40756240..0cb8b26a 100644 --- a/packages/claude-code-plugin/tests/test_stats.py +++ b/packages/claude-code-plugin/tests/test_stats.py @@ -51,6 +51,18 @@ def test_default_data_dir(self, monkeypatch): expected_dir = os.path.join(os.path.expanduser("~"), ".codingbuddy") assert os.path.isdir(expected_dir) + def test_chmod_failure_graceful(self, tmp_path, monkeypatch): + """chmod failure should not crash initialization.""" + d = str(tmp_path / "restricted_dir") + os.makedirs(d, mode=0o700) + + def failing_chmod(*args, **kwargs): + raise PermissionError("Operation not permitted") + + monkeypatch.setattr(os, "chmod", failing_chmod) + s = SessionStats(session_id="perm-test", data_dir=d) + assert os.path.isdir(d) + class TestRecordToolCall: def test_increments_count(self, stats):