@halfwhey/claudraband 0.1.0
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/dist/bin.js +9283 -0
- package/dist/claude/claude.d.ts +70 -0
- package/dist/claude/index.d.ts +9 -0
- package/dist/claude/inspect.d.ts +14 -0
- package/dist/claude/parser.d.ts +17 -0
- package/dist/claude/resolve.d.ts +4 -0
- package/dist/index.d.ts +207 -0
- package/dist/index.js +6850 -0
- package/dist/session-registry.d.ts +46 -0
- package/dist/terminal/activity.d.ts +23 -0
- package/dist/terminal/index.d.ts +82 -0
- package/dist/tmuxctl/index.d.ts +2 -0
- package/dist/tmuxctl/tmux.d.ts +39 -0
- package/dist/wrap/event.d.ts +24 -0
- package/dist/wrap/index.d.ts +3 -0
- package/dist/wrap/wrapper.d.ts +11 -0
- package/package.json +58 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ResolvedTerminalBackend } from "./terminal";
|
|
2
|
+
export interface LocalSessionOwnerRecord {
|
|
3
|
+
kind: "local";
|
|
4
|
+
pid?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface DaemonSessionOwnerRecord {
|
|
7
|
+
kind: "daemon";
|
|
8
|
+
serverUrl: string;
|
|
9
|
+
serverPid?: number;
|
|
10
|
+
serverInstanceId: string;
|
|
11
|
+
}
|
|
12
|
+
export type SessionOwnerRecord = LocalSessionOwnerRecord | DaemonSessionOwnerRecord;
|
|
13
|
+
export interface SessionRecord {
|
|
14
|
+
version: 1;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
cwd: string;
|
|
17
|
+
backend: ResolvedTerminalBackend;
|
|
18
|
+
title?: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
lastKnownAlive: boolean;
|
|
22
|
+
reattachable: boolean;
|
|
23
|
+
transcriptPath?: string;
|
|
24
|
+
owner: SessionOwnerRecord;
|
|
25
|
+
}
|
|
26
|
+
export interface KnownSessionRecord {
|
|
27
|
+
version: 1;
|
|
28
|
+
sessionId: string;
|
|
29
|
+
cwd: string;
|
|
30
|
+
backend: ResolvedTerminalBackend;
|
|
31
|
+
title?: string;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
transcriptPath?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function ensureSessionRegistry(): Promise<void>;
|
|
37
|
+
export declare function readSessionRecord(sessionId: string): Promise<SessionRecord | null>;
|
|
38
|
+
export declare function listSessionRecords(): Promise<SessionRecord[]>;
|
|
39
|
+
export declare function readKnownSessionRecord(sessionId: string): Promise<KnownSessionRecord | null>;
|
|
40
|
+
export declare function listKnownSessionRecords(): Promise<KnownSessionRecord[]>;
|
|
41
|
+
export declare function writeSessionRecord(record: SessionRecord): Promise<void>;
|
|
42
|
+
export declare function writeKnownSessionRecord(record: KnownSessionRecord): Promise<void>;
|
|
43
|
+
export declare function deleteSessionRecord(sessionId: string): Promise<void>;
|
|
44
|
+
export declare function deleteKnownSessionRecord(sessionId: string): Promise<void>;
|
|
45
|
+
export declare function normalizeServerUrl(server: string): string;
|
|
46
|
+
export declare function isPidAlive(pid?: number): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PaneActivityOptions {
|
|
2
|
+
/** Milliseconds between captures. Default: 250 */
|
|
3
|
+
intervalMs?: number;
|
|
4
|
+
/** Number of consecutive identical captures required to declare idle. Default: 3 */
|
|
5
|
+
stableCount?: number;
|
|
6
|
+
/** Maximum wait time in ms before giving up. Default: 60_000 */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/** AbortSignal for cancellation. */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export type ActivityResult = "idle" | "timeout" | "aborted";
|
|
12
|
+
/**
|
|
13
|
+
* Poll `capture()` until the pane content is stable for `stableCount`
|
|
14
|
+
* consecutive intervals. Backend-agnostic: works for tmux (capturePane)
|
|
15
|
+
* and xterm (serialize) alike.
|
|
16
|
+
*
|
|
17
|
+
* Returns:
|
|
18
|
+
* - `"idle"` when the pane has not changed for the required number of
|
|
19
|
+
* consecutive captures
|
|
20
|
+
* - `"timeout"` if `timeoutMs` elapses before stability is reached
|
|
21
|
+
* - `"aborted"` if the provided `signal` is aborted
|
|
22
|
+
*/
|
|
23
|
+
export declare function awaitPaneIdle(capture: () => Promise<string>, options?: PaneActivityOptions): Promise<ActivityResult>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { PaneActivityOptions, ActivityResult } from "./activity";
|
|
2
|
+
export type TerminalBackend = "auto" | "tmux" | "xterm";
|
|
3
|
+
export type ResolvedTerminalBackend = Exclude<TerminalBackend, "auto">;
|
|
4
|
+
export type XtermTransportKind = "node-pty" | "bun-terminal";
|
|
5
|
+
export interface TerminalStartOptions {
|
|
6
|
+
cwd: string;
|
|
7
|
+
cols: number;
|
|
8
|
+
rows: number;
|
|
9
|
+
signal: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export interface TerminalHost {
|
|
12
|
+
readonly backend: ResolvedTerminalBackend;
|
|
13
|
+
start(command: string[], options: TerminalStartOptions): Promise<void>;
|
|
14
|
+
stop(): Promise<void>;
|
|
15
|
+
/** Disconnect without killing the process. For tmux the window stays alive. */
|
|
16
|
+
detach(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Reattach to an existing terminal by window name (tmux) or id.
|
|
19
|
+
* Returns true if an existing process was found, false otherwise.
|
|
20
|
+
*/
|
|
21
|
+
reattach(windowName: string): Promise<boolean>;
|
|
22
|
+
send(input: string): Promise<void>;
|
|
23
|
+
interrupt(): Promise<void>;
|
|
24
|
+
capture(): Promise<string>;
|
|
25
|
+
/** Poll capture() until the pane content stabilizes. */
|
|
26
|
+
awaitIdle(options?: PaneActivityOptions): Promise<ActivityResult>;
|
|
27
|
+
alive(): boolean;
|
|
28
|
+
processId(): Promise<number | undefined>;
|
|
29
|
+
}
|
|
30
|
+
export interface CreateTerminalHostOptions {
|
|
31
|
+
backend: TerminalBackend;
|
|
32
|
+
tmuxSessionName: string;
|
|
33
|
+
tmuxWindowName: string;
|
|
34
|
+
}
|
|
35
|
+
export interface CreateTerminalBackendDriverOptions {
|
|
36
|
+
backend: TerminalBackend;
|
|
37
|
+
tmuxSessionName: string;
|
|
38
|
+
}
|
|
39
|
+
export interface LiveTerminalSessionSummary {
|
|
40
|
+
sessionId: string;
|
|
41
|
+
cwd?: string;
|
|
42
|
+
updatedAt?: string;
|
|
43
|
+
pid?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface TerminalBackendDriver {
|
|
46
|
+
readonly backend: ResolvedTerminalBackend;
|
|
47
|
+
createHost(windowName: string): TerminalHost;
|
|
48
|
+
listLiveSessions(): Promise<LiveTerminalSessionSummary[]>;
|
|
49
|
+
hasLiveSession(sessionId: string): Promise<boolean>;
|
|
50
|
+
closeLiveSession(sessionId: string): Promise<boolean>;
|
|
51
|
+
supportsLiveReconnect(): boolean;
|
|
52
|
+
}
|
|
53
|
+
type TmuxDetector = () => boolean;
|
|
54
|
+
type BunRuntimeDetector = () => boolean;
|
|
55
|
+
export declare function hasTmuxBinary(): boolean;
|
|
56
|
+
export declare function hasBunTerminalRuntime(): boolean;
|
|
57
|
+
export declare function resolveXtermTransportKind(detectBunRuntime?: BunRuntimeDetector): XtermTransportKind;
|
|
58
|
+
export declare function resolveTerminalBackend(backend: TerminalBackend, detectTmux?: TmuxDetector): ResolvedTerminalBackend;
|
|
59
|
+
export declare function createTerminalHost(options: CreateTerminalHostOptions): TerminalHost;
|
|
60
|
+
export declare function createTerminalBackendDriver(options: CreateTerminalBackendDriverOptions): TerminalBackendDriver;
|
|
61
|
+
declare class XtermTerminalHost implements TerminalHost {
|
|
62
|
+
readonly backend: "xterm";
|
|
63
|
+
private transport;
|
|
64
|
+
private terminal;
|
|
65
|
+
private serializeAddon;
|
|
66
|
+
private outputDrain;
|
|
67
|
+
private exited;
|
|
68
|
+
start(command: string[], options: TerminalStartOptions): Promise<void>;
|
|
69
|
+
stop(): Promise<void>;
|
|
70
|
+
detach(): Promise<void>;
|
|
71
|
+
reattach(_windowName: string): Promise<boolean>;
|
|
72
|
+
send(input: string): Promise<void>;
|
|
73
|
+
interrupt(): Promise<void>;
|
|
74
|
+
capture(): Promise<string>;
|
|
75
|
+
awaitIdle(options?: PaneActivityOptions): Promise<ActivityResult>;
|
|
76
|
+
alive(): boolean;
|
|
77
|
+
processId(): Promise<number | undefined>;
|
|
78
|
+
}
|
|
79
|
+
export declare const __test: {
|
|
80
|
+
createXtermTerminalHost(): XtermTerminalHost;
|
|
81
|
+
};
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PaneActivityOptions, ActivityResult } from "../terminal/activity";
|
|
2
|
+
export interface TmuxWindowSummary {
|
|
3
|
+
windowId: string;
|
|
4
|
+
paneId: string;
|
|
5
|
+
windowName: string;
|
|
6
|
+
paneCurrentPath?: string;
|
|
7
|
+
windowActivity?: string;
|
|
8
|
+
panePid?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function hasSession(name: string): boolean;
|
|
11
|
+
export declare function killSession(name: string): Promise<void>;
|
|
12
|
+
export declare function listWindows(name: string): Promise<TmuxWindowSummary[]>;
|
|
13
|
+
export interface CaptureOpts {
|
|
14
|
+
withEscapes?: boolean;
|
|
15
|
+
includeScrollback?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class Session {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly command: string[];
|
|
20
|
+
readonly windowId: string;
|
|
21
|
+
readonly paneId: string;
|
|
22
|
+
private constructor();
|
|
23
|
+
static newSession(name: string, width: number, height: number, workingDir: string, command: string[], windowName: string): Promise<Session>;
|
|
24
|
+
/**
|
|
25
|
+
* Find an existing tmux window by session name and window name.
|
|
26
|
+
* Returns a Session if the window is alive, null otherwise.
|
|
27
|
+
*/
|
|
28
|
+
static find(sessionName: string, windowName: string): Promise<Session | null>;
|
|
29
|
+
kill(): Promise<void>;
|
|
30
|
+
get isAlive(): boolean;
|
|
31
|
+
resize(width: number, height: number): Promise<void>;
|
|
32
|
+
sendKeys(input: string): Promise<void>;
|
|
33
|
+
sendLine(input: string): Promise<void>;
|
|
34
|
+
sendSpecial(...keys: string[]): Promise<void>;
|
|
35
|
+
interrupt(): Promise<void>;
|
|
36
|
+
capturePane(opts?: CaptureOpts): Promise<string>;
|
|
37
|
+
awaitIdle(options?: PaneActivityOptions): Promise<ActivityResult>;
|
|
38
|
+
panePID(): Promise<number>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare enum EventKind {
|
|
2
|
+
UserMessage = "user_message",
|
|
3
|
+
AssistantText = "assistant_text",
|
|
4
|
+
AssistantThinking = "assistant_thinking",
|
|
5
|
+
ToolCall = "tool_call",
|
|
6
|
+
ToolResult = "tool_result",
|
|
7
|
+
System = "system",
|
|
8
|
+
Error = "error",
|
|
9
|
+
SessionStart = "session_start",
|
|
10
|
+
TurnStart = "turn_start",
|
|
11
|
+
TurnEnd = "turn_end"
|
|
12
|
+
}
|
|
13
|
+
export interface Event {
|
|
14
|
+
kind: EventKind;
|
|
15
|
+
time: Date;
|
|
16
|
+
text: string;
|
|
17
|
+
toolName: string;
|
|
18
|
+
toolID: string;
|
|
19
|
+
toolInput: string;
|
|
20
|
+
role: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function makeEvent(partial: Partial<Event> & {
|
|
23
|
+
kind: EventKind;
|
|
24
|
+
}): Event;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Event } from "./event";
|
|
2
|
+
export interface Wrapper {
|
|
3
|
+
name(): string;
|
|
4
|
+
model(): string;
|
|
5
|
+
start(signal: AbortSignal): Promise<void>;
|
|
6
|
+
stop(): Promise<void>;
|
|
7
|
+
send(input: string): Promise<void>;
|
|
8
|
+
interrupt(): Promise<void>;
|
|
9
|
+
alive(): boolean;
|
|
10
|
+
events(): AsyncIterable<Event>;
|
|
11
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@halfwhey/claudraband",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Control the official Claude Code CLI programmatically. Use as a library, a direct CLI, an ACP server, or a persistent session daemon.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"claudraband": "dist/bin.js",
|
|
10
|
+
"cband": "dist/bin.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clean": "rm -rf dist",
|
|
23
|
+
"build:bin": "bun build src/bin.ts --target node --external '@agentclientprotocol/*' --external 'node-pty' --outdir dist",
|
|
24
|
+
"build:lib": "bun build ../claudraband-core/src/index.ts --target node --external 'node-pty' --outdir dist --entry-naming index.js",
|
|
25
|
+
"build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
26
|
+
"build": "bun run clean && bun run build:bin && bun run build:lib && bun run build:types",
|
|
27
|
+
"prepack": "bun run build",
|
|
28
|
+
"test": "bun test src",
|
|
29
|
+
"typecheck": "tsc --noEmit"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@agentclientprotocol/sdk": "^0.18.0",
|
|
33
|
+
"@anthropic-ai/claude-code": "2.1.96",
|
|
34
|
+
"@xterm/addon-serialize": "^0.13.0",
|
|
35
|
+
"@xterm/headless": "^5.5.0"
|
|
36
|
+
},
|
|
37
|
+
"optionalDependencies": {
|
|
38
|
+
"node-pty": "^1.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/bun": "^1.2.0",
|
|
42
|
+
"@types/node": "^24.6.0",
|
|
43
|
+
"typescript": "^5.8.0"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"claude",
|
|
47
|
+
"claude-code",
|
|
48
|
+
"acp",
|
|
49
|
+
"agent",
|
|
50
|
+
"cli",
|
|
51
|
+
"tmux"
|
|
52
|
+
],
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/halfwhey/claudraband"
|
|
57
|
+
}
|
|
58
|
+
}
|