From d038c5feff0acc1b5dbb8aec6037536451968099 Mon Sep 17 00:00:00 2001 From: Mordris Date: Mon, 30 Mar 2026 10:29:21 +0300 Subject: [PATCH 1/2] fix: recognize Windows absolute drive paths (C:\...) in isLocalPath Closes #138 --- src/installer.test.ts | 3 +++ src/installer.ts | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/installer.test.ts b/src/installer.test.ts index 85ed711..895054b 100644 --- a/src/installer.test.ts +++ b/src/installer.test.ts @@ -1314,6 +1314,9 @@ describe("isLocalPath", () => { test("detects absolute paths", () => { expect(isLocalPath("/absolute/path/to/skill")).toBe(true); expect(isLocalPath("/home/user/skills/my-skill")).toBe(true); + expect(isLocalPath("C:\\Users\\foo\\skill")).toBe(true); + expect(isLocalPath("C:/Users/foo/skill")).toBe(true); + expect(isLocalPath("D:\\projects\\my-skill")).toBe(true); }); test("detects relative paths with ./", () => { diff --git a/src/installer.ts b/src/installer.ts index 9c72f1e..ae3bd46 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -54,7 +54,8 @@ export function isLocalPath(input: string): boolean { input.startsWith("~/") || input === "~" || input === "." || - input === ".." + input === ".." || + /^[a-zA-Z]:[/\\]/.test(input) ); } From b14e0cbf36ce13bc7261747ed253e4678d8b20e4 Mon Sep 17 00:00:00 2001 From: Mordris Date: Mon, 30 Mar 2026 10:44:14 +0300 Subject: [PATCH 2/2] feat: add support for Windows-style backslashes (.\\ and ..\\) in isLocalPath --- src/installer.test.ts | 35 ++++++++++++++++++++++++----------- src/installer.ts | 3 +++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/installer.test.ts b/src/installer.test.ts index 895054b..4377e61 100644 --- a/src/installer.test.ts +++ b/src/installer.test.ts @@ -1319,18 +1319,21 @@ describe("isLocalPath", () => { expect(isLocalPath("D:\\projects\\my-skill")).toBe(true); }); - test("detects relative paths with ./", () => { + test("detects relative paths with ./ or .\\", () => { expect(isLocalPath("./my-skill")).toBe(true); + expect(isLocalPath(".\\my-skill")).toBe(true); expect(isLocalPath("./relative/path/to/skill")).toBe(true); }); - test("detects parent-relative paths with ../", () => { + test("detects parent-relative paths with ../ or ..\\", () => { expect(isLocalPath("../sibling/skill")).toBe(true); + expect(isLocalPath("..\\sibling\\skill")).toBe(true); expect(isLocalPath("../my-skill")).toBe(true); }); test("detects tilde paths", () => { expect(isLocalPath("~/skills/my-skill")).toBe(true); + expect(isLocalPath("~\\skills\\my-skill")).toBe(true); expect(isLocalPath("~")).toBe(true); }); @@ -1398,23 +1401,33 @@ describe("parseLocalSource", () => { // ─── parseSource local path integration tests ────────────────────────────── describe("parseSource with local paths", () => { - test("detects and parses absolute path", () => { + test("detects and parses absolute path (Linux)", () => { const result = parseSource("/home/user/skills/my-skill"); expect(result.isLocal).toBe(true); - expect(result.localPath).toBe("/home/user/skills/my-skill"); - expect(result.repo).toBe("my-skill"); + expect(result.localPath).toBeTruthy(); }); - test("detects and parses relative path", () => { - const result = parseSource("./my-skill"); + test("detects and parses absolute path (Windows)", () => { + const result = parseSource("C:\\Users\\emre\\skill"); expect(result.isLocal).toBe(true); - expect(result.localPath!.startsWith("/")).toBe(true); + expect(result.localPath).toBeTruthy(); }); - test("detects and parses parent-relative path", () => { - const result = parseSource("../my-skill"); + test("detects and parses relative backslash path", () => { + const result = parseSource(".\\my-skill"); + expect(result.isLocal).toBe(true); + expect(result.localPath).toBeTruthy(); + }); + + test("detects and parses parent-relative backslash path", () => { + const result = parseSource("..\\my-skill"); + expect(result.isLocal).toBe(true); + expect(result.localPath).toBeTruthy(); + }); + + test("detects and parses relative slash path", () => { + const result = parseSource("./my-skill"); expect(result.isLocal).toBe(true); - expect(result.localPath!.startsWith("/")).toBe(true); }); test("detects and parses tilde path", () => { diff --git a/src/installer.ts b/src/installer.ts index ae3bd46..7c6a332 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -50,8 +50,11 @@ export function isLocalPath(input: string): boolean { return ( input.startsWith("/") || input.startsWith("./") || + input.startsWith(".\\") || input.startsWith("../") || + input.startsWith("..\\") || input.startsWith("~/") || + input.startsWith("~\\") || input === "~" || input === "." || input === ".." ||