Skip to content

Commit 695a2f9

Browse files
committed
feat: add PumpFun plugin, browser mode, strip stubs for v0.1.0 release
PumpFun integration with bonding curve reads, token launches, and fee collection. Browser mode with agent-assisted navigation and SSRF guard. Comment out 7 unfinished plugin stubs from registry. Fix electron-builder output dir and package script for CI. Rewrite README for public release.
1 parent dfd1c41 commit 695a2f9

31 files changed

Lines changed: 2126 additions & 172 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,9 @@ features/
5757
# Claude Code config (per-machine)
5858
.claude/
5959
.mcp.json
60+
61+
# Internal dev artifacts
62+
PLUGIN_TODOS.md
63+
.planning/
64+
.playwright-mcp/
65+
Usersoffic.claudeplans/

README.md

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
<p align="center">
22
<h1 align="center">DAEMON</h1>
3-
<p align="center">The IDE built for developers who ship with AI.</p>
3+
<p align="center">An open-source IDE built for AI-native development.</p>
44
</p>
55

66
<p align="center">
77
<a href="#install">Install</a> &middot;
88
<a href="#features">Features</a> &middot;
9+
<a href="#architecture">Architecture</a> &middot;
910
<a href="#development">Development</a> &middot;
1011
<a href="CONTRIBUTING.md">Contributing</a>
1112
</p>
1213

1314
---
1415

15-
DAEMON is an open-source Electron IDE designed from the ground up for AI-native development. Monaco editor, integrated terminals, Claude Code agent spawning, MCP management, Solana wallet, and a plugin system — all in one window.
16+
<!-- screenshot: hero — full window with editor, terminal, and sidebar visible -->
1617

17-
Built for solo developers who use AI agents as their primary workflow. Not a VS Code fork. Every panel is purpose-built.
18+
DAEMON is a standalone Electron IDE designed around AI agent workflows. It ships a Monaco editor, integrated PTY terminals, Claude Code agent spawning, MCP server management, a Git panel, a Solana wallet, and a plugin system — all purpose-built from scratch. Not a VS Code fork.
1819

1920
## Install
2021

