Skip to content

Commit f0c51dc

Browse files
committed
Initial commit: 1Code v0.0.10
Open source release of 1Code - Best UI for Claude Code with Local and Remote agent execution. Apache License 2.0
0 parents  commit f0c51dc

File tree

348 files changed

+82632
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

348 files changed

+82632
-0
lines changed

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Apple Developer credentials (required for macOS code signing & notarization)
2+
APPLE_ID=your-email@example.com
3+
APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx
4+
APPLE_TEAM_ID=XXXXXXXXXX
5+
APPLE_IDENTITY=Developer ID Application: Your Name (TEAM_ID)
6+
7+
# Sentry error tracking (optional - disabled if not set)
8+
# Main process uses MAIN_VITE_ prefix
9+
MAIN_VITE_SENTRY_DSN=https://xxxxx@xxx.ingest.sentry.io/xxxxx
10+
11+
# PostHog analytics (optional - disabled if not set)
12+
# Main process (MAIN_VITE_ prefix for electron-vite)
13+
MAIN_VITE_POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
14+
MAIN_VITE_POSTHOG_HOST=https://us.i.posthog.com
15+
# Renderer process (VITE_ prefix for Vite)
16+
VITE_POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
17+
VITE_POSTHOG_HOST=https://us.i.posthog.com

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Build outputs
5+
dist/
6+
release/
7+
release-*/
8+
out/
9+
10+
# IDE
11+
.idea/
12+
*.swp
13+
*.swo
14+
.vscode/
15+
16+
# System files
17+
.DS_Store
18+
Thumbs.db
19+
20+
# Logs
21+
*.log
22+
npm-debug.log*
23+
24+
# Environment
25+
.env
26+
.env.local
27+
28+
# electron-vite temp files
29+
electron.vite.config.*.mjs
30+
31+
# Claude binary (downloaded at build time)
32+
resources/bin/

