diff --git a/test/detect.test.ts b/test/detect.test.ts
new file mode 100644
index 0000000..e746d59
--- /dev/null
+++ b/test/detect.test.ts
@@ -0,0 +1,85 @@
+import { describe, expect, it } from "vitest";
+import {
+ detectSlashSkill,
+ matchReadPathToSkill,
+ matchReadPathToSkillWhenEnabled,
+ parseSkillBlocksFromText,
+ type SkillPathMeta,
+} from "../src/detect";
+
+const sampleSkills: SkillPathMeta[] = [
+ {
+ name: "brave-search",
+ filePath: "/home/user/.pi/skills/brave-search/SKILL.md",
+ baseDir: "/home/user/.pi/skills/brave-search",
+ },
+ {
+ name: "pdf-tools",
+ filePath: "/proj/.pi/skills/pdf-tools/SKILL.md",
+ baseDir: "/proj/.pi/skills/pdf-tools",
+ },
+];
+
+describe("detectSlashSkill", () => {
+ it("detects slash command at start of text", () => {
+ expect(detectSlashSkill("/skill:brave-search")).toBe("brave-search");
+ expect(detectSlashSkill("/skill:pdf-tools extract pages")).toBe("pdf-tools");
+ });
+
+ it("returns null for non-slash or invalid names", () => {
+ expect(detectSlashSkill("hello")).toBeNull();
+ expect(detectSlashSkill(" /skill:foo")).toBeNull();
+ expect(detectSlashSkill("/skill:Bad_Name")).toBeNull();
+ });
+});
+
+describe("parseSkillBlocksFromText", () => {
+ const block =
+ '\nbody\n';
+
+ it("parses one or more skill blocks", () => {
+ expect(parseSkillBlocksFromText(block)).toEqual([
+ {
+ name: "brave-search",
+ location: "/home/user/.pi/skills/brave-search/SKILL.md",
+ content: "body",
+ },
+ ]);
+ expect(parseSkillBlocksFromText(`${block}\n\n${block.replace("brave-search", "pdf-tools")}`)).toHaveLength(2);
+ });
+
+ it("returns empty array when no blocks", () => {
+ expect(parseSkillBlocksFromText("plain text")).toEqual([]);
+ expect(parseSkillBlocksFromText(' {
+ it("matches absolute skill filePath", () => {
+ expect(matchReadPathToSkill("/home/user/.pi/skills/brave-search/SKILL.md", sampleSkills)?.name).toBe(
+ "brave-search",
+ );
+ });
+
+ it("matches relative path via skill baseDir", () => {
+ expect(matchReadPathToSkill("SKILL.md", [sampleSkills[0]])?.name).toBe("brave-search");
+ });
+
+ it("returns null for unrelated paths", () => {
+ expect(matchReadPathToSkill("/tmp/README.md", sampleSkills)).toBeNull();
+ });
+});
+
+describe("matchReadPathToSkillWhenEnabled", () => {
+ it("skips read detection when trackReadPaths is false", () => {
+ expect(
+ matchReadPathToSkillWhenEnabled("/home/user/.pi/skills/brave-search/SKILL.md", sampleSkills, false),
+ ).toBeNull();
+ });
+
+ it("delegates to matchReadPathToSkill when enabled", () => {
+ expect(
+ matchReadPathToSkillWhenEnabled("/home/user/.pi/skills/brave-search/SKILL.md", sampleSkills, true)?.name,
+ ).toBe("brave-search");
+ });
+});