diff --git a/test/expand.test.ts b/test/expand.test.ts
new file mode 100644
index 0000000..013aebd
--- /dev/null
+++ b/test/expand.test.ts
@@ -0,0 +1,117 @@
+import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs";
+import { tmpdir } from "os";
+import { join } from "path";
+import { afterEach, describe, expect, it } from "vitest";
+import {
+ appendSuffix,
+ expandSkill,
+ formatBlock,
+ readSkillBody,
+ type SkillBlockMeta,
+} from "../src/expand";
+
+const tempDirs: string[] = [];
+
+afterEach(() => {
+ for (const dir of tempDirs.splice(0)) {
+ rmSync(dir, { recursive: true, force: true });
+ }
+});
+
+function writeSkillMd(dir: string, name: string, content: string): SkillBlockMeta {
+ const baseDir = join(dir, name);
+ const filePath = join(baseDir, "SKILL.md");
+ mkdirSync(baseDir, { recursive: true });
+ writeFileSync(filePath, content, "utf-8");
+ return { name, filePath, baseDir };
+}
+
+describe("readSkillBody", () => {
+ it("strips YAML frontmatter and trims body", () => {
+ const dir = mkdtempSync(join(tmpdir(), "pi-skill-reinject-expand-"));
+ tempDirs.push(dir);
+ const meta = writeSkillMd(
+ dir,
+ "demo-skill",
+ `---
+name: demo-skill
+description: Demo
+---
+
+# Instructions
+
+Do the thing.
+`,
+ );
+
+ expect(readSkillBody(meta.filePath)).toBe("# Instructions\n\nDo the thing.");
+ });
+
+ it("returns trimmed body when frontmatter is absent", () => {
+ const dir = mkdtempSync(join(tmpdir(), "pi-skill-reinject-expand-"));
+ tempDirs.push(dir);
+ const meta = writeSkillMd(dir, "plain", " hello world \n");
+
+ expect(readSkillBody(meta.filePath)).toBe("hello world");
+ });
+});
+
+describe("formatBlock", () => {
+ it("embeds name, location, baseDir, and body", () => {
+ const meta: SkillBlockMeta = {
+ name: "brave-search",
+ filePath: "/home/user/.pi/skills/brave-search/SKILL.md",
+ baseDir: "/home/user/.pi/skills/brave-search",
+ };
+
+ expect(formatBlock(meta, "Search the web.")).toBe(
+ `
+References are relative to /home/user/.pi/skills/brave-search.
+
+Search the web.
+`,
+ );
+ });
+});
+
+describe("appendSuffix", () => {
+ it("appends suffix after a blank line", () => {
+ const block = "body";
+ expect(appendSuffix(block, "[skill-reinject] note")).toBe(
+ `${block}\n\n[skill-reinject] note`,
+ );
+ });
+
+ it("returns block unchanged for empty or whitespace suffix", () => {
+ const block = "body";
+ expect(appendSuffix(block, undefined)).toBe(block);
+ expect(appendSuffix(block, " ")).toBe(block);
+ });
+});
+
+describe("expandSkill", () => {
+ it("produces full injectable text with optional suffix", () => {
+ const dir = mkdtempSync(join(tmpdir(), "pi-skill-reinject-expand-"));
+ tempDirs.push(dir);
+ const meta = writeSkillMd(
+ dir,
+ "pdf-tools",
+ `---
+name: pdf-tools
+---
+
+Extract pages from PDFs.
+`,
+ );
+
+ const withoutSuffix = expandSkill(meta);
+ expect(withoutSuffix).toContain('name="pdf-tools"');
+ expect(withoutSuffix).toContain(`location="${meta.filePath}"`);
+ expect(withoutSuffix).toContain(`References are relative to ${meta.baseDir}.`);
+ expect(withoutSuffix).toContain("Extract pages from PDFs.");
+
+ expect(expandSkill(meta, "[skill-reinject] Re-applied.")).toBe(
+ `${withoutSuffix}\n\n[skill-reinject] Re-applied.`,
+ );
+ });
+});