@hasna/computer 0.1.7 → 0.1.9
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/README.md +67 -0
- package/dist/apps/ghostty/applescript.d.ts +36 -0
- package/dist/apps/ghostty/applescript.d.ts.map +1 -0
- package/dist/apps/ghostty/applescript.test.d.ts +2 -0
- package/dist/apps/ghostty/applescript.test.d.ts.map +1 -0
- package/dist/apps/ghostty/driver.d.ts +10 -0
- package/dist/apps/ghostty/driver.d.ts.map +1 -0
- package/dist/apps/registry.d.ts +5 -0
- package/dist/apps/registry.d.ts.map +1 -0
- package/dist/apps/registry.test.d.ts +2 -0
- package/dist/apps/registry.test.d.ts.map +1 -0
- package/dist/apps/types.d.ts +47 -0
- package/dist/apps/types.d.ts.map +1 -0
- package/dist/cli/index.js +5893 -9970
- package/dist/cli/storage.d.ts +3 -0
- package/dist/cli/storage.d.ts.map +1 -0
- package/dist/cli/storage.test.d.ts +2 -0
- package/dist/cli/storage.test.d.ts.map +1 -0
- package/dist/db/index.d.ts +15 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts +2 -0
- package/dist/db/pg-migrations.d.ts.map +1 -0
- package/dist/db/remote-storage.d.ts +11 -0
- package/dist/db/remote-storage.d.ts.map +1 -0
- package/dist/db/storage-sync.d.ts +57 -0
- package/dist/db/storage-sync.d.ts.map +1 -0
- package/dist/db/storage-sync.test.d.ts +2 -0
- package/dist/db/storage-sync.test.d.ts.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13473 -17215
- package/dist/mcp/index.js +17467 -21724
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/server/index.js +14852 -19139
- package/dist/storage.d.ts +5 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +5519 -0
- package/package.json +9 -3
- package/src/db/migrations/001_initial.sql +2 -1
- package/dashboard/dist/assets/index-6UXnbsOB.js +0 -40
- package/dashboard/dist/assets/index-CwAxlYtY.css +0 -1
- package/dashboard/dist/index.html +0 -13
package/README.md
CHANGED
|
@@ -47,12 +47,63 @@ bun install -g @hasna/computer
|
|
|
47
47
|
computer run <task> # Run a computer use task
|
|
48
48
|
computer run <task> -p openai # Use OpenAI instead of Anthropic
|
|
49
49
|
computer run <task> -s 30 # Limit to 30 steps
|
|
50
|
+
computer open <app> [options] # Open an app deterministically via its driver
|
|
51
|
+
computer apps # List app drivers + availability
|
|
50
52
|
computer screenshot # Capture current screen
|
|
51
53
|
computer sessions # List past sessions
|
|
52
54
|
computer session <id> # Show session details + action log
|
|
53
55
|
computer stats # Usage statistics
|
|
54
56
|
```
|
|
55
57
|
|
|
58
|
+
## Apps
|
|
59
|
+
|
|
60
|
+
Beyond AI-driven tasks (`computer run`), `computer` ships deterministic **app
|
|
61
|
+
drivers** that open and arrange desktop apps with zero AI in the loop — windows,
|
|
62
|
+
tabs, pane grids, and a command per pane.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
computer apps # List registered drivers and availability
|
|
66
|
+
computer open <app> [options] # Open/orchestrate an app via its driver
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Options for `computer open`:
|
|
70
|
+
|
|
71
|
+
| Option | Description |
|
|
72
|
+
|--------|-------------|
|
|
73
|
+
| `--grid RxC` | Split the window into R rows x C cols (panes fill row-major: left-to-right, top-to-bottom) |
|
|
74
|
+
| `--tabs "spec1,spec2,..."` | Multiple tabs in one window, each with its own grid (e.g. `"2x2,1x2,1x2"`) |
|
|
75
|
+
| `--run <cmd>` | Command for the next pane in order (repeatable); with `--tabs`, commands flow across tabs |
|
|
76
|
+
| `--all` | Run the single `--run` command in every pane |
|
|
77
|
+
| `--dir <path>` | Working directory — every pane `cd`s there first |
|
|
78
|
+
| `--max` | Maximize the new window (not native fullscreen) |
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# 2x2 grid, run codewith in all four panes, maximized
|
|
84
|
+
computer open ghostty --grid 2x2 --run "codewith" --all --max
|
|
85
|
+
|
|
86
|
+
# 2x2 grid with a different command per pane
|
|
87
|
+
computer open ghostty --grid 2x2 --run "htop" --run "btop" --run "vim" --run "bun dev"
|
|
88
|
+
|
|
89
|
+
# Three tabs (2x2, then two 1x2), every pane cd'd into the project
|
|
90
|
+
computer open ghostty --tabs "2x2,1x2,1x2" --dir ~/Workspace/myproject
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Drivers:**
|
|
94
|
+
|
|
95
|
+
- **ghostty** — Ghostty terminal (macOS, Ghostty 1.3+). Uses Ghostty's native
|
|
96
|
+
AppleScript dictionary for windows, tabs, and splits. Requires
|
|
97
|
+
`/Applications/Ghostty.app` (or `ghostty` on PATH).
|
|
98
|
+
|
|
99
|
+
Drivers are app-generic: each implements `available()` (with a reason when
|
|
100
|
+
unavailable, e.g. on Linux) and `open(spec)`. New drivers register in
|
|
101
|
+
`src/apps/registry.ts`.
|
|
102
|
+
|
|
103
|
+
The same surface is exposed over MCP via `computer_open_app`
|
|
104
|
+
(params: `app`, `grid`, `tabs`, `run[]`, `all`, `dir`, `max` — falls back to a
|
|
105
|
+
plain macOS app launch for apps without a driver) and `computer_list_apps`.
|
|
106
|
+
|
|
56
107
|
## MCP Server
|
|
57
108
|
|
|
58
109
|
Add to your Claude Code config:
|
|
@@ -159,6 +210,22 @@ const result = await driver.execute({
|
|
|
159
210
|
|
|
160
211
|
Sessions and action logs are stored in `~/.hasna/computer/computer.db` (SQLite).
|
|
161
212
|
|
|
213
|
+
## Storage Sync
|
|
214
|
+
|
|
215
|
+
Optional Postgres sync is available through package-local commands:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
export HASNA_COMPUTER_DATABASE_URL=postgres://...
|
|
219
|
+
computer storage status
|
|
220
|
+
computer storage push
|
|
221
|
+
computer storage pull
|
|
222
|
+
computer storage sync
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The MCP server also exposes `storage_status`, `storage_push`, `storage_pull`, and `storage_sync`.
|
|
226
|
+
|
|
227
|
+
`COMPUTER_DATABASE_URL` is accepted as the non-Hasna fallback database URL.
|
|
228
|
+
|
|
162
229
|
## License
|
|
163
230
|
|
|
164
231
|
Apache-2.0
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PaneGrid } from "../types.js";
|
|
2
|
+
/** Parse "RxC" (e.g. "2x2", "3x1") into a PaneGrid. Throws on invalid input. */
|
|
3
|
+
export declare function parseGrid(spec: string): PaneGrid;
|
|
4
|
+
/** Parse a comma-separated tabs spec like "2x2,1x2,1x2" into one grid per tab. */
|
|
5
|
+
export declare function parseTabsSpec(spec: string): PaneGrid[];
|
|
6
|
+
/** Escape a string for embedding inside an AppleScript double-quoted literal. */
|
|
7
|
+
export declare function escapeAppleScript(s: string): string;
|
|
8
|
+
/** Single-quote a string for POSIX shells (used for `cd <dir>`). */
|
|
9
|
+
export declare function shellQuote(s: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Map run commands onto panes (row-major across tabs in order).
|
|
12
|
+
* - `all` fills every pane with the single command (requires exactly one).
|
|
13
|
+
* - Otherwise commands are assigned in order; extra panes get undefined.
|
|
14
|
+
* Throws when there are more commands than panes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assignPaneCommands(totalPanes: number, run: string[], all: boolean): (string | undefined)[];
|
|
17
|
+
export interface GhosttyScriptOptions {
|
|
18
|
+
/** One grid per tab; the first tab reuses the new window's selected tab. */
|
|
19
|
+
tabs: PaneGrid[];
|
|
20
|
+
/** Command per pane, row-major across tabs in order. undefined = empty shell. */
|
|
21
|
+
commands?: (string | undefined)[];
|
|
22
|
+
/** Working directory — every pane cds here before its command. */
|
|
23
|
+
dir?: string;
|
|
24
|
+
/** Maximize the new window (toggle_maximize, not native fullscreen). */
|
|
25
|
+
max?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the full AppleScript for opening one Ghostty window with the given
|
|
29
|
+
* tabs/grids/commands. Pure — returns the script string.
|
|
30
|
+
*
|
|
31
|
+
* Grid algorithm (per tab): build column 0 downward (split direction down
|
|
32
|
+
* from the previous row), then split each row rightward C-1 times, then
|
|
33
|
+
* equalize once. Commands inject row-major with `input text` + enter key.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildGhosttyScript(opts: GhosttyScriptOptions): string;
|
|
36
|
+
//# sourceMappingURL=applescript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applescript.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/applescript.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAShD;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAMtD;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EAAE,EACb,GAAG,EAAE,OAAO,GACX,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAWxB;AAED,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAClC,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAiErE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applescript.test.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/applescript.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AppAvailability, AppDriver } from "../types.js";
|
|
2
|
+
export interface GhosttyEnvironment {
|
|
3
|
+
platform?: NodeJS.Platform | string;
|
|
4
|
+
hasAppBundle?: boolean;
|
|
5
|
+
hasBinary?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** Availability check, injectable for tests. */
|
|
8
|
+
export declare function ghosttyAvailability(env?: GhosttyEnvironment): AppAvailability;
|
|
9
|
+
export declare const ghosttyDriver: AppDriver;
|
|
10
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/driver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAKpG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,kBAAuB,GAAG,eAAe,CAWjF;AAmBD,eAAO,MAAM,aAAa,EAAE,SAiD3B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AppDriver } from "./types.js";
|
|
2
|
+
export declare function registerAppDriver(driver: AppDriver): void;
|
|
3
|
+
export declare function getAppDriver(name: string): AppDriver | undefined;
|
|
4
|
+
export declare function listAppDrivers(): AppDriver[];
|
|
5
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/apps/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAEzD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEhE;AAED,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../src/apps/registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** A pane grid: R rows x C cols. Panes are addressed row-major. */
|
|
2
|
+
export interface PaneGrid {
|
|
3
|
+
rows: number;
|
|
4
|
+
cols: number;
|
|
5
|
+
}
|
|
6
|
+
/** Declarative description of how to open/arrange an app. */
|
|
7
|
+
export interface AppOpenSpec {
|
|
8
|
+
/** Split the window into rows x cols panes (single tab). */
|
|
9
|
+
grid?: PaneGrid;
|
|
10
|
+
/** Multiple tabs in one window, each with its own grid. Overrides `grid`. */
|
|
11
|
+
tabs?: PaneGrid[];
|
|
12
|
+
/** Commands per pane, row-major across tabs in order. */
|
|
13
|
+
run?: string[];
|
|
14
|
+
/** Fill every pane with the single `run` command. */
|
|
15
|
+
all?: boolean;
|
|
16
|
+
/** Working directory — every pane cds here before running its command. */
|
|
17
|
+
dir?: string;
|
|
18
|
+
/** Maximize the new window (not native fullscreen). */
|
|
19
|
+
max?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Whether a driver can run on this machine, and why not if it can't. */
|
|
22
|
+
export interface AppAvailability {
|
|
23
|
+
available: boolean;
|
|
24
|
+
/** Human-readable reason when unavailable. */
|
|
25
|
+
reason?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Result of an open() call. */
|
|
28
|
+
export interface AppOpenResult {
|
|
29
|
+
ok: boolean;
|
|
30
|
+
message: string;
|
|
31
|
+
/** Total panes created (when applicable). */
|
|
32
|
+
panes?: number;
|
|
33
|
+
/** Tabs created (when applicable). */
|
|
34
|
+
tabs?: number;
|
|
35
|
+
}
|
|
36
|
+
/** A deterministic driver for one desktop application. */
|
|
37
|
+
export interface AppDriver {
|
|
38
|
+
/** Registry key, e.g. "ghostty". Lowercase. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** One-line human description. */
|
|
41
|
+
description: string;
|
|
42
|
+
/** Check availability on this machine. */
|
|
43
|
+
available(): AppAvailability;
|
|
44
|
+
/** Open/orchestrate the app according to spec. */
|
|
45
|
+
open(spec: AppOpenSpec): Promise<AppOpenResult>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/apps/types.ts"],"names":[],"mappings":"AAOA,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;IAClB,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,qDAAqD;IACrD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,SAAS,IAAI,eAAe,CAAC;IAC7B,kDAAkD;IAClD,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACjD"}
|