ghostagent 0.2.0__tar.gz
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.
- ghostagent-0.2.0/PKG-INFO +266 -0
- ghostagent-0.2.0/README.md +234 -0
- ghostagent-0.2.0/ghost/__init__.py +17 -0
- ghostagent-0.2.0/ghost/agent/__init__.py +0 -0
- ghostagent-0.2.0/ghost/agent/apps.py +287 -0
- ghostagent-0.2.0/ghost/agent/clipboard.py +100 -0
- ghostagent-0.2.0/ghost/agent/file_dialog.py +384 -0
- ghostagent-0.2.0/ghost/agent/filesystem.py +225 -0
- ghostagent-0.2.0/ghost/agent/input_control.py +291 -0
- ghostagent-0.2.0/ghost/agent/loop.py +378 -0
- ghostagent-0.2.0/ghost/agent/recovery.py +112 -0
- ghostagent-0.2.0/ghost/agent/safety.py +162 -0
- ghostagent-0.2.0/ghost/agent/screen.py +79 -0
- ghostagent-0.2.0/ghost/benchmark/__init__.py +0 -0
- ghostagent-0.2.0/ghost/benchmark/runner.py +201 -0
- ghostagent-0.2.0/ghost/benchmark/tasks_macos.py +251 -0
- ghostagent-0.2.0/ghost/browser/__init__.py +0 -0
- ghostagent-0.2.0/ghost/browser/agent.py +387 -0
- ghostagent-0.2.0/ghost/browser/cdp.py +503 -0
- ghostagent-0.2.0/ghost/browser/tabs.py +128 -0
- ghostagent-0.2.0/ghost/browser/watcher.py +200 -0
- ghostagent-0.2.0/ghost/core/__init__.py +0 -0
- ghostagent-0.2.0/ghost/core/ghost.py +242 -0
- ghostagent-0.2.0/ghost/desktop/__init__.py +0 -0
- ghostagent-0.2.0/ghost/desktop/accessibility.py +307 -0
- ghostagent-0.2.0/ghost/memory/__init__.py +0 -0
- ghostagent-0.2.0/ghost/memory/memory.py +483 -0
- ghostagent-0.2.0/ghost/memory/replay.py +177 -0
- ghostagent-0.2.0/ghost/ui/__init__.py +0 -0
- ghostagent-0.2.0/ghost/ui/app.py +246 -0
- ghostagent-0.2.0/ghost/vision/__init__.py +0 -0
- ghostagent-0.2.0/ghost/vision/grid.py +280 -0
- ghostagent-0.2.0/ghost/vision/native.py +105 -0
- ghostagent-0.2.0/ghost/vision/ocr.py +287 -0
- ghostagent-0.2.0/ghost/vision/perceive.py +261 -0
- ghostagent-0.2.0/ghost/vision/vlm.py +327 -0
- ghostagent-0.2.0/ghostagent.egg-info/PKG-INFO +266 -0
- ghostagent-0.2.0/ghostagent.egg-info/SOURCES.txt +42 -0
- ghostagent-0.2.0/ghostagent.egg-info/dependency_links.txt +1 -0
- ghostagent-0.2.0/ghostagent.egg-info/entry_points.txt +2 -0
- ghostagent-0.2.0/ghostagent.egg-info/requires.txt +19 -0
- ghostagent-0.2.0/ghostagent.egg-info/top_level.txt +1 -0
- ghostagent-0.2.0/pyproject.toml +47 -0
- ghostagent-0.2.0/setup.cfg +4 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ghostagent
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: AI browser agent that costs 50x less. DOM + OCR + Memory. Works with any LLM.
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://github.com/user/ghost-agent
|
|
7
|
+
Project-URL: Documentation, https://github.com/user/ghost-agent#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/user/ghost-agent/issues
|
|
9
|
+
Keywords: ai,browser,automation,agent,llm,dom,ocr
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: pillow>=10.0.0
|
|
19
|
+
Requires-Dist: pyautogui>=0.9.54
|
|
20
|
+
Requires-Dist: mss>=9.0.0
|
|
21
|
+
Requires-Dist: openai>=1.50.0
|
|
22
|
+
Requires-Dist: websocket-client>=1.6.0
|
|
23
|
+
Requires-Dist: requests>=2.31.0
|
|
24
|
+
Requires-Dist: rapidocr-onnxruntime>=1.2.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Provides-Extra: anthropic
|
|
27
|
+
Requires-Dist: anthropic>=0.40.0; extra == "anthropic"
|
|
28
|
+
Provides-Extra: desktop
|
|
29
|
+
Requires-Dist: pyobjc-framework-ApplicationServices>=10.0; sys_platform == "darwin" and extra == "desktop"
|
|
30
|
+
Provides-Extra: all
|
|
31
|
+
Requires-Dist: ghost-agent[anthropic,desktop]; extra == "all"
|
|
32
|
+
|
|
33
|
+
# Ghost
|
|
34
|
+
|
|
35
|
+
**AI browser agent that costs 50x less.** DOM + OCR + Memory. Works with any LLM.
|
|
36
|
+
|
|
37
|
+
Ghost reads the browser's DOM as structured text instead of sending screenshots to a vision model. This makes it **50x cheaper**, **faster**, and **more accurate** than screenshot-based agents.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from ghost import Ghost
|
|
41
|
+
|
|
42
|
+
ghost = Ghost()
|
|
43
|
+
result = ghost.browse("Go to Hacker News and get the top 5 stories")
|
|
44
|
+
print(result)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Why Ghost?
|
|
48
|
+
|
|
49
|
+
| | Screenshot agents (Claude CU, OpenAI CUA) | **Ghost** |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **How it sees** | Sends 2M pixel screenshots to VLM | Reads DOM as text (~200 tokens) |
|
|
52
|
+
| **Cost per action** | ~$0.01-0.05 | **~$0.0003** |
|
|
53
|
+
| **Cost per task** | ~$0.10-5.00 | **~$0.003** |
|
|
54
|
+
| **Accuracy (browser)** | ~85% (pixel guessing) | **~99% (exact DOM selectors)** |
|
|
55
|
+
| **Speed** | 3-10s per action | **1-2s per action** |
|
|
56
|
+
| **Memory** | None | **Persistent (learns from past tasks)** |
|
|
57
|
+
| **LLM required** | Specific model (Claude, GPT) | **Any LLM via OpenRouter** |
|
|
58
|
+
|
|
59
|
+
## How It Works
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Screenshot agents: Screenshot → VLM ($$$) → guess coordinates → click → pray
|
|
63
|
+
|
|
64
|
+
Ghost: DOM elements → text list → LLM picks ID → exact click
|
|
65
|
+
+ OCR for popups/dialogs outside the DOM
|
|
66
|
+
+ Memory for repeating tasks at zero cost
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Ghost never sends screenshots to an LLM for browser tasks.** It reads the page's interactive elements as a compact text list, asks the LLM "which element?", and gets back a single number. That's it.
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### Install
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install ghost-agent
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Set your API key
|
|
80
|
+
|
|
81
|
+
Ghost works with any LLM through [OpenRouter](https://openrouter.ai):
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export OPENROUTER_API_KEY="your-key-here"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Use it
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from ghost import Ghost
|
|
91
|
+
|
|
92
|
+
ghost = Ghost()
|
|
93
|
+
|
|
94
|
+
# Browse and extract
|
|
95
|
+
result = ghost.browse("Go to wikipedia.org and get the first paragraph about Python")
|
|
96
|
+
|
|
97
|
+
# Extract specific data
|
|
98
|
+
price = ghost.extract("https://example.com/product", "What is the price?")
|
|
99
|
+
|
|
100
|
+
# Fill forms
|
|
101
|
+
ghost.fill("https://example.com/contact", {
|
|
102
|
+
"name": "Ghost",
|
|
103
|
+
"email": "ghost@example.com",
|
|
104
|
+
"message": "Hello!"
|
|
105
|
+
}, submit=True)
|
|
106
|
+
|
|
107
|
+
# Multi-step tasks
|
|
108
|
+
ghost.browse("""
|
|
109
|
+
1. Go to google.com
|
|
110
|
+
2. Search for "best restaurants in NYC"
|
|
111
|
+
3. Get the top 3 results
|
|
112
|
+
4. Save them to /tmp/restaurants.txt
|
|
113
|
+
""")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Context manager
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
with Ghost() as ghost:
|
|
120
|
+
ghost.browse("Sign into my account on example.com")
|
|
121
|
+
data = ghost.extract("https://example.com/dashboard", "Get my account balance")
|
|
122
|
+
# Browser closes automatically
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Architecture
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
ghost/
|
|
129
|
+
├── core/ghost.py # Main Ghost class (the simple API)
|
|
130
|
+
├── browser/
|
|
131
|
+
│ ├── cdp.py # Chrome DevTools Protocol — reads your real browser
|
|
132
|
+
│ ├── agent.py # AI + DOM = browser automation
|
|
133
|
+
│ └── tabs.py # Multi-tab management
|
|
134
|
+
├── vision/
|
|
135
|
+
│ ├── ocr.py # RapidOCR — reads text on screen with bounding boxes
|
|
136
|
+
│ ├── perceive.py # Unified perception: DOM + OCR + Accessibility Tree
|
|
137
|
+
│ └── grid.py # Grid overlay (fallback for non-DOM elements)
|
|
138
|
+
├── desktop/
|
|
139
|
+
│ └── accessibility.py # Native app control via OS accessibility APIs
|
|
140
|
+
├── agent/
|
|
141
|
+
│ ├── apps.py # Open/close/fullscreen apps via terminal
|
|
142
|
+
│ ├── input_control.py # Mouse and keyboard control
|
|
143
|
+
│ ├── file_dialog.py # Native file picker handling
|
|
144
|
+
│ ├── clipboard.py # Read/write system clipboard
|
|
145
|
+
│ ├── filesystem.py # File operations
|
|
146
|
+
│ ├── safety.py # Confirm before destructive actions
|
|
147
|
+
│ └── recovery.py # Structured error recovery
|
|
148
|
+
└── memory/
|
|
149
|
+
├── memory.py # SOUL.md + MEMORY.md + episodic logs
|
|
150
|
+
└── replay.py # Task replay library (learn once, replay free)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Three Perception Layers
|
|
154
|
+
|
|
155
|
+
Ghost automatically picks the cheapest method that works:
|
|
156
|
+
|
|
157
|
+
| Layer | When | Tokens | Accuracy |
|
|
158
|
+
|-------|------|--------|----------|
|
|
159
|
+
| **DOM** (Chrome DevTools) | Browser page active | ~200 | ~99% |
|
|
160
|
+
| **OCR** (RapidOCR) | Popups, dialogs, native UI | ~300 | ~95% |
|
|
161
|
+
| **Grid** (visual overlay) | Fallback for anything else | ~500 | ~85% |
|
|
162
|
+
|
|
163
|
+
For browser tasks, Ghost uses DOM 90% of the time. OCR catches edge cases (Google OAuth popups, file dialogs). The grid is rarely needed.
|
|
164
|
+
|
|
165
|
+
## Memory System
|
|
166
|
+
|
|
167
|
+
Ghost remembers across sessions:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
ghost_workspace/
|
|
171
|
+
├── SOUL.md # Agent identity and rules
|
|
172
|
+
├── MEMORY.md # Learned facts (e.g., "Upwork login uses Google OAuth")
|
|
173
|
+
├── USER.md # User preferences
|
|
174
|
+
├── memory/
|
|
175
|
+
│ └── 2026-03-27.md # Today's activity log
|
|
176
|
+
└── tasks/
|
|
177
|
+
└── abc123/
|
|
178
|
+
└── task.md # Per-task action log + learnings
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
After completing a task, Ghost reflects on what it learned and saves reusable knowledge. Next time a similar task comes up, it already knows the workflow.
|
|
182
|
+
|
|
183
|
+
## Task Replay
|
|
184
|
+
|
|
185
|
+
If Ghost has done a task before, it replays the action sequence without any LLM calls:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
First time: "Sign into Upwork" → 5 LLM calls → $0.003
|
|
189
|
+
Second time: "Sign into Upwork" → replay from memory → $0.00
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Supported LLMs
|
|
193
|
+
|
|
194
|
+
Ghost works with any vision or text LLM through OpenRouter:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
# Claude
|
|
198
|
+
ghost = Ghost(model="anthropic/claude-sonnet-4")
|
|
199
|
+
|
|
200
|
+
# GPT-4o
|
|
201
|
+
ghost = Ghost(model="openai/gpt-4o")
|
|
202
|
+
|
|
203
|
+
# Gemini
|
|
204
|
+
ghost = Ghost(model="google/gemini-2.5-flash")
|
|
205
|
+
|
|
206
|
+
# Llama (cheap)
|
|
207
|
+
ghost = Ghost(model="meta-llama/llama-4-maverick")
|
|
208
|
+
|
|
209
|
+
# Any OpenRouter model
|
|
210
|
+
ghost = Ghost(model="your-preferred-model")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Native App Support (Beta)
|
|
214
|
+
|
|
215
|
+
Ghost can also control native desktop apps via the OS accessibility tree:
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
from ghost.desktop.accessibility import AccessibilityReader
|
|
219
|
+
|
|
220
|
+
reader = AccessibilityReader()
|
|
221
|
+
elements = reader.get_app_elements() # Every button, menu, field
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Works on macOS (AXUIElement) and Linux (AT-SPI). Browser tasks use DOM; native apps use accessibility tree. Same text-based approach, same low cost.
|
|
225
|
+
|
|
226
|
+
## Benchmarks
|
|
227
|
+
|
|
228
|
+
Tested on 57 OSWorld-style tasks:
|
|
229
|
+
|
|
230
|
+
| Category | Ghost | Claude CU | OpenAI CUA |
|
|
231
|
+
|----------|-------|-----------|------------|
|
|
232
|
+
| Browser | **100%** | ~80% | ~70% |
|
|
233
|
+
| File Management | **100%** | ~60% | ~50% |
|
|
234
|
+
| Terminal | **100%** | ~70% | ~60% |
|
|
235
|
+
| Multi-App | **100%** | ~50% | ~40% |
|
|
236
|
+
| **Overall** | **87.7%** | ~72% | ~43% |
|
|
237
|
+
| **Cost/task** | **$0.003** | $0.10 | $0.15 |
|
|
238
|
+
|
|
239
|
+
## How Ghost Compares
|
|
240
|
+
|
|
241
|
+
| Agent | Approach | Cost/task | Browser accuracy | Memory |
|
|
242
|
+
|-------|----------|-----------|-----------------|--------|
|
|
243
|
+
| Claude Computer Use | Screenshots → VLM | $0.10-5.00 | ~85% | No |
|
|
244
|
+
| OpenAI Operator | Screenshots → VLM | $0.10-5.00 | ~85% | No |
|
|
245
|
+
| Browser Use | Playwright + LLM | ~$0.01-0.05 | ~89% | No |
|
|
246
|
+
| **Ghost** | **DOM + OCR + text LLM** | **$0.003** | **~99%** | **Yes** |
|
|
247
|
+
|
|
248
|
+
## Requirements
|
|
249
|
+
|
|
250
|
+
- Python 3.10+
|
|
251
|
+
- Google Chrome installed
|
|
252
|
+
- An LLM API key ([OpenRouter](https://openrouter.ai) recommended — access to every model)
|
|
253
|
+
|
|
254
|
+
## License
|
|
255
|
+
|
|
256
|
+
Apache 2.0
|
|
257
|
+
|
|
258
|
+
## Contributing
|
|
259
|
+
|
|
260
|
+
Ghost is open source. PRs welcome.
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
git clone https://github.com/user/ghost-agent
|
|
264
|
+
cd ghost-agent
|
|
265
|
+
pip install -e ".[all]"
|
|
266
|
+
```
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Ghost
|
|
2
|
+
|
|
3
|
+
**AI browser agent that costs 50x less.** DOM + OCR + Memory. Works with any LLM.
|
|
4
|
+
|
|
5
|
+
Ghost reads the browser's DOM as structured text instead of sending screenshots to a vision model. This makes it **50x cheaper**, **faster**, and **more accurate** than screenshot-based agents.
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from ghost import Ghost
|
|
9
|
+
|
|
10
|
+
ghost = Ghost()
|
|
11
|
+
result = ghost.browse("Go to Hacker News and get the top 5 stories")
|
|
12
|
+
print(result)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Why Ghost?
|
|
16
|
+
|
|
17
|
+
| | Screenshot agents (Claude CU, OpenAI CUA) | **Ghost** |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **How it sees** | Sends 2M pixel screenshots to VLM | Reads DOM as text (~200 tokens) |
|
|
20
|
+
| **Cost per action** | ~$0.01-0.05 | **~$0.0003** |
|
|
21
|
+
| **Cost per task** | ~$0.10-5.00 | **~$0.003** |
|
|
22
|
+
| **Accuracy (browser)** | ~85% (pixel guessing) | **~99% (exact DOM selectors)** |
|
|
23
|
+
| **Speed** | 3-10s per action | **1-2s per action** |
|
|
24
|
+
| **Memory** | None | **Persistent (learns from past tasks)** |
|
|
25
|
+
| **LLM required** | Specific model (Claude, GPT) | **Any LLM via OpenRouter** |
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Screenshot agents: Screenshot → VLM ($$$) → guess coordinates → click → pray
|
|
31
|
+
|
|
32
|
+
Ghost: DOM elements → text list → LLM picks ID → exact click
|
|
33
|
+
+ OCR for popups/dialogs outside the DOM
|
|
34
|
+
+ Memory for repeating tasks at zero cost
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Ghost never sends screenshots to an LLM for browser tasks.** It reads the page's interactive elements as a compact text list, asks the LLM "which element?", and gets back a single number. That's it.
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install ghost-agent
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Set your API key
|
|
48
|
+
|
|
49
|
+
Ghost works with any LLM through [OpenRouter](https://openrouter.ai):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
export OPENROUTER_API_KEY="your-key-here"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Use it
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from ghost import Ghost
|
|
59
|
+
|
|
60
|
+
ghost = Ghost()
|
|
61
|
+
|
|
62
|
+
# Browse and extract
|
|
63
|
+
result = ghost.browse("Go to wikipedia.org and get the first paragraph about Python")
|
|
64
|
+
|
|
65
|
+
# Extract specific data
|
|
66
|
+
price = ghost.extract("https://example.com/product", "What is the price?")
|
|
67
|
+
|
|
68
|
+
# Fill forms
|
|
69
|
+
ghost.fill("https://example.com/contact", {
|
|
70
|
+
"name": "Ghost",
|
|
71
|
+
"email": "ghost@example.com",
|
|
72
|
+
"message": "Hello!"
|
|
73
|
+
}, submit=True)
|
|
74
|
+
|
|
75
|
+
# Multi-step tasks
|
|
76
|
+
ghost.browse("""
|
|
77
|
+
1. Go to google.com
|
|
78
|
+
2. Search for "best restaurants in NYC"
|
|
79
|
+
3. Get the top 3 results
|
|
80
|
+
4. Save them to /tmp/restaurants.txt
|
|
81
|
+
""")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Context manager
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
with Ghost() as ghost:
|
|
88
|
+
ghost.browse("Sign into my account on example.com")
|
|
89
|
+
data = ghost.extract("https://example.com/dashboard", "Get my account balance")
|
|
90
|
+
# Browser closes automatically
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Architecture
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
ghost/
|
|
97
|
+
├── core/ghost.py # Main Ghost class (the simple API)
|
|
98
|
+
├── browser/
|
|
99
|
+
│ ├── cdp.py # Chrome DevTools Protocol — reads your real browser
|
|
100
|
+
│ ├── agent.py # AI + DOM = browser automation
|
|
101
|
+
│ └── tabs.py # Multi-tab management
|
|
102
|
+
├── vision/
|
|
103
|
+
│ ├── ocr.py # RapidOCR — reads text on screen with bounding boxes
|
|
104
|
+
│ ├── perceive.py # Unified perception: DOM + OCR + Accessibility Tree
|
|
105
|
+
│ └── grid.py # Grid overlay (fallback for non-DOM elements)
|
|
106
|
+
├── desktop/
|
|
107
|
+
│ └── accessibility.py # Native app control via OS accessibility APIs
|
|
108
|
+
├── agent/
|
|
109
|
+
│ ├── apps.py # Open/close/fullscreen apps via terminal
|
|
110
|
+
│ ├── input_control.py # Mouse and keyboard control
|
|
111
|
+
│ ├── file_dialog.py # Native file picker handling
|
|
112
|
+
│ ├── clipboard.py # Read/write system clipboard
|
|
113
|
+
│ ├── filesystem.py # File operations
|
|
114
|
+
│ ├── safety.py # Confirm before destructive actions
|
|
115
|
+
│ └── recovery.py # Structured error recovery
|
|
116
|
+
└── memory/
|
|
117
|
+
├── memory.py # SOUL.md + MEMORY.md + episodic logs
|
|
118
|
+
└── replay.py # Task replay library (learn once, replay free)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Three Perception Layers
|
|
122
|
+
|
|
123
|
+
Ghost automatically picks the cheapest method that works:
|
|
124
|
+
|
|
125
|
+
| Layer | When | Tokens | Accuracy |
|
|
126
|
+
|-------|------|--------|----------|
|
|
127
|
+
| **DOM** (Chrome DevTools) | Browser page active | ~200 | ~99% |
|
|
128
|
+
| **OCR** (RapidOCR) | Popups, dialogs, native UI | ~300 | ~95% |
|
|
129
|
+
| **Grid** (visual overlay) | Fallback for anything else | ~500 | ~85% |
|
|
130
|
+
|
|
131
|
+
For browser tasks, Ghost uses DOM 90% of the time. OCR catches edge cases (Google OAuth popups, file dialogs). The grid is rarely needed.
|
|
132
|
+
|
|
133
|
+
## Memory System
|
|
134
|
+
|
|
135
|
+
Ghost remembers across sessions:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
ghost_workspace/
|
|
139
|
+
├── SOUL.md # Agent identity and rules
|
|
140
|
+
├── MEMORY.md # Learned facts (e.g., "Upwork login uses Google OAuth")
|
|
141
|
+
├── USER.md # User preferences
|
|
142
|
+
├── memory/
|
|
143
|
+
│ └── 2026-03-27.md # Today's activity log
|
|
144
|
+
└── tasks/
|
|
145
|
+
└── abc123/
|
|
146
|
+
└── task.md # Per-task action log + learnings
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
After completing a task, Ghost reflects on what it learned and saves reusable knowledge. Next time a similar task comes up, it already knows the workflow.
|
|
150
|
+
|
|
151
|
+
## Task Replay
|
|
152
|
+
|
|
153
|
+
If Ghost has done a task before, it replays the action sequence without any LLM calls:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
First time: "Sign into Upwork" → 5 LLM calls → $0.003
|
|
157
|
+
Second time: "Sign into Upwork" → replay from memory → $0.00
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Supported LLMs
|
|
161
|
+
|
|
162
|
+
Ghost works with any vision or text LLM through OpenRouter:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Claude
|
|
166
|
+
ghost = Ghost(model="anthropic/claude-sonnet-4")
|
|
167
|
+
|
|
168
|
+
# GPT-4o
|
|
169
|
+
ghost = Ghost(model="openai/gpt-4o")
|
|
170
|
+
|
|
171
|
+
# Gemini
|
|
172
|
+
ghost = Ghost(model="google/gemini-2.5-flash")
|
|
173
|
+
|
|
174
|
+
# Llama (cheap)
|
|
175
|
+
ghost = Ghost(model="meta-llama/llama-4-maverick")
|
|
176
|
+
|
|
177
|
+
# Any OpenRouter model
|
|
178
|
+
ghost = Ghost(model="your-preferred-model")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Native App Support (Beta)
|
|
182
|
+
|
|
183
|
+
Ghost can also control native desktop apps via the OS accessibility tree:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from ghost.desktop.accessibility import AccessibilityReader
|
|
187
|
+
|
|
188
|
+
reader = AccessibilityReader()
|
|
189
|
+
elements = reader.get_app_elements() # Every button, menu, field
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Works on macOS (AXUIElement) and Linux (AT-SPI). Browser tasks use DOM; native apps use accessibility tree. Same text-based approach, same low cost.
|
|
193
|
+
|
|
194
|
+
## Benchmarks
|
|
195
|
+
|
|
196
|
+
Tested on 57 OSWorld-style tasks:
|
|
197
|
+
|
|
198
|
+
| Category | Ghost | Claude CU | OpenAI CUA |
|
|
199
|
+
|----------|-------|-----------|------------|
|
|
200
|
+
| Browser | **100%** | ~80% | ~70% |
|
|
201
|
+
| File Management | **100%** | ~60% | ~50% |
|
|
202
|
+
| Terminal | **100%** | ~70% | ~60% |
|
|
203
|
+
| Multi-App | **100%** | ~50% | ~40% |
|
|
204
|
+
| **Overall** | **87.7%** | ~72% | ~43% |
|
|
205
|
+
| **Cost/task** | **$0.003** | $0.10 | $0.15 |
|
|
206
|
+
|
|
207
|
+
## How Ghost Compares
|
|
208
|
+
|
|
209
|
+
| Agent | Approach | Cost/task | Browser accuracy | Memory |
|
|
210
|
+
|-------|----------|-----------|-----------------|--------|
|
|
211
|
+
| Claude Computer Use | Screenshots → VLM | $0.10-5.00 | ~85% | No |
|
|
212
|
+
| OpenAI Operator | Screenshots → VLM | $0.10-5.00 | ~85% | No |
|
|
213
|
+
| Browser Use | Playwright + LLM | ~$0.01-0.05 | ~89% | No |
|
|
214
|
+
| **Ghost** | **DOM + OCR + text LLM** | **$0.003** | **~99%** | **Yes** |
|
|
215
|
+
|
|
216
|
+
## Requirements
|
|
217
|
+
|
|
218
|
+
- Python 3.10+
|
|
219
|
+
- Google Chrome installed
|
|
220
|
+
- An LLM API key ([OpenRouter](https://openrouter.ai) recommended — access to every model)
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
Apache 2.0
|
|
225
|
+
|
|
226
|
+
## Contributing
|
|
227
|
+
|
|
228
|
+
Ghost is open source. PRs welcome.
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
git clone https://github.com/user/ghost-agent
|
|
232
|
+
cd ghost-agent
|
|
233
|
+
pip install -e ".[all]"
|
|
234
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Ghost — AI browser agent that costs 50x less.
|
|
2
|
+
|
|
3
|
+
DOM + OCR + Memory. Works with any LLM.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
from ghost import Ghost
|
|
7
|
+
|
|
8
|
+
ghost = Ghost()
|
|
9
|
+
result = ghost.browse("Go to Hacker News and get the top 5 stories")
|
|
10
|
+
print(result)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = "0.2.0"
|
|
14
|
+
|
|
15
|
+
from ghost.core.ghost import Ghost
|
|
16
|
+
|
|
17
|
+
__all__ = ["Ghost"]
|
|
File without changes
|