https://github.com/jamesmurdza/upstream-agents
Run AI coding agents in isolated sandboxes connected to your GitHub repositories
https://github.com/jamesmurdza/upstream-agents
ai-agents claude-code codex opencode
Last synced: 2 months ago
JSON representation
Run AI coding agents in isolated sandboxes connected to your GitHub repositories
- Host: GitHub
- URL: https://github.com/jamesmurdza/upstream-agents
- Owner: jamesmurdza
- License: apache-2.0
- Created: 2026-03-02T08:51:12.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-03T05:53:51.000Z (2 months ago)
- Last Synced: 2026-04-03T13:32:27.754Z (2 months ago)
- Topics: ai-agents, claude-code, codex, opencode
- Language: TypeScript
- Homepage: https://upstreamagents.com/
- Size: 4.68 MB
- Stars: 7
- Watchers: 0
- Forks: 2
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Upstream Agents
A sophisticated multi-tenant web application that enables users to run AI coding agents (Claude Code, OpenCode, Codex) in isolated Daytona sandboxes. Features a Slack-like interface for managing AI-powered coding agents across multiple GitHub repositories with real-time streaming output, background execution, and persistent chat history.

## Features
### Core Capabilities
- **Multi-Agent Support** - Run Claude Code, OpenCode, or Codex agents with configurable models
- **GitHub OAuth Login** - Sign in with GitHub, OAuth tokens used for seamless repo access
- **Isolated Sandboxes** - Each branch gets its own Daytona sandbox environment
- **Real-time Streaming** - Live agent output via Server-Sent Events (SSE)
- **Background Execution** - Agent tasks continue even when browser is closed
- **Persistent Chat History** - Full conversation history with tool calls and content blocks
### User Experience
- **Slack-like Interface** - Repository sidebar with branch-based conversations
- **Multi-tenant Architecture** - User data fully isolated, shared infrastructure
- **Quota Enforcement** - Configurable concurrent sandbox limits
- **Encrypted Credentials** - API keys stored AES-encrypted in database
- **Drag-and-Drop Reordering** - Customize repository order in sidebar
- **Dark Mode Support** - Theme switching with next-themes
- **Mobile Responsive** - Full mobile UI with drawer navigation
### Developer Features
- **Pull Request Integration** - Create PRs directly from branches
- **Git Diff Viewer** - Compare branches and view changes
- **Git History** - Browse commit history per branch
- **Advanced Git Operations** - Merge, rebase, reset, tag, rename, and delete remote branches
- **MCP Server Registry** - Browse and connect 3,000+ MCP servers via [Smithery](https://smithery.ai)
- **Environment Variables** - Per-repository encrypted env vars for sandboxes
- **Auto-Stop** - Configurable sandbox auto-stop intervals (5-20 minutes)
- **Safe Push Handling** - Branch checks plus retry and graceful "already up-to-date" handling
---
## Architecture
```
┌─────────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ Browser (React) │────▶│ Next.js 16 API │────▶│ Neon Postgres │
│ - Shadcn/ui │◀────│ (Vercel/Node) │◀────│ (Serverless) │
│ - SSE Streaming │ │ - 34 API routes │ │ - Prisma ORM │
└─────────────────────┘ └──────────┬──────────┘ └──────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Daytona Cloud │ │ GitHub API │ │ LLM APIs │
│ (Sandboxes) │ │ (OAuth) │ │ - Anthropic │
│ - SDK control │ │ - Repos/PRs │ │ - OpenAI │
└────────┬────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐
│ Coding Agents │────────▶│ Smithery │
│ - Claude Code │ │ (MCP Registry │
│ - OpenCode │◀────────│ + Connect) │
│ - Codex │ └─────────────────┘
└─────────────────┘
```
---
## Tech Stack
### Frontend
- **Framework**: Next.js 16.1.6 (App Router, React 19)
- **UI Library**: Shadcn/ui (50+ Radix UI components)
- **Styling**: Tailwind CSS 4.2
- **Forms**: React Hook Form + Zod validation
- **Icons**: Lucide React (564 icons)
- **Charts**: Recharts
- **Notifications**: Sonner toast notifications
- **Markdown**: react-markdown for agent output
### Backend
- **Server**: Next.js API Routes (serverless)
- **ORM**: Prisma 7.4.2 with Neon adapter
- **Database**: PostgreSQL (Neon serverless)
- **Authentication**: NextAuth.js 4.24 (GitHub OAuth)
- **Encryption**: crypto-js (AES encryption)
### External Services
- **Sandboxes**: Daytona SDK (@daytonaio/sdk)
- **Agent Runner**: background-agents
- **LLM Providers**: Anthropic SDK, OpenAI SDK
- **MCP Registry**: [Smithery](https://smithery.ai) (server discovery + managed connections)
---
## Setup
### Prerequisites
- Node.js 18+
- A Vercel account (for deployment + Neon integration)
- A GitHub account (for OAuth app)
- A Daytona API key
### 1. Neon Database
**Option A: Via Vercel (Recommended)**
1. Go to your Vercel project → **Storage** tab
2. Click **Create Database** → Select **Neon Postgres**
3. Vercel auto-adds `DATABASE_URL` and `DATABASE_URL_UNPOOLED` env vars
**Option B: Direct Setup**
1. Go to [neon.tech](https://neon.tech) → Create project
2. Copy the connection strings
3. Add to Vercel env vars:
```
DATABASE_URL=postgres://...?sslmode=require
DATABASE_URL_UNPOOLED=postgres://...?sslmode=require
```
### 2. GitHub OAuth App
1. Go to GitHub → **Settings** → **Developer settings** → **OAuth Apps** → **New OAuth App**
2. Fill in:
- **Application name**: `Upstream Agents`
- **Homepage URL**: `https://your-app.vercel.app`
- **Authorization callback URL**: `https://your-app.vercel.app/api/auth/callback/github`
3. Click **Register application**
4. Copy the **Client ID**
5. Generate a **Client Secret** and copy it
### 3. Generate Secrets
```bash
# NextAuth secret (32-byte base64)
openssl rand -base64 32
# Encryption key for API credentials (32-byte hex)
openssl rand -hex 32
```
### 4. Environment Variables
Add these to Vercel (Settings → Environment Variables):
| Variable | Description | Example |
|----------|-------------|---------|
| `DATABASE_URL` | Neon pooled connection | (auto-set by Vercel) |
| `DATABASE_URL_UNPOOLED` | Neon direct connection (migrations) | (auto-set by Vercel) |
| `NEXTAUTH_URL` | Your app's URL | `https://your-app.vercel.app` |
| `NEXTAUTH_SECRET` | Random secret for NextAuth | (output of `openssl rand -base64 32`) |
| `GITHUB_CLIENT_ID` | From GitHub OAuth App | `Ov23li...` |
| `GITHUB_CLIENT_SECRET` | From GitHub OAuth App | `abc123...` |
| `ENCRYPTION_KEY` | For encrypting API keys | (output of `openssl rand -hex 32`) |
| `DAYTONA_API_KEY` | Your shared Daytona API key | `dtn_...` |
| `DAYTONA_API_URL` | Daytona API endpoint | `https://api.daytona.io` |
| `SMITHERY_API_KEY` | Smithery API key for MCP registry | (from [smithery.ai/account/api-keys](https://smithery.ai/account/api-keys)) |
### 5. Deploy
```bash
# Install dependencies
npm install
# Generate Prisma client
npx prisma generate
# Run migrations (uses DATABASE_URL_UNPOOLED)
npx prisma migrate deploy
# Build
npm run build
```
Or push to Vercel - the build script handles migrations automatically.
---
## Development
This is a monorepo with two packages:
```
packages/
├── agents/ # @sandboxed-agents/sdk - TypeScript SDK for AI coding agents
└── web/ # @sandboxed-agents/web - Next.js web application
```
For full local development setup (database, environment variables, running the dev server), see [DEVELOPMENT.md](./DEVELOPMENT.md).
### Available Scripts (Root)
| Script | Description |
|--------|-------------|
| `npm run dev` | Start web development server |
| `npm run build` | Build SDK + web app |
| `npm run build:sdk` | Build only the SDK package |
| `npm run build:web` | Build only the web app |
| `npm run start` | Start production server |
| `npm run lint` | ESLint check across all packages |
| `npm run clean` | Clean build artifacts |
For SDK development, see [`packages/agents/README.md`](packages/agents/README.md).
### Testing
For unit tests and Playwright end-to-end tests, see [TESTING.md](./TESTING.md).
---
## Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Make your changes
4. Run linting: `npm run lint`
5. Commit your changes: `git commit -m "Add my feature"`
6. Push to the branch: `git push origin feature/my-feature`
7. Open a Pull Request
---
## License
MIT