21-
Download the latest release from [Releases](https://github.com/nullxnothing/daemon/releases), or build from source:
22+
**Download** the latest `.exe` or `.dmg` from [Releases](https://github.com/nullxnothing/daemon/releases).
23+
24+
Or build from source:
2225

2326
```bash
2427
git clone https://github.com/nullxnothing/daemon.git
@@ -27,60 +30,74 @@ pnpm install
2730
pnpm run package
2831
```
2932

30-
Requires Node.js 22+ and pnpm 9+.
33+
Requires **Node.js 22+** and **pnpm 9+**.
3134

3235
## Features
3336

34-
**Editor** — Monaco with offline support, syntax highlighting, multi-tab, breadcrumbs, Ctrl+S save, markdown tidy with AI diff preview.
37+
<!-- screenshot: editor with multiple tabs, breadcrumbs, and file tree -->
38+
39+
**Editor** — Monaco running fully offline via a custom protocol handler. Multi-tab, breadcrumbs, syntax highlighting, Ctrl+S save. No CDN dependency.
40+
41+
**Terminal** — Real PTY sessions powered by node-pty and xterm.js. Multiple tabs, split panes, command history search (Ctrl+R), tab-completion hints, and dedicated agent session management.
42+
43+
<!-- screenshot: agent launcher with model selection and MCP config -->
44+
45+
**Agent Launcher** — Spawn Claude Code agents with custom system prompts, model selection, and per-project MCP configurations. Agents run as real CLI sessions in dedicated terminal tabs.
46+
47+
**MCP Management** — Toggle project-level and global MCP servers from the sidebar. Changes write directly to `.claude/settings.json` and `.mcp.json` with a restart indicator when configs change.
3548

36-
**Terminal**Full PTY terminal with multiple tabs, split panes, command history search (Ctrl+R), tab-completion hints, and agent session management.
49+
**Git**Branch switching, per-file and folder-level staging, commit, push, stash save/pop, branch creation, and tag management.
3750

38-
**Agent Launcher**Create and spawn Claude Code agents with custom system prompts, model selection (Opus/Sonnet/Haiku), and per-project MCP configurations. Agents run as real CLI sessions in dedicated terminal tabs.
51+
**Wallet**Live Solana portfolio tracking via Helius. SOL balance and SPL token holdings with USD values from Jupiter.
3952

40-
**MCP Management** — Toggle project-level and global MCP servers from the sidebar. Changes write directly to `.claude/settings.json` and `.mcp.json`. Restart indicator when config changes.
53+
<!-- screenshot: wallet panel showing token balances -->
4154

42-
**Git**Branch switching, staging (individual file + folder-level + stage all), commit with AI-generated messages, push, stash save/pop, branch and tag creation.
55+
**Settings**API keys encrypted via the OS keychain. MCP integrations, agent defaults, and display preferences.
4356

44-
**Wallet**Live Solana portfolio tracking via Helius RPC. SOL balance, SPL token holdings with USD values from Jupiter price API.
57+
**Tools Browser**Create, import, and run scripts (TypeScript, Python, Shell) with per-language execution.
4558

46-
**Settings**Encrypted API key storage (OS keychain), MCP integrations, agent defaults, display preferences.
59+
**Embedded Browser**Built-in browser with a security sandbox for previewing and testing.
4760

48-
**Tools**Built-in tool browser for creating, importing, and running scripts (TypeScript, Python, Shell) with per-language execution.
61+
**PumpFun Integration**Token launches and bonding curve interactions directly from the IDE.
4962

50-
**Plugins**Image generation (Gemini), tweet drafting with voice profiles, embedded browser (Playwright), Telegram client (GramJS), Gmail integration, Remotion video editor, subscription tracker, background services manager.
63+
**Multi-Project Tabs**Tabbed project switching with per-project terminal sessions, MCP configs, and file trees. Context switching without losing state.
5164

52-
**Multi-Project**Tabbed project switching with per-project terminal sessions, MCP configs, and file trees. Seamless context switching without losing state.
65+
**Plugin System**Extensible architecture for loading additional panels and integrations.
5366

5467
## Architecture
5568

5669
```
57-
electron/ Main process (Node.js)
58-
ipc/ IPC handler per domain (agents, git, terminal, etc.)
59-
services/ Business logic, never imported from renderer
60-
db/ SQLite with WAL mode, versioned migrations
61-
src/ Renderer (React 18 + TypeScript)
62-
panels/ One directory per UI panel
63-
store/ Zustand state management
64-
plugins/ Plugin registry and lazy-loaded components
65-
styles/ CSS custom properties and base reset
70+
electron/
71+
main/ App entry, window management, protocol handlers
72+
ipc/ One handler per domain (agents, git, terminal, wallet, ...)
73+
services/ Business logic — never imported from renderer
74+
db/ SQLite (WAL mode), versioned migrations
75+
76+
src/
77+
panels/ One directory per UI panel
78+
store/ Zustand state management
79+
plugins/ Plugin registry, lazy-loaded components
80+
components/ Shared UI primitives
81+
82+
styles/ CSS custom properties and base reset
6683
```
6784

68-
Key architectural decisions:
69-
- All database access in main process only — renderer communicates via IPC
70-
- Every IPC handler returns `{ ok: true, data }` or `{ ok: false, error }`
71-
- Native modules (`better-sqlite3`, `node-pty`) unpacked from ASAR for production
72-
- Monaco editor runs offline via custom protocol handler — no CDN dependency
73-
- CSS Modules with a strict token system — no utility frameworks
85+
Key decisions:
86+
- All database access runs in the main process. The renderer communicates exclusively via IPC.
87+
- Every IPC handler returns `{ ok, data }` or `{ ok, error }` — no raw throws across the bridge.
88+
- Native modules (`better-sqlite3`, `node-pty`) are unpacked from ASAR for production builds.
89+
- Monaco runs offline through a custom `monaco-editor://` protocol — zero network requests.
90+
- CSS Modules with a design token system. No utility CSS frameworks.
7491

7592
## Tech Stack
7693

7794
| Layer | Technology |
7895
|-------|-----------|
7996
| Shell | Electron 33 |
80-
| Build | Vite + vite-plugin-electron |
81-
| UI | React 18 + TypeScript |
97+
| Build | Vite |
98+
| UI | React 18, TypeScript |
8299
| Editor | Monaco Editor |
83-
| Terminal | node-pty + xterm.js |
100+
| Terminal | node-pty, xterm.js |
84101
| State | Zustand |
85102
| Database | better-sqlite3 (WAL) |
86103
| Git | simple-git |
@@ -89,30 +106,15 @@ Key architectural decisions:
89106
## Development
90107

91108
```bash
92-
pnpm install # Install deps + rebuild native modules
109+
pnpm install # Install dependencies and rebuild native modules
93110
pnpm run dev # Dev server with hot reload
94111
pnpm run typecheck # TypeScript validation
95-
pnpm run test # Run test suite (Vitest)
112+
pnpm run test # Run tests (Vitest)
96113
pnpm run build # Production build
97-
pnpm run package # Create .exe / .dmg
114+
pnpm run package # Create distributable (.exe / .dmg)
98115
```
99116

100-
See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.
101-
102-
## Roadmap
103-
104-
- [x] Core IDE (editor, terminal, file explorer, project management)
105-
- [x] Agent system (launcher, Claude Code spawning, MCP management)
106-
- [x] Developer panels (git, env manager, ports, processes, wallet)
107-
- [x] Settings and tools browser
108-
- [x] Production infrastructure (error recovery, resource management, logging)
109-
- [ ] Image generation (Gemini)
110-
- [ ] Gmail integration
111-
- [ ] Tweet generator with voice profiles
112-
- [ ] Subscription tracker
113-
- [ ] Remotion video panel
114-
- [ ] Embedded browser with Playwright CDP
115-
- [ ] Chrome extension context bridge
117+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on pull requests and code style.
116118

117119
## License
118120

electron-builder.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"productName": "DAEMON",
55
"asar": true,
66
"directories": {
7-
"output": "dist"
7+
"output": "release"
88
},
99
"files": [
1010
"dist-electron",

electron/db/migrations.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type Database from 'better-sqlite3'
2-
import { SCHEMA_V1, SCHEMA_V2, SCHEMA_V3, SCHEMA_V4, SCHEMA_V5, SCHEMA_V6, SCHEMA_V7, SCHEMA_V8 } from './schema'
2+
import { SCHEMA_V1, SCHEMA_V2, SCHEMA_V3, SCHEMA_V4, SCHEMA_V5, SCHEMA_V6, SCHEMA_V7, SCHEMA_V8, SCHEMA_V9 } from './schema'
33

44
export function runMigrations(db: Database.Database) {
55
db.exec(`
@@ -79,6 +79,17 @@ export function runMigrations(db: Database.Database) {
7979
})()
8080
}
8181

82+
if (currentVersion < 9) {
83+
db.transaction(() => {
84+
// Each ALTER TABLE must be separate — SQLite doesn't support multi-ALTER in one exec
85+
const stmts = SCHEMA_V9.split(';').map((s) => s.trim()).filter(Boolean)
86+
for (const stmt of stmts) {
87+
try { db.exec(stmt) } catch { /* column/index may already exist */ }
88+
}
89+
db.prepare('INSERT INTO _migrations (version) VALUES (?)').run(9)
90+
})()
91+
}
92+
8293
// Ensure built-in tools exist (idempotent — handles upgrades where table exists but seed was missed)
8394
try {
8495
const hasRecovery = db.prepare("SELECT id FROM tools WHERE id = 'builtin-wallet-recovery'").get()
@@ -87,6 +98,19 @@ export function runMigrations(db: Database.Database) {
8798
console.warn('[Migrations] built-in tools seed check failed:', (err as Error).message)
8899
}
89100

101+
// Ensure all registry plugins have DB rows (handles plugins added after initial migration)
102+
try {
103+
const newPlugins = [
104+
{ id: 'pumpfun', order: 9 },
105+
]
106+
const insert = db.prepare('INSERT OR IGNORE INTO plugins (id, enabled, sort_order, config) VALUES (?,?,?,?)')
107+
for (const p of newPlugins) {
108+
insert.run(p.id, 1, p.order, '{}')
109+
}
110+
} catch (err) {
111+
console.warn('[Migrations] plugin seed check failed:', (err as Error).message)
112+
}
113+
90114
// Clean stale sessions from previous crashed runs — PTY processes are dead after restart
91115
db.prepare('DELETE FROM active_sessions').run()
92116
}

electron/db/schema.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,13 @@ CREATE TABLE IF NOT EXISTS tools (
261261
262262
CREATE INDEX IF NOT EXISTS idx_tools_category ON tools(category);
263263
`
264+
265+
export const SCHEMA_V9 = `
266+
ALTER TABLE subscriptions ADD COLUMN created_at INTEGER DEFAULT (unixepoch());
267+
ALTER TABLE subscriptions ADD COLUMN updated_at INTEGER DEFAULT (unixepoch());
268+
ALTER TABLE oauth_tokens ADD COLUMN updated_at INTEGER DEFAULT (unixepoch());
269+
270+
CREATE INDEX IF NOT EXISTS idx_wallets_default ON wallets(is_default);
271+
CREATE INDEX IF NOT EXISTS idx_plugins_enabled ON plugins(enabled);
272+
CREATE INDEX IF NOT EXISTS idx_tweets_status ON tweets(status);
273+
`

electron/ipc/browser.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { ipcMain } from 'electron'
2+
import fs from 'node:fs'
3+
import path from 'node:path'
4+
import os from 'node:os'
25
import {
36
navigate,
47
getPage,
@@ -8,8 +11,42 @@ import {
811
getHistory,
912
clearHistory,
1013
} from '../services/BrowserService'
14+
import { getClaudePath } from '../services/ClaudeRouter'
1115
import { ipcHandler } from '../services/IpcHandlerFactory'
1216

17+
const BROWSER_AGENT_PROMPT = `You are a Browser Agent inside DAEMON — a collaborative development assistant that can see and interact with web pages the user is viewing.
18+
19+
You receive live context from the browser:
20+
- [CONSOLE] messages show console.log, console.warn, and console.error from the page
21+
- [ERROR] messages show uncaught exceptions and runtime errors
22+
- [INSPECT] messages show elements the user Ctrl+clicked, with CSS selectors and computed styles
23+
- [NAV] messages show URL changes as the user navigates
24+
25+
Your capabilities:
26+
- Analyze page structure, layout, and styling from inspect data
27+
- Debug JavaScript errors using console output
28+
- Suggest code fixes when the user points at broken elements
29+
- Identify components from selectors and map them to source files
30+
- Explain what elements do and how they're styled
31+
32+
BROWSER CONTROL:
33+
You can navigate the browser by outputting this exact format:
34+
[NAVIGATE] https://example.com
35+
36+
The browser will automatically navigate to that URL. Use this instead of opening external browsers.
37+
Examples:
38+
- User says "go to solana.com" → output: [NAVIGATE] https://solana.com
39+
- User says "open localhost:3000" → output: [NAVIGATE] http://localhost:3000
40+
- User says "check the docs" → output: [NAVIGATE] https://docs.example.com
41+
42+
When the user inspects an element:
43+
1. Identify what component/element it is from the selector
44+
2. If it's a localhost dev server, try to map the selector to a source file
45+
3. Suggest improvements or fixes if asked
46+
4. Reference exact CSS selectors so the user can find elements
47+
48+
Be concise. Lead with the answer. The user is a developer — speak technically.`
49+
1350
export function registerBrowserHandlers() {
1451
ipcMain.handle('browser:navigate', ipcHandler(async (_event, url: string) => {
1552
return await navigate(url)
@@ -41,4 +78,13 @@ export function registerBrowserHandlers() {
4178
ipcMain.handle('browser:clear', ipcHandler(async () => {
4279
clearHistory()
4380
}))
81+
82+
ipcMain.handle('browser:agent-command', ipcHandler(async () => {
83+
const promptPath = path.join(os.tmpdir(), `daemon_browser_agent_${Date.now()}.txt`)
84+
fs.writeFileSync(promptPath, BROWSER_AGENT_PROMPT, 'utf8')
85+
86+
const claudePath = getClaudePath()
87+
const command = `${claudePath} --model claude-sonnet-4-20250514 --append-system-prompt-file "${promptPath}"`
88+
return { command, promptPath }
89+
}))
4490
}

electron/ipc/pumpfun.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { ipcMain } from 'electron'
2+
import { ipcHandler } from '../services/IpcHandlerFactory'
3+
import * as PumpFun from '../services/PumpFunService'
4+
5+
export function registerPumpFunHandlers() {
6+
ipcMain.handle('pumpfun:bonding-curve', ipcHandler(async (_event, mint: string) => {
7+
return await PumpFun.getBondingCurveState(mint)
8+
}))
9+
10+
ipcMain.handle('pumpfun:create-token', ipcHandler(async (_event, input: PumpFun.TokenCreateInput) => {
11+
return await PumpFun.createToken(input)
12+
}))
13+
14+
ipcMain.handle('pumpfun:buy', ipcHandler(async (_event, input: PumpFun.TradeInput) => {
15+
return await PumpFun.buyToken(input)
16+
}))
17+
18+
ipcMain.handle('pumpfun:sell', ipcHandler(async (_event, input: PumpFun.TradeInput) => {
19+
return await PumpFun.sellToken(input)
20+
}))
21+
22+
ipcMain.handle('pumpfun:collect-fees', ipcHandler(async (_event, walletId: string) => {
23+
return await PumpFun.collectCreatorFees(walletId)
24+
}))
25+
26+
ipcMain.handle('pumpfun:pick-image', ipcHandler(async () => {
27+
return await PumpFun.pickImage()
28+
}))
29+
30+
ipcMain.handle('pumpfun:has-keypair', ipcHandler(async (_event, walletId: string) => {
31+
return PumpFun.hasKeypair(walletId)
32+
}))
33+
34+
ipcMain.handle('pumpfun:import-keypair', ipcHandler(async (_event, walletId: string) => {
35+
return await PumpFun.importKeypair(walletId)
36+
}))
37+
}

electron/preload/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ contextBridge.exposeInMainWorld('daemon', {
159159
reorder: (orderedIds: string[]) => ipcRenderer.invoke('plugins:reorder', orderedIds),
160160
},
161161

162+
browser: {
163+
navigate: (url: string) => ipcRenderer.invoke('browser:navigate', url),
164+
content: (pageId: string) => ipcRenderer.invoke('browser:content', pageId),
165+
analyze: (pageId: string, type: string, target?: string) => ipcRenderer.invoke('browser:analyze', pageId, type, target),
166+
audit: (pageId: string) => ipcRenderer.invoke('browser:audit', pageId),
167+
history: () => ipcRenderer.invoke('browser:history'),
168+
clear: () => ipcRenderer.invoke('browser:clear'),
169+
agentCommand: () => ipcRenderer.invoke('browser:agent-command'),
170+
},
171+
162172
tweets: {
163173
generate: (prompt: string, mode: string, sourceTweet?: string) => ipcRenderer.invoke('tweets:generate', prompt, mode, sourceTweet),
164174
list: (limit?: number) => ipcRenderer.invoke('tweets:list', limit),
@@ -204,6 +214,17 @@ contextBridge.exposeInMainWorld('daemon', {
204214
openExternal: (url: string) => ipcRenderer.invoke('shell:open-external', url),
205215
},
206216

217+
pumpfun: {
218+
bondingCurve: (mint: string) => ipcRenderer.invoke('pumpfun:bonding-curve', mint),
219+
createToken: (input: object) => ipcRenderer.invoke('pumpfun:create-token', input),
220+
buy: (input: object) => ipcRenderer.invoke('pumpfun:buy', input),
221+
sell: (input: object) => ipcRenderer.invoke('pumpfun:sell', input),
222+
collectFees: (walletId: string) => ipcRenderer.invoke('pumpfun:collect-fees', walletId),
223+
pickImage: () => ipcRenderer.invoke('pumpfun:pick-image'),
224+
hasKeypair: (walletId: string) => ipcRenderer.invoke('pumpfun:has-keypair', walletId),
225+
importKeypair: (walletId: string) => ipcRenderer.invoke('pumpfun:import-keypair', walletId),
226+
},
227+
207228
tools: {
208229
list: () => ipcRenderer.invoke('tools:list'),
209230
get: (id: string) => ipcRenderer.invoke('tools:get', id),

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"build": "tsc && vite build",
1919
"typecheck": "tsc --noEmit",
2020
"typecheck:watch": "tsc --noEmit --watch --preserveWatchOutput",
21-
"package": "npm run build && electron-builder",
21+
"package": "electron-builder",
2222
"postinstall": "electron-rebuild -f --only better-sqlite3 && electron-rebuild -f --only node-pty",
2323
"rebuild": "electron-rebuild -f --only better-sqlite3 && electron-rebuild -f --only node-pty",
2424
"preview": "vite preview",

0 commit comments

Comments
 (0)