Package Exports
- @sudocode-ai/environment-harness
- @sudocode-ai/environment-harness/package.json
Readme
@sudocode-ai/environment-harness
TypeScript/Node.js library for creating and managing GitHub Codespaces as sandboxed development environments.
Installation
npm install @sudocode-ai/environment-harnessPrerequisites
- Node.js: Version 18.0.0 or higher (tested with Node 18-25)
- GitHub CLI: Install from cli.github.com
- GitHub Token: Personal access token or OAuth token with codespace permissions
- Required scopes:
codespace,repo
- Required scopes:
Quick Start
Creating a Sandbox
Create a new GitHub Codespace with sudocode and Claude Code installed:
import { create_sandbox } from '@sudocode-ai/environment-harness';
const result = await create_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
repository: 'owner/repo',
ref: 'main', // Optional: branch, tag, or commit
claudeOAuthToken: process.env.CLAUDE_OAUTH_TOKEN, // Optional
});
console.log('Sandbox created:', result.codespace.name);
console.log('Web URL:', result.codespace.webUrl);
console.log('GitHub token:', result.githubToken);
console.log('Sudocode server port:', result.sudocodeServer.port);
console.log('Tools installed:', result.toolsInstalled);Resuming an Existing Sandbox
Resume a previously created sandbox (handles auto-stopped codespaces):
import { resume_sandbox } from '@sudocode-ai/environment-harness';
const result = await resume_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
codespaceName: 'symmetrical-space-telegram-abc123',
serverPort: 3000, // Optional: sudocode server port
});
console.log('Reconnected to:', result.codespace.name);
console.log('Server running on port:', result.sudocodeServer.port);
console.log('GitHub token:', result.githubToken);Deleting a Sandbox
Delete a sandbox and clean up all resources:
import { delete_sandbox } from '@sudocode-ai/environment-harness';
const result = await delete_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
codespaceName: 'symmetrical-space-telegram-abc123',
});
console.log('Sandbox deleted:', result.codespaceName);
console.log('Success:', result.success);API Reference
create_sandbox(params)
Creates a new GitHub Codespace with required tools installed.
Parameters:
githubToken(string, required): GitHub token with codespace permissionsrepository(string, required): Repository in format "owner/repo"ref(string, optional): Git ref (branch/tag/commit), defaults to repository default branchdevcontainerPath(string, optional): Path to .devcontainer subdirectoryidleTimeoutMinutes(number, optional): Minutes of inactivity before auto-shutdownretentionPeriodMinutes(number, optional): Minutes to retain codespace after shutdownclaudeOAuthToken(string, optional): Claude OAuth token for Claude Code
Returns: Promise<SandboxResult>
codespace: Codespace details (name, id, state, webUrl)githubToken: GitHub token from codespace environment (ghu_* format)sudocodeServer: Server details (port)toolsInstalled: List of installed tools
Throws:
GitHubAPIError: If API call fails (invalid token, permissions, repository not found)Error: If codespace creation times out or provisioning fails
resume_sandbox(params)
Resumes an existing sandbox, handling state transitions and restarting services.
Parameters:
githubToken(string, required): GitHub token with codespace permissionscodespaceName(string, required): Unique codespace identifierserverPort(number, optional): Port for sudocode server (default: 3000)
Returns: Promise<SandboxResult>
Throws:
GitHubAPIError: If API call fails (invalid token, permissions)Error: If codespace not found, SSH connection fails, or token extraction fails
delete_sandbox(params)
Deletes a sandbox (idempotent operation).
Parameters:
githubToken(string, required): GitHub token with codespace permissionscodespaceName(string, required): Unique codespace identifier
Returns: Promise<DeleteSandboxResult>
success: Whether deletion was successfulcodespaceName: Name of the deleted codespace
Throws:
GitHubAPIError: If API call fails (invalid token, permissions)
Authentication Setup
GitHub Token
You can create a GitHub personal access token at github.com/settings/tokens.
Required scopes:
codespace- Create and manage codespacesrepo- Access repositories
Set the token as an environment variable:
export GITHUB_TOKEN=ghp_your_token_hereClaude OAuth Token (Optional)
If you want Claude Code installed in your sandboxes, provide a Claude OAuth token:
export CLAUDE_OAUTH_TOKEN=your_oauth_tokenError Handling
The library throws typed errors that you can catch and handle:
import { create_sandbox } from '@sudocode-ai/environment-harness';
try {
const result = await create_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
repository: 'owner/repo',
});
console.log('Success:', result.codespace.name);
} catch (error) {
if (error.name === 'GitHubAPIError') {
console.error('GitHub API error:', error.message);
// Handle API-specific errors (auth, permissions, rate limits)
} else {
console.error('Unexpected error:', error);
// Handle other errors (timeouts, network issues)
}
}Advanced Usage
Custom Timeout Configuration
const result = await create_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
repository: 'owner/repo',
idleTimeoutMinutes: 30, // Auto-stop after 30 minutes of inactivity
retentionPeriodMinutes: 60, // Delete 60 minutes after stopping
});Custom Devcontainer Path
const result = await create_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
repository: 'owner/repo',
devcontainerPath: '.devcontainer/custom-config',
});Full Lifecycle Example
import {
create_sandbox,
resume_sandbox,
delete_sandbox
} from '@sudocode-ai/environment-harness';
// Create
const created = await create_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
repository: 'owner/repo',
});
console.log('Created:', created.codespace.name);
// Resume later (e.g., after it auto-stopped)
const resumed = await resume_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
codespaceName: created.codespace.name,
});
console.log('Resumed:', resumed.codespace.state);
// Clean up
const deleted = await delete_sandbox({
githubToken: process.env.GITHUB_TOKEN!,
codespaceName: created.codespace.name,
});
console.log('Deleted:', deleted.success);Development
# Install dependencies
npm install
# Run tests
npm test
# Run integration tests (requires GitHub token)
npm run test:integration
# Build
npm run build
# Type check
npm run typecheck
# Dry run npm pack (validate package contents)
npm run pack:dryPublishing
To publish a new version to npm:
Pre-publish Validation
# 1. Build the package
npm run build
# 2. Run all tests
npm test
# 3. Validate package contents
npm run pack:dryPublish to npm
# 1. Bump version (patch | minor | major)
npm version patch
# 2. Publish to npm (first time requires --access public)
npm publish --access public
# 3. Push tags to git
git push origin main --tagsPost-publish Verification
# Test installation
npm install @sudocode-ai/environment-harness
# Verify in a test project
node -e "import('@sudocode-ai/environment-harness').then(m => console.log(m))"Notes:
- The
prepublishOnlyscript automatically runs build and tests before publishing - Package contents are controlled by the
filesfield inpackage.json(onlydist/is included) .envfiles and other gitignored files are automatically excluded
Testing
Integration tests require a GitHub token with codespace permissions:
export GITHUB_TOKEN=ghp_your_token_here
npm run test:integrationCompatibility
- Node.js: >= 18.0.0
- TypeScript: >= 5.0
- ESM only (no CommonJS support)
License
MIT