npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@magnet-ai/magnet-agent-server

v0.1.17

Published

A WebSocket server companion to Magnet AI (https://www.magnet.run) that proxies requests to Claude Code API

Readme

Magnet Agent Server

A WebSocket server that proxies requests to the Claude Code API, enabling real-time communication with Claude's code assistance capabilities.

Features

  • 🔌 WebSocket-based communication with Claude Code API
  • 🚀 Built with Bun for high performance
  • ⚡ Real-time streaming of Claude responses
  • 🌳 Git worktree isolation for safe code changes
  • 💾 Saved Sessions - persistent session storage and retrieval
  • 🛑 Session management with abort capabilities
  • 📊 Git diff functionality for worktree changes
  • 🌿 Automatic branch creation from worktree changes
  • 🔍 Issue-based session tracking
  • 📈 Session continuation support
  • 🏥 Health check endpoint
  • 📦 Easy CLI installation and usage

Requirements

  • Bun >= 1.0.0
  • Anthropic API key
  • TypeScript >= 5.0

Installation

Global Installation

bun install -g @magnet-ai/magnet-agent-server

Development Installation

git clone <repository-url>
cd magnet-agent-server
bun install

Usage

Starting the Server

# Using global installation
magnet-agent-server

# With custom port
magnet-agent-server --port 8080
magnet-agent-server -p 3000

# Show help
magnet-agent-server --help

# Show version
magnet-agent-server --version

# Using npm scripts
bun run dev          # Development mode
bun run start        # Production mode

# Custom port via environment variable
MAGNET_SERVER_PORT=8080 bun run dev

The server will start on http://localhost:3002 by default.

CLI Options

  • -p, --port <number> - Port to run the server on (default: 3002)
  • -h, --help - Show help message
  • -v, --version - Show version number

Environment Variables

  • MAGNET_SERVER_PORT - Server port (default: 3002, overridden by CLI --port option)
  • ANTHROPIC_API_KEY - Can be set globally or passed per request

Git Worktree Isolation

By default, magnet-agent-server creates an isolated git worktree for each Claude Code session. This provides several benefits:

Benefits

  • 🛡️ Safety: Changes are made in an isolated copy, protecting your main working directory
  • 🔬 Experimentation: Try different approaches without affecting your current work
  • 📋 Review: Examine all changes before deciding to integrate them
  • 🚫 No Conflicts: Avoid merge conflicts with your ongoing work
  • 🌿 Branch Creation: Automatically create branches from completed changes

How It Works

  1. When a Claude Code session starts, the server checks if your projectRoot is a git repository
  2. If yes, it creates a new worktree in the system temp directory with pattern magnet-{issueId}--{timestamp}
  3. The worktree contains all your current code and uses the same branch as a detached HEAD
  4. Claude Code operates in this isolated environment
  5. When the session ends, you can optionally create a branch from the changes
  6. The worktree is automatically cleaned up after session completion

Configuration

Enable/Disable Options:

  • Default: Enabled for all git repositories
  • Per-Session: Include "useWorktree": false in WebSocket prompt message

Example Worktree Structure

System Temp Directory:
├── magnet-abc123--1703123456789/  # Session 1 worktree
│   ├── src/                       # Copy of your code
│   └── package.json               # Changes made here
└── magnet-def456--1703123567890/  # Session 2 worktree (if overlapping)

Session Management

Issue-Based Tracking

Each Claude Code session is tracked using an issueId parameter, which provides:

  • 🔍 Unique Identification: Each session has a distinct identifier
  • 📊 Better Tracking: Monitor multiple concurrent sessions
  • 🔄 Session Continuation: Continue previous sessions with the same issueId
  • 🌿 Branch Management: Create branches tied to specific issues

Session Continuation

The server supports continuing previous Claude Code sessions within the same WebSocket connection:

  • First Prompt: Creates a new session with the given issueId
  • Subsequent Prompts: Continues the existing session, maintaining context and history
  • Max Turns: Configurable limit to prevent infinite loops (default: 50)
  • Connection-Based: Sessions only persist within the same WebSocket connection
  • Memory-Based: Sessions are lost when the connection closes or server restarts

Saved Sessions

The server now supports persistent session storage, allowing you to retrieve session history even after the connection is closed or the server restarts.

How It Works

  1. Automatic Logging: All Claude Code messages are automatically saved to disk during the session
  2. File Storage: Sessions are stored as JSON files in a sessions/ directory
  3. Persistent: Sessions persist across server restarts and connection drops
  4. Metadata: Each session includes metadata like issueId, branchName, creation time, and status

Session Lifecycle

  • Created: When a new session starts, a session file is created with metadata
  • Active: Messages are logged in real-time as they stream through the WebSocket
  • Completed: Session is marked as completed when the Claude Code session ends normally
  • Aborted: Session is marked as aborted when manually terminated or on error

Storage Format

Sessions are stored in sessions/{issueId}.json with the following structure:

{
  "metadata": {
    "issueId": "issue-123",
    "branchName": "feature/fix-bug",
    "createdAt": "2024-01-01T00:00:00Z",
    "lastUpdatedAt": "2024-01-01T00:30:00Z",
    "status": "completed"
  },
  "messages": [
    {
      "timestamp": "2024-01-01T00:00:00Z",
      "type": "claude_message",
      "data": { /* Full Claude Code message */ }
    }
  ]
}

Benefits

  • 📚 Session History: Review past interactions with Claude Code
  • 🔄 Resume Context: Understand what was discussed in previous sessions
  • 🐛 Debugging: Trace issues across multiple sessions
  • 📊 Analytics: Track usage patterns and session outcomes
  • 🔗 Integration: Build workflows that depend on session history

Git Diff Functionality

When using git worktree isolation, you can request diffs to see what changes Claude has made to your code. This is useful for:

  • 🔍 Reviewing Changes: See exactly what Claude modified before integrating changes
  • 📋 Code Review: Get a clear diff view of all modifications
  • 🧪 Testing: Understand the scope of changes before applying them
  • 📊 Progress Tracking: Monitor changes as Claude works on your project

How to Request Diffs

Send a get_diff message to the WebSocket connection:

{
  "type": "get_diff",
  "issueId": "your-issue-id",
  "includeUntracked": true
}

Parameters:

  • issueId (required): The issue ID of the active session
  • includeUntracked (optional, default: true): Whether to include untracked files in the response

Diff Response Format

{
  "type": "diff",
  "diff": "git diff output...",
  "stats": {
    "filesChanged": 3,
    "insertions": 45,
    "deletions": 12
  },
  "hasChanges": true,
  "untrackedFiles": ["new-file.js", "temp.txt"],
  "worktreePath": "/tmp/magnet-abc123--1703123456789",
  "originalBranch": "main",
  "issueId": "abc123"
}

Response Fields:

  • diff: The complete git diff output showing all changes
  • stats: Summary statistics of the changes
  • hasChanges: Boolean indicating if any changes were detected
  • untrackedFiles: Array of newly created files not yet tracked by git
  • worktreePath: Path to the isolated worktree directory
  • originalBranch: The original branch the worktree was created from
  • issueId: The issue ID for the session

Branch Creation

When a session completes with changes, the server can automatically create a branch:

  • Automatic Detection: Checks for changes in the worktree
  • Smart Naming: Creates branches with pattern magnet-{issueId}--{timestamp}
  • Commit Creation: Creates a commit with all changes in the worktree
  • Branch Creation: Creates the branch in the original repository
  • Optional: Only creates branches if there are actual changes

API Reference

WebSocket Endpoint

Connect to: ws://localhost:3002/claude-code

Message Formats

Sending a Prompt

{
  "type": "prompt",
  "content": "Your prompt here",
  "projectRoot": "/path/to/your/project",
  "anthropicApiKey": "your-api-key-here",
  "issueId": "unique-issue-identifier",
  "useWorktree": true,
  "maxTurns": 50,
  "promptToAppend": "Additional system prompt"
}

Parameters:

  • content (required): Your prompt/question for Claude
  • projectRoot (required): Path to your project directory
  • anthropicApiKey (required): Your Anthropic API key
  • issueId (required): Unique identifier for this session/issue
  • useWorktree (optional): Override server default for worktree usage
  • maxTurns (optional): Maximum number of turns for this session (default: 50)
  • promptToAppend (optional): Additional system prompt to append (first turn only)

Aborting a Session

{
  "type": "abort",
  "issueId": "your-issue-id"
}

Requesting a Diff

{
  "type": "get_diff",
  "issueId": "your-issue-id",
  "includeUntracked": true
}

Parameters:

  • issueId (required): The issue ID of the active session
  • includeUntracked (optional): Include untracked files in response (default: true)

Response Types

Connection Established

{
  "type": "connected",
  "message": "Connected to Claude Code server. Send your prompt to begin.",
  "issueId": "system"
}

Status Updates

{
  "type": "status",
  "message": "Processing your request...",
  "issueId": "abc123"
}

Worktree Created

{
  "type": "status",
  "message": "Created isolated git worktree: /tmp/magnet-abc123--1703123456789",
  "issueId": "abc123",
  "worktreePath": "/tmp/magnet-abc123--1703123456789",
  "originalProjectRoot": "/path/to/project"
}

Worktree Warning/Info

{
  "type": "warning",
  "message": "Failed to create git worktree, using original project root: error details",
  "issueId": "abc123"
}
{
  "type": "info",
  "message": "Git worktree isolation not available (not a git repository)",
  "issueId": "abc123"
}

Claude Messages

{
  "type": "claude_message",
  "data": {
    "type": "assistant",
    "message": {
      "id": "msg_123",
      "content": [{"type": "text", "text": "Claude's response"}],
      "model": "claude-3-5-sonnet-20241022",
      "role": "assistant",
      "stop_reason": "end_turn",
      "usage": {
        "input_tokens": 100,
        "output_tokens": 200
      }
    },
    "session_id": "session-123"
  },
  "issueId": "abc123"
}

Session Complete

{
  "type": "complete",
  "message": "Claude Code session completed",
  "issueId": "abc123",
  "worktreePath": "/tmp/magnet-abc123--1703123456789"
}

Session Aborted

{
  "type": "aborted",
  "message": "Claude Code session aborted successfully",
  "issueId": "abc123"
}

Abort Failed

{
  "type": "abort_failed",
  "message": "Failed to abort session: no active session found",
  "issueId": "abc123"
}

Diff Response

{
  "type": "diff",
  "diff": "git diff output showing changes...",
  "stats": {
    "filesChanged": 3,
    "insertions": 45,
    "deletions": 12
  },
  "hasChanges": true,
  "untrackedFiles": ["new-file.js"],
  "worktreePath": "/tmp/magnet-abc123--1703123456789",
  "originalBranch": "main",
  "issueId": "abc123"
}

Errors

{
  "type": "error",
  "message": "Error description",
  "issueId": "abc123"
}

HTTP Endpoints

Health Check

GET /health

Response:

{
  "status": "healthy",
  "timestamp": "2024-01-01T00:00:00.000Z"
}

Version

GET /version

Returns the server version and package name.

Response:

{
  "version": "0.1.15",
  "name": "@magnet-ai/magnet-agent-server"
}

Root

GET /

Returns basic server information.

Get Saved Session

GET /session?issueId=<issueId>

Retrieves a saved session by issueId.

Parameters:

  • issueId (required): The unique identifier of the session to retrieve

Response:

{
  "metadata": {
    "issueId": "abc123",
    "branchName": "feature-branch",
    "createdAt": "2024-01-01T00:00:00.000Z",
    "lastUpdatedAt": "2024-01-01T00:30:00.000Z",
    "status": "completed"
  },
  "messages": [
    {
      "timestamp": "2024-01-01T00:00:00.000Z",
      "type": "claude_message",
      "data": {
        "type": "assistant",
        "message": {
          "content": [{"type": "text", "text": "Response from Claude"}],
          "role": "assistant"
        },
        "session_id": "session-123"
      }
    }
  ],
  "isCurrentlyActive": false
}

Status Codes:

  • 200 - Session found and returned
  • 404 - Session not found for the given issueId
  • 400 - Missing or invalid issueId parameter
  • 500 - Server error or session logger not initialized

Client Example

JavaScript/TypeScript Client

const ws = new WebSocket('ws://localhost:3002/claude-code');

ws.onopen = () => {
  console.log('Connected to Magnet Agent Server');

  // Send a prompt
  ws.send(JSON.stringify({
    type: 'prompt',
    content: 'Help me write a function to calculate fibonacci numbers',
    projectRoot: '/path/to/my/project',
    anthropicApiKey: 'your-api-key',
    issueId: 'fibonacci-task-001',
    useWorktree: true,
    maxTurns: 25,
    promptToAppend: 'Please focus on performance and readability'
  }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case 'connected':
      console.log('Server ready');
      break;
    case 'claude_message':
      console.log(`[${message.issueId}] Claude response:`, message.data);
      break;
    case 'complete':
      console.log(`[${message.issueId}] Session completed`);
      if (message.worktreePath) {
        console.log(`Worktree: ${message.worktreePath}`);
      }
      break;
    case 'error':
      console.error(`[${message.issueId}] Error:`, message.message);
      break;
    case 'diff':
      console.log(`[${message.issueId}] Diff:`, message.diff);
      console.log(`Files changed: ${message.stats.filesChanged}`);
      break;
  }
};

// Request diff of current changes
const getDiff = (issueId: string) => {
  ws.send(JSON.stringify({
    type: 'get_diff',
    issueId: issueId,
    includeUntracked: true
  }));
};

// Abort current session
const abortSession = (issueId: string) => {
  ws.send(JSON.stringify({
    type: 'abort',
    issueId: issueId
  }));
};

// Continue a previous session (within the same WebSocket connection)
const continueSession = (issueId: string, newPrompt: string) => {
  ws.send(JSON.stringify({
    type: 'prompt',
    content: newPrompt,
    projectRoot: '/path/to/my/project',
    anthropicApiKey: 'your-api-key',
    issueId: issueId, // Same issueId continues the session
    useWorktree: true
  }));
};

Test Client

The project includes a test client:

bun run test-client
bun run test-diff              # Test diff functionality
bun run test-worktree          # Test worktree functionality
bun run test-worktree-enabled  # Test with worktree enabled
bun run test-worktree-disabled # Test with worktree disabled

Example Usage

The project includes an interactive diff example:

# Start the server
bun run dev

# In another terminal, run the diff example
ANTHROPIC_API_KEY=your_key bun examples/diff-example.ts /path/to/your/project

This example demonstrates:

  • Starting a Claude Code session with worktree
  • Making changes through Claude
  • Requesting periodic diffs to see progress
  • Displaying diff results in a readable format
  • Creating branches from completed changes

Session Management

  • Multiple Claude Code sessions can be active simultaneously (one per issueId per connection)
  • Sessions are automatically cleaned up when connections close
  • Use the abort message type to cancel active sessions
  • Each session gets a unique issueId for tracking and continuation
  • Sessions can be continued by using the same issueId in subsequent prompts within the same WebSocket connection
  • Sessions do not persist across WebSocket reconnections or server restarts
  • Worktrees are isolated per session and automatically cleaned up

Development

Running Tests

bun test

Health Check

bun run health
# or
curl http://localhost:3002/health

Project Structure

magnet-agent-server/
├── bin/                    # CLI executable
├── lib/                    # Library modules
│   ├── git-worktree.ts    # Git worktree utilities
│   ├── ClaudeCodeSession.ts # Claude Code session management
│   └── types.ts           # Type definitions and schemas
├── index.ts               # Main server file
├── test-client.ts         # Test client
├── test-worktree.ts       # Worktree test client
├── package.json
└── README.md

Error Handling

The server handles various error scenarios:

  • Invalid JSON: Malformed message handling
  • Missing required fields: Validation for prompt, API key, project root, and issueId
  • Session conflicts: Manages multiple concurrent sessions per issueId per connection
  • API errors: Forwards Claude Code API errors to clients
  • Connection drops: Automatic cleanup of resources and worktrees
  • Worktree failures: Graceful fallback to original project root
  • Branch creation errors: Non-blocking failures with proper logging

Security Considerations

  • API keys are passed per request and not stored
  • Sessions are isolated per issueId within each WebSocket connection
  • Git worktrees provide additional isolation for code changes in system temp directory
  • Automatic cleanup prevents resource leaks (including worktrees)
  • Input validation for all incoming messages using Zod schemas
  • Worktrees are created with restricted permissions
  • Session continuation only works within the same WebSocket connection

Performance Considerations

  • Worktree Cleanup: Automatic cleanup of old worktrees older than 24 hours
  • Session Limits: Configurable maxTurns to prevent infinite loops
  • Memory Management: Proper cleanup of AbortControllers and sessions
  • Concurrent Sessions: Support for multiple simultaneous sessions
  • Resource Isolation: Each session operates in its own worktree

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

MIT

Support

For issues and questions, please open an issue in the repository.