1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
/**
* Client for the backend's workspace file API (see internal/files and the
* WebSocket/CLI references in docs/). All functions throw an Error carrying
* the server's message when the request fails.
*
* @example
* const { entries } = await listFiles(); // workspace root
* const { content } = await readFile(entries[0].path);
* await writeFile("notes.txt", "hello");
*/
/** One file matched by the recursive search. */
export interface FileHit {
name: string;
/** Absolute path, usable in further API calls. */
path: string;
/** Path relative to the workspace root, with forward slashes. */
relPath: string;
}
/** One Claude Code skill discovered on disk. */
export interface Skill {
name: string;
description: string;
path: string;
source: "project" | "user";
}
/** One child of a listed directory. */
export interface FileEntry {
name: string;
path: string;
isDir: boolean;
size: number;
}
async function requestJSON<T>(input: string, init?: RequestInit): Promise<T> {
const response = await fetch(input, init);
const payload = (await response.json()) as T & { error?: string };
if (!response.ok) {
throw new Error(
payload.error ?? `request failed with status ${response.status}`,
);
}
return payload;
}
/** listFiles returns the entries of a directory (workspace root when omitted). */
export function listFiles(
path?: string,
): Promise<{ path: string; entries: FileEntry[] }> {
const query = path ? `?path=${encodeURIComponent(path)}` : "";
return requestJSON(`/api/files${query}`);
}
/**
* searchFiles returns the workspace files whose relative path contains the
* query (case-insensitive), recursively, at most `limit` of them.
*/
export function searchFiles(
query: string,
limit = 50,
): Promise<{ root: string; files: FileHit[] }> {
return requestJSON(
`/api/files/search?q=${encodeURIComponent(query)}&limit=${limit}`,
);
}
/** listSkills returns the skills of the project and of the user. */
export function listSkills(): Promise<{ skills: Skill[] }> {
return requestJSON("/api/skills");
}
/** rawFileUrl is the URL streaming a file's bytes (images, downloads). */
export function rawFileUrl(path: string): string {
return `/api/raw?path=${encodeURIComponent(path)}`;
}
/** readFile returns a text file's content. */
export function readFile(
path: string,
): Promise<{ path: string; content: string }> {
return requestJSON(`/api/file?path=${encodeURIComponent(path)}`);
}
/** writeFile saves content to a file, creating parent directories as needed. */
export async function writeFile(path: string, content: string): Promise<void> {
await requestJSON(`/api/file?path=${encodeURIComponent(path)}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content }),
});
}
|