Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Actions that can change local state include:
- creating, updating, syncing, importing, or deleting a slash command
- changing harness support settings

App-owned files live under `~/Library/Application Support/skill-manager` on macOS and XDG base directories on Linux.
App-owned files live under `~/.skill-manager` on macOS (with a legacy fallback to `~/Library/Application Support/skill-manager` if it already exists) and XDG base directories on Linux.

## How it works

Expand Down Expand Up @@ -242,17 +242,17 @@ CLI marketplace entries are preview-only.

## Configuration

On macOS, app-owned files live under `~/Library/Application Support/skill-manager`. On Linux, app-owned files use XDG base directories.
On macOS, app-owned files live under `~/.skill-manager` (with a legacy fallback to `~/Library/Application Support/skill-manager` if it already exists). On Linux, app-owned files use XDG base directories.

Useful macOS paths:

- shared skills store: `~/Library/Application Support/skill-manager/shared`
- MCP manifest: `~/Library/Application Support/skill-manager/mcp/manifest.json`
- slash command library: `~/Library/Application Support/skill-manager/slash-commands/commands`
- slash command sync state: `~/Library/Application Support/skill-manager/slash-commands/sync-state.json`
- marketplace cache: `~/Library/Application Support/skill-manager/marketplace`
- app database and LLM scan configs: `~/Library/Application Support/skill-manager/skill-manager.db`
- app settings: `~/Library/Application Support/skill-manager/settings.json`
- shared skills store: `~/.skill-manager/shared`
- MCP manifest: `~/.skill-manager/mcp/manifest.json`
- slash command library: `~/.skill-manager/slash-commands/commands`
- slash command sync state: `~/.skill-manager/slash-commands/sync-state.json`
- marketplace cache: `~/.skill-manager/marketplace`
- app database and LLM scan configs: `~/.skill-manager/skill-manager.db`
- app settings: `~/.skill-manager/settings.json`

Useful Linux paths:

Expand Down
18 changes: 9 additions & 9 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ Skill Manager 是本地配置管理工具。它在你的机器上运行,并读
- 创建、更新、同步、导入或删除 slash command
- 修改 harness 支持设置

在 macOS 上,应用拥有的文件位于 `~/Library/Application Support/skill-manager`;在 Linux 上使用 XDG base directories。
在 macOS 上,应用拥有的文件位于 `~/.skill-manager`(如果已存在,则回退到 `~/Library/Application Support/skill-manager`;在 Linux 上使用 XDG base directories。

## 工作方式

Expand Down Expand Up @@ -212,17 +212,17 @@ CLI marketplace 条目仅用于预览。

## 配置

在 macOS 上,应用拥有的文件位于 `~/Library/Application Support/skill-manager`;在 Linux 上使用 XDG base directories。
在 macOS 上,应用拥有的文件位于 `~/.skill-manager`(如果已存在,则回退到 `~/Library/Application Support/skill-manager`;在 Linux 上使用 XDG base directories。

常用 macOS 路径:

- 共享 Skill 存储:`~/Library/Application Support/skill-manager/shared`
- MCP manifest:`~/Library/Application Support/skill-manager/mcp/manifest.json`
- slash command 库:`~/Library/Application Support/skill-manager/slash-commands/commands`
- slash command 同步状态:`~/Library/Application Support/skill-manager/slash-commands/sync-state.json`
- 商城缓存:`~/Library/Application Support/skill-manager/marketplace`
- 应用数据库和 LLM 扫描配置:`~/Library/Application Support/skill-manager/skill-manager.db`
- 应用设置:`~/Library/Application Support/skill-manager/settings.json`
- 共享 Skill 存储:`~/.skill-manager/shared`
- MCP manifest:`~/.skill-manager/mcp/manifest.json`
- slash command 库:`~/.skill-manager/slash-commands/commands`
- slash command 同步状态:`~/.skill-manager/slash-commands/sync-state.json`
- 商城缓存:`~/.skill-manager/marketplace`
- 应用数据库和 LLM 扫描配置:`~/.skill-manager/skill-manager.db`
- 应用设置:`~/.skill-manager/settings.json`

常用 Linux 路径:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe("ScanConfigPage", () => {
expect(screen.queryByText(/Missing required fields: API Key/)).not.toBeInTheDocument();
expect(screen.getByRole("button", { name: "Update" })).toBeDisabled();
expect(screen.queryByRole("columnheader", { name: "Last validation" })).not.toBeInTheDocument();
expect(screen.getByLabelText("Last validation")).toHaveTextContent(/May 12|12 May|Failed|Not validated/);
expect(screen.getByLabelText("Last validation")).toHaveTextContent(/May 11|11 May|May 12|12 May|Failed|Not validated/);
const apiKeyInput = screen.getByLabelText("API Key", { selector: "input" });
expect(apiKeyInput).toHaveAttribute("type", "password");
expect(String(apiKeyInput.getAttribute("value") ?? "")).not.toBe("");
Expand Down
3 changes: 2 additions & 1 deletion skill_manager/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ def _base_dirs(context: PlatformContext) -> tuple[Path, Path, Path]:
state_override = context.env.get(STATE_DIR_ENV)

if context.platform == "macos":
default_macos = context.home / "Library" / "Application Support" / APP_NAME
legacy_dir = context.home / "Library" / "Application Support" / APP_NAME
default_macos = legacy_dir if legacy_dir.is_dir() else context.home / f".{APP_NAME}"
config_dir = _xdg_dir(context.env, "XDG_CONFIG_HOME", default_macos)
data_dir = _xdg_dir(context.env, "XDG_DATA_HOME", default_macos)
state_dir = (
Expand Down
14 changes: 12 additions & 2 deletions tests/unit/test_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ def isolated_env(platform: str):


class ResolveAppPathsTests(unittest.TestCase):
def test_macos_default_layout_collapses_to_application_support(self) -> None:
def test_macos_default_layout_collapses_to_dot_dir(self) -> None:
with isolated_env("darwin"), TemporaryDirectory() as temp:
home = Path(temp) / "home"
paths = resolve_app_paths({"HOME": str(home)})
base = home / "Library" / "Application Support" / APP_NAME
base = home / f".{APP_NAME}"
self.assertEqual(paths.config_dir, base)
self.assertEqual(paths.data_dir, base)
self.assertEqual(paths.state_dir, base)
Expand All @@ -44,6 +44,16 @@ def test_macos_default_layout_collapses_to_application_support(self) -> None:
self.assertEqual(paths.runtime_state_path, base / "runtime.json")
self.assertEqual(paths.server_log_path, base / "server.log")

def test_macos_default_layout_falls_back_to_legacy_application_support_if_exists(self) -> None:
with isolated_env("darwin"), TemporaryDirectory() as temp:
home = Path(temp) / "home"
legacy_dir = home / "Library" / "Application Support" / APP_NAME
legacy_dir.mkdir(parents=True)
paths = resolve_app_paths({"HOME": str(home)})
self.assertEqual(paths.config_dir, legacy_dir)
self.assertEqual(paths.data_dir, legacy_dir)
self.assertEqual(paths.state_dir, legacy_dir)

def test_xdg_overrides_each_dir_independently(self) -> None:
with isolated_env("darwin"), TemporaryDirectory() as temp:
root = Path(temp)
Expand Down