@nutthead/cc-statusline 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nutthead/cc-statusline",
3
3
  "description": "Status Line for Claude Code",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "module": "index.ts",
6
6
  "type": "module",
7
7
  "private": false,
@@ -1,8 +0,0 @@
1
- {
2
- "outputStyle": "Explanatory",
3
- "permissions": {
4
- "allow": [
5
- "Bash(bun test:*)"
6
- ]
7
- }
8
- }
package/CLAUDE.md DELETED
@@ -1,33 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- Default to using Bun instead of Node.js.
6
-
7
- - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
8
- - Use `bun test` instead of `jest` or `vitest`
9
- - Use `bun build <file.ts>` instead of `webpack` or `esbuild`
10
- - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
11
- - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
12
- - Bun automatically loads .env, so don't use dotenv.
13
-
14
- ## APIs
15
-
16
- - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
17
- - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
18
- - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
19
- - Bun.$`ls` instead of execa.
20
-
21
- ## Testing
22
-
23
- Use `bun test` to run tests.
24
-
25
- ```ts#index.test.ts
26
- import { test, expect } from "bun:test";
27
-
28
- test("hello world", () => {
29
- expect(1).toBe(1);
30
- });
31
- ```
32
-
33
- For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
package/bun.lock DELETED
@@ -1,56 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "configVersion": 1,
4
- "workspaces": {
5
- "": {
6
- "name": "statusline",
7
- "dependencies": {
8
- "@logtape/file": "^1.3.6",
9
- "@logtape/logtape": "^1.3.6",
10
- "ansi-colors": "^4.1.3",
11
- "simple-git": "^3.30.0",
12
- "type-fest": "^5.3.1",
13
- "zod": "^4.3.5",
14
- },
15
- "devDependencies": {
16
- "@types/bun": "latest",
17
- },
18
- "peerDependencies": {
19
- "typescript": "^5",
20
- },
21
- },
22
- },
23
- "packages": {
24
- "@kwsites/file-exists": ["@kwsites/file-exists@1.1.1", "", { "dependencies": { "debug": "^4.1.1" } }, "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw=="],
25
-
26
- "@kwsites/promise-deferred": ["@kwsites/promise-deferred@1.1.1", "", {}, "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="],
27
-
28
- "@logtape/file": ["@logtape/file@1.3.6", "", { "peerDependencies": { "@logtape/logtape": "^1.3.6" } }, "sha512-wYh1qb8uOj2LtoAHyzCnkjvScJsJiOSYPcrPaaa3QxLdvR6ZQHo3939jRdeqkv5oQMW/rfMImmY7ma/kgW6Ogw=="],
29
-
30
- "@logtape/logtape": ["@logtape/logtape@1.3.6", "", {}, "sha512-OaK8eal8zcjB0GZbllXKgUC2T9h/GyNLQyQXjJkf1yum7SZKTWs9gs/t8NMS0kVVaSnA7bhU0Sjws/Iy4e0/IQ=="],
31
-
32
- "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
33
-
34
- "@types/node": ["@types/node@25.0.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-9L7EOcoPf2mpvBL6GbE4z6zY9oaaP389dZ5ZZ05n2K9p3e1rEUwcXqwhXIKRMbK/uV1U8MYactPf1XH0xmtZWg=="],
35
-
36
- "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
37
-
38
- "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
39
-
40
- "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
41
-
42
- "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
43
-
44
- "simple-git": ["simple-git@3.30.0", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "debug": "^4.4.0" } }, "sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg=="],
45
-
46
- "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
47
-
48
- "type-fest": ["type-fest@5.3.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg=="],
49
-
50
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
51
-
52
- "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
53
-
54
- "zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="],
55
- }
56
- }
@@ -1,26 +0,0 @@
1
- {
2
- "session_id": "fc9bbbee-466c-45b8-ad86-8f3d848823f2",
3
- "transcript_path": "/home/amadeus/.claude/projects/-home-amadeus-Code-behrangsa-statusline/fc9bbbee-466c-45b8-ad86-8f3d848823f2.jsonl",
4
- "cwd": "/home/amadeus/Code/behrangsa/statusline",
5
- "model": { "id": "claude-opus-4-5-20251101", "display_name": "Opus 4.5" },
6
- "workspace": {
7
- "current_dir": "/home/amadeus/Code/behrangsa/statusline",
8
- "project_dir": "/home/amadeus/Code/behrangsa/statusline"
9
- },
10
- "version": "2.1.3",
11
- "output_style": { "name": "Explanatory" },
12
- "cost": {
13
- "total_cost_usd": 0,
14
- "total_duration_ms": 1345,
15
- "total_api_duration_ms": 0,
16
- "total_lines_added": 0,
17
- "total_lines_removed": 0
18
- },
19
- "context_window": {
20
- "total_input_tokens": 0,
21
- "total_output_tokens": 0,
22
- "context_window_size": 200000,
23
- "current_usage": null
24
- },
25
- "exceeds_200k_tokens": false
26
- }
@@ -1,31 +0,0 @@
1
- {
2
- "session_id": "09f8e582-5026-4970-9530-fdff14b0dbe9",
3
- "transcript_path": "/home/amadeus/.claude/projects/-home-amadeus-Code-behrangsa-statusline/09f8e582-5026-4970-9530-fdff14b0dbe9.jsonl",
4
- "cwd": "/home/amadeus/Code/behrangsa/statusline",
5
- "model": { "id": "claude-opus-4-5-20251101", "display_name": "Opus 4.5" },
6
- "workspace": {
7
- "current_dir": "/home/amadeus/Code/behrangsa/statusline",
8
- "project_dir": "/home/amadeus/Code/behrangsa/statusline"
9
- },
10
- "version": "2.1.3",
11
- "output_style": { "name": "Explanatory" },
12
- "cost": {
13
- "total_cost_usd": 0.057773349999999994,
14
- "total_duration_ms": 122167,
15
- "total_api_duration_ms": 18488,
16
- "total_lines_added": 0,
17
- "total_lines_removed": 0
18
- },
19
- "context_window": {
20
- "total_input_tokens": 753,
21
- "total_output_tokens": 665,
22
- "context_window_size": 200000,
23
- "current_usage": {
24
- "input_tokens": 10,
25
- "output_tokens": 3,
26
- "cache_creation_input_tokens": 212,
27
- "cache_read_input_tokens": 21034
28
- }
29
- },
30
- "exceeds_200k_tokens": false
31
- }
@@ -1,22 +0,0 @@
1
- import { test, expect, describe } from "bun:test";
2
- import { statusSchema } from "./statusLineSchema";
3
- import { readdirSync } from "node:fs";
4
-
5
- const fixturesDir = `${import.meta.dir}/../fixtures`;
6
- const fixtureFiles = readdirSync(fixturesDir).filter((f) =>
7
- f.endsWith(".json")
8
- );
9
-
10
- describe("statusLineSchema", () => {
11
- describe("fixtures validation", () => {
12
- test.each(fixtureFiles)(
13
- "%s does not lead to an error",
14
- async (filename) => {
15
- const fixture = await Bun.file(`${fixturesDir}/${filename}`).json();
16
- const result = statusSchema.safeParse(fixture);
17
-
18
- expect(result.success).toBe(true);
19
- }
20
- );
21
- });
22
- });
package/src/utils.test.ts DELETED
@@ -1,472 +0,0 @@
1
- import { test, expect, describe, mock, beforeAll, afterAll } from "bun:test";
2
- import { mkdtemp, rm } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- // Mock homedir to return a consistent value for testing
7
- mock.module("node:os", () => ({
8
- homedir: () => "/home/testuser",
9
- }));
10
-
11
- // Import after mocking
12
- import {
13
- abbreviatePath,
14
- abbreviateModelId,
15
- currentBranchName,
16
- currentDirStatus,
17
- currentGitStatus,
18
- currentModelStatus,
19
- } from "./utils";
20
- import type { Status } from "./statusLineSchema";
21
-
22
- /** Default Status fixture with sensible test values */
23
- const defaultStatus: Status = {
24
- session_id: "test-session",
25
- transcript_path: "/tmp/transcript.json",
26
- cwd: "/test/cwd",
27
- model: {
28
- id: "claude-opus-4.5",
29
- display_name: "Test Model",
30
- },
31
- workspace: {
32
- project_dir: "/home/testuser/project",
33
- current_dir: "/home/testuser/project",
34
- },
35
- version: "1.0.0",
36
- cost: {
37
- total_cost_usd: 0,
38
- total_duration_ms: 0,
39
- total_api_duration_ms: 0,
40
- total_lines_added: 0,
41
- total_lines_removed: 0,
42
- },
43
- context_window: null,
44
- };
45
-
46
- describe("abbreviatePath", () => {
47
- describe("home directory replacement", () => {
48
- test("replaces homedir with ~ at start of path", () => {
49
- expect(abbreviatePath("/home/testuser/projects/myapp")).toBe("~/p/myapp");
50
- });
51
-
52
- test("returns ~ for exact homedir match", () => {
53
- expect(abbreviatePath("/home/testuser")).toBe("~");
54
- });
55
-
56
- test("does not replace homedir if not at start", () => {
57
- expect(abbreviatePath("/var/home/testuser/data")).toBe("/v/h/t/data");
58
- });
59
-
60
- test("handles path immediately under homedir", () => {
61
- expect(abbreviatePath("/home/testuser/file.txt")).toBe("~/file.txt");
62
- });
63
- });
64
-
65
- describe("path abbreviation", () => {
66
- test("abbreviates all segments except the last", () => {
67
- expect(abbreviatePath("/foo/bar/baz/etc/last")).toBe("/f/b/b/e/last");
68
- });
69
-
70
- test("keeps single segment paths unchanged", () => {
71
- expect(abbreviatePath("filename")).toBe("filename");
72
- });
73
-
74
- test("handles relative paths", () => {
75
- expect(abbreviatePath("relative/path/here")).toBe("r/p/here");
76
- });
77
-
78
- test("handles two segment absolute paths", () => {
79
- expect(abbreviatePath("/etc/nginx")).toBe("/e/nginx");
80
- });
81
-
82
- test("handles deep paths", () => {
83
- expect(abbreviatePath("/a/b/c/d/e/f/g/target")).toBe(
84
- "/a/b/c/d/e/f/g/target"
85
- );
86
- });
87
- });
88
-
89
- describe("edge cases", () => {
90
- test("handles empty string", () => {
91
- expect(abbreviatePath("")).toBe("");
92
- });
93
-
94
- test("handles root path", () => {
95
- expect(abbreviatePath("/")).toBe("/");
96
- });
97
-
98
- test("handles path with only one segment after root", () => {
99
- expect(abbreviatePath("/single")).toBe("/single");
100
- });
101
-
102
- test("preserves trailing slash behavior", () => {
103
- // Trailing slash creates empty last segment which is preserved
104
- expect(abbreviatePath("/foo/bar/")).toBe("/f/b/");
105
- });
106
-
107
- test("handles homedir with subdirectories", () => {
108
- expect(abbreviatePath("/home/testuser/Code/project/src")).toBe(
109
- "~/C/p/src"
110
- );
111
- });
112
- });
113
- });
114
-
115
- describe("abbreviateModelId", () => {
116
- describe("claude prefix removal", () => {
117
- test("removes claude- prefix from model name", () => {
118
- expect(abbreviateModelId("claude-opus-4.5")).toBe("opus-4.5");
119
- });
120
-
121
- test("removes claude- prefix from sonnet model", () => {
122
- expect(abbreviateModelId("claude-sonnet-4")).toBe("sonnet-4");
123
- });
124
-
125
- test("removes claude- prefix from haiku model", () => {
126
- expect(abbreviateModelId("claude-haiku-3.5")).toBe("haiku-3.5");
127
- });
128
- });
129
-
130
- describe("non-claude models", () => {
131
- test("returns non-claude model unchanged", () => {
132
- expect(abbreviateModelId("gpt-4")).toBe("gpt-4");
133
- });
134
-
135
- test("returns model without prefix unchanged", () => {
136
- expect(abbreviateModelId("opus-4.5")).toBe("opus-4.5");
137
- });
138
-
139
- test("does not match partial claude prefix", () => {
140
- expect(abbreviateModelId("claud-model")).toBe("claud-model");
141
- });
142
-
143
- test("does not match claude without hyphen", () => {
144
- expect(abbreviateModelId("claudemodel")).toBe("claudemodel");
145
- });
146
- });
147
-
148
- describe("edge cases", () => {
149
- test("handles empty string", () => {
150
- expect(abbreviateModelId("")).toBe("");
151
- });
152
-
153
- test("handles just the prefix", () => {
154
- expect(abbreviateModelId("claude-")).toBe("");
155
- });
156
-
157
- test("is case-sensitive (uppercase not matched)", () => {
158
- expect(abbreviateModelId("Claude-opus")).toBe("Claude-opus");
159
- });
160
-
161
- test("only removes prefix once", () => {
162
- expect(abbreviateModelId("claude-claude-test")).toBe("claude-test");
163
- });
164
- });
165
- });
166
-
167
- describe("currentBranchName", () => {
168
- describe("valid git repository", () => {
169
- test("returns branch name for current repository", async () => {
170
- // This test uses the actual repo we're in
171
- const result = await currentBranchName(process.cwd());
172
- expect(result.status).toBe("branch");
173
- if (result.status === "branch") {
174
- expect(result.name).toBe("master");
175
- }
176
- });
177
- });
178
-
179
- describe("non-git directory", () => {
180
- let tempDir: string;
181
-
182
- beforeAll(async () => {
183
- tempDir = await mkdtemp(join(tmpdir(), "git-test-"));
184
- });
185
-
186
- afterAll(async () => {
187
- await rm(tempDir, { recursive: true, force: true });
188
- });
189
-
190
- test("returns not-git status for non-git directory", async () => {
191
- const result = await currentBranchName(tempDir);
192
- expect(result.status).toBe("not-git");
193
- });
194
- });
195
-
196
- describe("detached HEAD state", () => {
197
- let tempDir: string;
198
-
199
- beforeAll(async () => {
200
- tempDir = await mkdtemp(join(tmpdir(), "git-detached-"));
201
- // Initialize a git repo, create a commit, then detach HEAD
202
- const proc = Bun.spawn(
203
- [
204
- "bash",
205
- "-c",
206
- `
207
- cd "${tempDir}" &&
208
- git init &&
209
- git config user.email "test@test.com" &&
210
- git config user.name "Test" &&
211
- echo "test" > file.txt &&
212
- git add file.txt &&
213
- git commit -m "initial" &&
214
- git checkout --detach HEAD
215
- `,
216
- ],
217
- { stdout: "pipe", stderr: "pipe" }
218
- );
219
- await proc.exited;
220
- });
221
-
222
- afterAll(async () => {
223
- await rm(tempDir, { recursive: true, force: true });
224
- });
225
-
226
- test("returns detached status with commit hash", async () => {
227
- const result = await currentBranchName(tempDir);
228
- expect(result.status).toBe("detached");
229
- if (result.status === "detached") {
230
- // Commit hash should be 7 characters (short hash)
231
- expect(result.commit).toMatch(/^[a-f0-9]{7}$/);
232
- }
233
- });
234
- });
235
-
236
- describe("fresh git repository", () => {
237
- let tempDir: string;
238
-
239
- beforeAll(async () => {
240
- tempDir = await mkdtemp(join(tmpdir(), "git-fresh-"));
241
- const proc = Bun.spawn(["git", "init", tempDir], {
242
- stdout: "pipe",
243
- stderr: "pipe",
244
- });
245
- await proc.exited;
246
- });
247
-
248
- afterAll(async () => {
249
- await rm(tempDir, { recursive: true, force: true });
250
- });
251
-
252
- test("returns branch name for fresh repo with no commits", async () => {
253
- const result = await currentBranchName(tempDir);
254
- // Fresh repos have a branch but no commits - should still work
255
- expect(result.status).toBe("branch");
256
- if (result.status === "branch") {
257
- // Default branch is typically "master" or "main"
258
- expect(["master", "main"]).toContain(result.name);
259
- }
260
- });
261
- });
262
- });
263
-
264
- describe("currentGitStatus", () => {
265
- describe("output format", () => {
266
- test("returns branch emoji format in current repository", async () => {
267
- // Since we're in a git repo on master branch
268
- const result = await currentGitStatus();
269
- expect(result).toBe("🌿 master");
270
- });
271
-
272
- test("returns a non-empty string", async () => {
273
- const result = await currentGitStatus();
274
- expect(typeof result).toBe("string");
275
- expect(result.length).toBeGreaterThan(0);
276
- });
277
-
278
- test("result starts with one of the expected emojis", async () => {
279
- const result = await currentGitStatus();
280
- // Should start with 🌿, 🪾, 💾, or 💥
281
- const validPrefixes = ["🌿", "🪾", "💾", "💥"];
282
- const startsWithValidEmoji = validPrefixes.some((emoji) =>
283
- result.startsWith(emoji)
284
- );
285
- expect(startsWithValidEmoji).toBe(true);
286
- });
287
- });
288
- });
289
-
290
- describe("currentModelStatus", () => {
291
- describe("Claude models", () => {
292
- test("formats opus model with icon and strips claude- prefix", () => {
293
- const status = {
294
- ...defaultStatus,
295
- model: { ...defaultStatus.model, id: "claude-opus-4.5" },
296
- };
297
- expect(currentModelStatus(status)).toBe("⏣ opus-4.5");
298
- });
299
-
300
- test("formats sonnet model with icon and strips claude- prefix", () => {
301
- const status = {
302
- ...defaultStatus,
303
- model: { ...defaultStatus.model, id: "claude-sonnet-4" },
304
- };
305
- expect(currentModelStatus(status)).toBe("⏣ sonnet-4");
306
- });
307
-
308
- test("formats haiku model with icon and strips claude- prefix", () => {
309
- const status = {
310
- ...defaultStatus,
311
- model: { ...defaultStatus.model, id: "claude-haiku-3.5" },
312
- };
313
- expect(currentModelStatus(status)).toBe("⏣ haiku-3.5");
314
- });
315
- });
316
-
317
- describe("non-Claude models", () => {
318
- test("formats non-Claude model without modification", () => {
319
- const status = {
320
- ...defaultStatus,
321
- model: { ...defaultStatus.model, id: "gpt-4-turbo" },
322
- };
323
- expect(currentModelStatus(status)).toBe("⏣ gpt-4-turbo");
324
- });
325
-
326
- test("keeps model name when already without claude- prefix", () => {
327
- const status = {
328
- ...defaultStatus,
329
- model: { ...defaultStatus.model, id: "opus-4.5" },
330
- };
331
- expect(currentModelStatus(status)).toBe("⏣ opus-4.5");
332
- });
333
- });
334
-
335
- describe("output format", () => {
336
- test("always starts with Model icon", () => {
337
- const status = {
338
- ...defaultStatus,
339
- model: { ...defaultStatus.model, id: "any-model" },
340
- };
341
- expect(currentModelStatus(status)).toStartWith("⏣ ");
342
- });
343
-
344
- test("returns string type", () => {
345
- const status = {
346
- ...defaultStatus,
347
- model: { ...defaultStatus.model, id: "claude-opus-4.5" },
348
- };
349
- expect(typeof currentModelStatus(status)).toBe("string");
350
- });
351
- });
352
-
353
- describe("edge cases", () => {
354
- test("handles empty model id", () => {
355
- const status = {
356
- ...defaultStatus,
357
- model: { ...defaultStatus.model, id: "" },
358
- };
359
- expect(currentModelStatus(status)).toBe("⏣ ");
360
- });
361
-
362
- test("handles model id that is just 'claude-'", () => {
363
- const status = {
364
- ...defaultStatus,
365
- model: { ...defaultStatus.model, id: "claude-" },
366
- };
367
- expect(currentModelStatus(status)).toBe("⏣ ");
368
- });
369
- });
370
- });
371
-
372
- describe("currentDirStatus", () => {
373
- describe("same directory", () => {
374
- test("returns single path when project and current dir match", () => {
375
- const status = {
376
- ...defaultStatus,
377
- workspace: {
378
- project_dir: "/home/testuser/project",
379
- current_dir: "/home/testuser/project",
380
- },
381
- };
382
- expect(currentDirStatus(status)).toBe("🗂️ ~/project");
383
- });
384
-
385
- test("abbreviates path segments except last", () => {
386
- const status = {
387
- ...defaultStatus,
388
- workspace: {
389
- project_dir: "/home/testuser/Code/myapp",
390
- current_dir: "/home/testuser/Code/myapp",
391
- },
392
- };
393
- expect(currentDirStatus(status)).toBe("🗂️ ~/C/myapp");
394
- });
395
- });
396
-
397
- describe("different directories", () => {
398
- test("returns both paths with separator when dirs differ", () => {
399
- const status = {
400
- ...defaultStatus,
401
- workspace: {
402
- project_dir: "/home/testuser/project",
403
- current_dir: "/home/testuser/other",
404
- },
405
- };
406
- expect(currentDirStatus(status)).toBe("🗂️ ~/project 📂 ~/other");
407
- });
408
-
409
- test("abbreviates both paths independently", () => {
410
- const status = {
411
- ...defaultStatus,
412
- workspace: {
413
- project_dir: "/home/testuser/Code/frontend",
414
- current_dir: "/home/testuser/Code/backend",
415
- },
416
- };
417
- expect(currentDirStatus(status)).toBe("🗂️ ~/C/frontend 📂 ~/C/backend");
418
- });
419
-
420
- test("handles deeply nested current directory", () => {
421
- const status = {
422
- ...defaultStatus,
423
- workspace: {
424
- project_dir: "/home/testuser/project",
425
- current_dir: "/home/testuser/project/src/components",
426
- },
427
- };
428
- expect(currentDirStatus(status)).toBe("🗂️ ~/project 📂 ~/p/s/components");
429
- });
430
- });
431
-
432
- describe("path abbreviation", () => {
433
- test("replaces home directory with ~", () => {
434
- const status = {
435
- ...defaultStatus,
436
- workspace: {
437
- project_dir: "/home/testuser/myapp",
438
- current_dir: "/home/testuser/myapp",
439
- },
440
- };
441
- expect(currentDirStatus(status)).toStartWith("🗂️ ~");
442
- });
443
-
444
- test("handles non-home paths", () => {
445
- const status = {
446
- ...defaultStatus,
447
- workspace: {
448
- project_dir: "/var/www/app",
449
- current_dir: "/var/www/app",
450
- },
451
- };
452
- expect(currentDirStatus(status)).toBe("🗂️ /v/w/app");
453
- });
454
- });
455
-
456
- describe("output format", () => {
457
- test("returns string type", () => {
458
- expect(typeof currentDirStatus(defaultStatus)).toBe("string");
459
- });
460
-
461
- test("uses folder emoji as separator for different directories", () => {
462
- const status = {
463
- ...defaultStatus,
464
- workspace: {
465
- project_dir: "/home/testuser/a",
466
- current_dir: "/home/testuser/b",
467
- },
468
- };
469
- expect(currentDirStatus(status)).toContain(" 📂 ");
470
- });
471
- });
472
- });
package/tsconfig.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- // Environment setup & latest features
4
- "lib": ["ESNext"],
5
- "target": "ESNext",
6
- "module": "Preserve",
7
- "moduleDetection": "force",
8
- "jsx": "react-jsx",
9
- "allowJs": true,
10
-
11
- // Bundler mode
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "verbatimModuleSyntax": true,
15
- "noEmit": true,
16
-
17
- // Best practices
18
- "strict": true,
19
- "skipLibCheck": true,
20
- "noFallthroughCasesInSwitch": true,
21
- "noUncheckedIndexedAccess": true,
22
- "noImplicitOverride": true,
23
-
24
- // Some stricter flags (disabled by default)
25
- "noUnusedLocals": false,
26
- "noUnusedParameters": false,
27
- "noPropertyAccessFromIndexSignature": false
28
- }
29
- }