CLAUDE.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What is this?
6+
7+
**21st Agents** - A local-first Electron desktop app for AI-powered code assistance. Users create chat sessions linked to local project folders, interact with Claude in Plan or Agent mode, and see real-time tool execution (bash, file edits, web search, etc.).
8+
9+
## Commands
10+
11+
```bash
12+
# Development
13+
bun run dev # Start Electron with hot reload
14+
15+
# Build
16+
bun run build # Compile app
17+
bun run package # Package for current platform (dir)
18+
bun run package:mac # Build macOS (DMG + ZIP)
19+
bun run package:win # Build Windows (NSIS + portable)
20+
bun run package:linux # Build Linux (AppImage + DEB)
21+
22+
# Database (Drizzle + SQLite)
23+
bun run db:generate # Generate migrations from schema
24+
bun run db:push # Push schema directly (dev only)
25+
```
26+
27+
## Architecture
28+
29+
```
30+
src/
31+
├── main/ # Electron main process
32+
│ ├── index.ts # App entry, window lifecycle
33+
│ ├── auth-manager.ts # OAuth flow, token refresh
34+
│ ├── auth-store.ts # Encrypted credential storage (safeStorage)
35+
│ ├── windows/main.ts # Window creation, IPC handlers
36+
│ └── lib/
37+
│ ├── db/ # Drizzle + SQLite
38+
│ │ ├── index.ts # DB init, auto-migrate on startup
39+
│ │ ├── schema/ # Drizzle table definitions
40+
│ │ └── utils.ts # ID generation
41+
│ └── trpc/routers/ # tRPC routers (projects, chats, claude)
42+
43+
├── preload/ # IPC bridge (context isolation)
44+
│ └── index.ts # Exposes desktopApi + tRPC bridge
45+
46+
└── renderer/ # React 19 UI
47+
├── App.tsx # Root with providers
48+
├── features/
49+
│ ├── agents/ # Main chat interface
50+
│ │ ├── main/ # active-chat.tsx, new-chat-form.tsx
51+
│ │ ├── ui/ # Tool renderers, preview, diff view
52+
│ │ ├── commands/ # Slash commands (/plan, /agent, /clear)
53+
│ │ ├── atoms/ # Jotai atoms for agent state
54+
│ │ └── stores/ # Zustand store for sub-chats
55+
│ ├── sidebar/ # Chat list, archive, navigation
56+
│ ├── sub-chats/ # Tab/sidebar sub-chat management
57+
│ └── layout/ # Main layout with resizable panels
58+
├── components/ui/ # Radix UI wrappers (button, dialog, etc.)
59+
└── lib/
60+
├── atoms/ # Global Jotai atoms
61+
├── stores/ # Global Zustand stores
62+
├── trpc.ts # Real tRPC client
63+
└── mock-api.ts # DEPRECATED - being replaced with real tRPC
64+
```
65+
66+
## Database (Drizzle ORM)
67+
68+
**Location:** `{userData}/data/agents.db` (SQLite)
69+
70+
**Schema:** `src/main/lib/db/schema/index.ts`
71+
72+
```typescript
73+
// Three main tables:
74+
projectsid, name, path (local folder), timestamps
75+
chatsid, name, projectId, worktree fields, timestamps
76+
sub_chatsid, name, chatId, sessionId, mode, messages (JSON)
77+
```
78+
79+
**Auto-migration:** On app start, `initDatabase()` runs migrations from `drizzle/` folder (dev) or `resources/migrations` (packaged).
80+
81+
**Queries:**
82+
```typescript
83+
import { getDatabase, projects, chats } from "../lib/db"
84+
import { eq } from "drizzle-orm"
85+
86+
const db = getDatabase()
87+
const allProjects = db.select().from(projects).all()
88+
const projectChats = db.select().from(chats).where(eq(chats.projectId, id)).all()
89+
```
90+
91+
## Key Patterns
92+
93+
### IPC Communication
94+
- Uses **tRPC** with `trpc-electron` for type-safe main↔renderer communication
95+
- All backend calls go through tRPC routers, not raw IPC
96+
- Preload exposes `window.desktopApi` for native features (window controls, clipboard, notifications)
97+
98+
### State Management
99+
- **Jotai**: UI state (selected chat, sidebar open, preview settings)
100+
- **Zustand**: Sub-chat tabs and pinned state (persisted to localStorage)
101+
- **React Query**: Server state via tRPC (auto-caching, refetch)
102+
103+
### Claude Integration
104+
- Dynamic import of `@anthropic-ai/claude-code` SDK
105+
- Two modes: "plan" (read-only) and "agent" (full permissions)
106+
- Session resume via `sessionId` stored in SubChat
107+
- Message streaming via tRPC subscription (`claude.onMessage`)
108+
109+
## Tech Stack
110+
111+
| Layer | Tech |
112+
|-------|------|
113+
| Desktop | Electron 33.4.5, electron-vite, electron-builder |
114+
| UI | React 19, TypeScript 5.4.5, Tailwind CSS |
115+
| Components | Radix UI, Lucide icons, Motion, Sonner |
116+
| State | Jotai, Zustand, React Query |
117+
| Backend | tRPC, Drizzle ORM, better-sqlite3 |
118+
| AI | @anthropic-ai/claude-code |
119+
| Package Manager | bun |
120+
121+
## File Naming
122+
123+
- Components: PascalCase (`ActiveChat.tsx`, `AgentsSidebar.tsx`)
124+
- Utilities/hooks: camelCase (`useFileUpload.ts`, `formatters.ts`)
125+
- Stores: kebab-case (`sub-chat-store.ts`, `agent-chat-store.ts`)
126+
- Atoms: camelCase with `Atom` suffix (`selectedAgentChatIdAtom`)
127+
128+
## Important Files
129+
130+
- `electron.vite.config.ts` - Build config (main/preload/renderer entries)
131+
- `src/main/lib/db/schema/index.ts` - Drizzle schema (source of truth)
132+
- `src/main/lib/db/index.ts` - DB initialization + auto-migrate
133+
- `src/renderer/features/agents/atoms/index.ts` - Agent UI state atoms
134+
- `src/renderer/features/agents/main/active-chat.tsx` - Main chat component
135+
- `src/main/lib/trpc/routers/claude.ts` - Claude SDK integration
136+
137+
## Debugging First Install Issues
138+
139+
When testing auth flows or behavior for new users, you need to simulate a fresh install:
140+
141+
```bash
142+
# 1. Clear all app data (auth, database, settings)
143+
rm -rf ~/Library/Application\ Support/Agents\ Dev/
144+
145+
# 2. Reset macOS protocol handler registration (if testing deep links)
146+
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user
147+
148+
# 3. Clear app preferences
149+
defaults delete dev.21st.agents.dev # Dev mode
150+
defaults delete dev.21st.agents # Production
151+
152+
# 4. Run in dev mode with clean state
153+
cd apps/desktop
154+
bun run dev
155+
```
156+
157+
**Common First-Install Bugs:**
158+
- **OAuth deep link not working**: macOS Launch Services may not immediately recognize protocol handlers on first app launch. User may need to click "Sign in" again after the first attempt.
159+
- **Folder dialog not appearing**: Window focus timing issues on first launch. Fixed by ensuring window focus before showing `dialog.showOpenDialog()`.
160+
161+
**Dev vs Production App:**
162+
- Dev mode uses `twentyfirst-agents-dev://` protocol
163+
- Dev mode uses separate userData path (`~/Library/Application Support/Agents Dev/`)
164+
- This prevents conflicts between dev and production installs
165+
166+
## Releasing a New Version
167+
168+
### Prerequisites for Notarization
169+
170+
Set environment variables (add to `.zshrc` or `.env.local`):
171+
172+
```bash
173+
export APPLE_ID="your-apple-id@example.com"
174+
export APPLE_APP_SPECIFIC_PASSWORD="xxxx-xxxx-xxxx-xxxx" # App-specific password from appleid.apple.com
175+
```
176+
177+
### Release Commands
178+
179+
```bash
180+
# Full release (build, sign, notarize, generate manifests, upload to CDN)
181+
bun run release
182+
183+
# Or step by step:
184+
bun run build # Compile TypeScript
185+
bun run package:mac # Build, sign & notarize macOS app
186+
bun run dist:manifest # Generate latest-mac.yml manifests
187+
./scripts/upload-release-wrangler.sh # Upload to R2 CDN
188+
```
189+
190+
### Bump Version Before Release
191+
192+
```bash
193+
npm version patch # 0.0.2 → 0.0.3
194+
npm version minor # 0.0.3 → 0.1.0
195+
npm version major # 0.1.0 → 1.0.0
196+
```
197+
198+
### Files Uploaded to CDN
199+
200+
| File | Purpose |
201+
|------|---------|
202+
| `latest-mac.yml` | Manifest for arm64 auto-updates |
203+
| `latest-mac-x64.yml` | Manifest for Intel auto-updates |
204+
| `Agents-{version}-arm64-mac.zip` | Auto-update payload (arm64) |
205+
| `Agents-{version}-mac.zip` | Auto-update payload (Intel) |
206+
| `Agents-{version}-arm64.dmg` | Manual download (arm64) |
207+
| `Agents-{version}.dmg` | Manual download (Intel) |
208+
209+
### Auto-Update Flow
210+
211+
1. App checks `https://cdn.21st.dev/releases/desktop/latest-mac.yml` on startup and when window regains focus (with 1 min cooldown)
212+
2. If version in manifest > current version, shows "Update Available" banner
213+
3. User clicks Download → downloads ZIP in background
214+
4. User clicks "Restart Now" → installs update and restarts
215+
216+
## Current Status (WIP)
217+
218+
**Done:**
219+
- Drizzle ORM setup with schema (projects, chats, sub_chats)
220+
- Auto-migration on app startup
221+
- tRPC routers structure
222+
223+
**In Progress:**
224+
- Replacing `mock-api.ts` with real tRPC calls in renderer
225+
- ProjectSelector component (local folder picker)
226+
227+
**Planned:**
228+
- Git worktree per chat (isolation)
229+
- Claude Code execution in worktree path
230+
- Full feature parity with web app

0 commit comments

Comments
 (0)