How to Integrate GitHub Repositories as Virtual Workspaces in Routa

Routa treats each workspace as a container for Git repositories, allowing you to clone GitHub repos into .routa/repos and link them via the RepoPicker component so agents and Kanban boards can access the codebase.

Routa is an AI-powered workspace platform that seamlessly integrates version control into its collaborative environment. By connecting GitHub repositories to workspaces, you enable file-aware agents, diff visualizations, and branch-aware task management directly within the phodal/routa ecosystem.

Understanding the Workspace-Repository Architecture

Routa implements a two-layer architecture that abstracts Git operations into workspace-scoped resources. A workspace serves as the logical container, while the repository provides the underlying file tree and version history.

The system relies on a lightweight association model. When you link a repository, Routa stores a RepoSelection object containing the repository name, absolute path, and current branch in the workspace record. This path points to the local clone directory—by default .routa/repos/owner--repo—where all Git utilities operate.

This architecture ensures that whether Routa runs as a web service or Tauri desktop application, the same Git logic applies uniformly.

Step-by-Step Integration Process

Integrating a GitHub repository requires cloning the source code and persisting the association in your workspace configuration.

  1. Open or create a workspace from the Routa home page.

  2. Launch the RepoPicker by clicking the repository selector in the workspace header or settings (src/app/workspace/[workspaceId]/workspace-settings-tab.tsx).

  3. Select the Clone tab and paste a GitHub URL or owner/repo shorthand. The picker's isGitHubInput helper validates the format before enabling the clone action.

  4. Initiate cloning via the UI. The front-end POSTs to /api/clone with the repository URL.

  5. Server-side processing: The src/app/api/clone/route.ts handler parses the URL using parseGitHubUrl, then clones the repository into <clone-base>/owner--repo. If the environment lacks git binaries, the system automatically falls back to importGitHubZipFallback (defined in src/core/github/github.ts) to fetch the zipball.

  6. Monitor progress: The UI subscribes to /api/clone/progress for Server-Sent Events (SSE) updates during the clone operation.

  7. Select the repository from the Existing repositories list. This updates the workspace model with the RepoSelection data.

  8. Verify integration: The workspace now displays branch selectors, file status badges, and enables file search and diff views powered by src/core/git/git-utils.ts.

Programmatic Integration Examples

Beyond the UI, you can integrate repositories programmatically using React components or direct API calls.

Using the RepoPicker React Component

Embed the repository selector directly in custom workspace views:

import { RepoPicker, type RepoSelection } from "@/client/components/repo-picker";
import { useState } from "react";

function WorkspaceHeader() {
  const [selectedRepo, setSelectedRepo] = useState<RepoSelection | null>(null);

  return (
    <div className="flex items-center gap-2">
      <RepoPicker
        value={selectedRepo}
        onChange={setSelectedRepo}
        allowClone={true}
        pathDisplay="inline"
      />
      {/* Selected repo path available via selectedRepo.path */}
    </div>
  );
}

The allowClone prop enables the GitHub import tab, while onChange receives the full RepoSelection object including name, path, and branch.

Manual API Integration

Clone repositories via HTTP requests for automation or external tooling:


# Clone a GitHub repository

curl -X POST https://my-routa-instance.com/api/clone \
  -H "Content-Type: application/json" \
  -d '{"url":"https://github.com/microsoft/TypeScript"}'

# List all cloned repositories

curl https://my-routa-instance.com/api/clone

The listing endpoint returns structured metadata:

{
  "repos": [
    {
      "name": "microsoft/TypeScript",
      "path": "/home/user/.routa/repos/microsoft--TypeScript",
      "branch": "main",
      "branches": ["main", "dev", "release-4.9"],
      "status": {
        "clean": false,
        "ahead": 2,
        "behind": 0,
        "modified": 3,
        "untracked": 1
      }
    }
  ]
}

This response derives from the listClonedRepos() function in src/core/git/git-utils.ts.

Switching Branches Programmatically

Change the active branch for a workspace-linked repository:

await fetch("/api/clone/branches", {
  method: "PATCH",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ 
    repoPath: selectedRepo.path, 
    branch: "feature/new-api" 
  })
});

The back-end handler in src/app/api/clone/branches/route.ts calls checkoutBranch() from the Git utilities, handling edge cases such as bare repositories and non-existent branches by creating them as needed.

Querying Repository Status from Tasks

Access file changes directly within agent tasks or automation scripts:

import { getRepoChanges } from "@/core/git/git-utils";

const changes = getRepoChanges(workspace.repoPath);
console.log(changes.files.map(f => `${f.status}: ${f.path}`));

The getRepoChanges function performs cached git status and git diff --numstat operations for efficient file statistics, enabling agents to respond to code modifications without expensive re-indexing.

Key Implementation Files

Understanding these source files helps when extending or debugging the integration:

Summary

  • Routa integrates GitHub repositories by cloning them into .routa/repos and storing the path in workspace records
  • The RepoPicker component (src/client/components/repo-picker.tsx) provides the primary UI for cloning and selection
  • API endpoints under /api/clone handle repository management, with fallback support for zipball imports in serverless environments
  • Git operations are centralized in src/core/git/git-utils.ts, exposing uniform methods for status checks, branch switching, and diff generation
  • Once linked, repositories enable file-aware agents, Kanban task references, and inline diff visualizations throughout the workspace

Frequently Asked Questions

Can I connect private GitHub repositories to Routa?

Yes, provided your Routa instance has authentication credentials configured. The src/app/api/clone/route.ts handler uses standard git protocols; for private repos, ensure your deployment has SSH keys or HTTPS credentials configured for the runtime environment. The Git utility layer in src/core/git/git-utils.ts executes standard git commands that respect the host's credential store.

What happens if the server environment does not have git installed?

Routa falls back to a zipball import mechanism. When parseGitHubUrl detects a public GitHub repository but git is unavailable, the system calls importGitHubZipFallback from src/core/github/github.ts to download and extract the repository as a static snapshot. This ensures functionality in serverless or restricted environments, though branch switching and history traversal will be limited compared to full git clones.

How does Routa handle switching between branches?

Branch switching occurs through the PATCH /api/clone/branches endpoint, which invokes checkoutBranch() in src/core/git/git-utils.ts. This utility safely handles working directory changes, creates missing branches when specified, and validates that the target repository path exists within the allowed clone base directory. The UI reflects changes immediately by re-fetching the RepoSelection state.

Where does Routa physically store cloned repositories?

Repositories are stored in the clone base directory—by default .routa/repos relative to the working directory—using a sanitized naming convention of owner--repo. This path structure is defined in src/core/git/git-utils.ts and ensures valid filesystem names while maintaining uniqueness across different namespaces. All Git utilities reference repositories by this absolute path, stored in the workspace's RepoSelection record.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →