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.
- Front-end layer: The
RepoPickercomponent (src/client/components/repo-picker.tsx) handles UI interactions, URL validation, and branch selection - Back-end layer: REST endpoints under
/api/clonemanage cloning, progress streaming, and branch operations, delegating to utilities insrc/core/git/git-utils.ts
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.
-
Open or create a workspace from the Routa home page.
-
Launch the RepoPicker by clicking the repository selector in the workspace header or settings (
src/app/workspace/[workspaceId]/workspace-settings-tab.tsx). -
Select the Clone tab and paste a GitHub URL or
owner/reposhorthand. The picker'sisGitHubInputhelper validates the format before enabling the clone action. -
Initiate cloning via the UI. The front-end POSTs to
/api/clonewith the repository URL. -
Server-side processing: The
src/app/api/clone/route.tshandler parses the URL usingparseGitHubUrl, then clones the repository into<clone-base>/owner--repo. If the environment lacksgitbinaries, the system automatically falls back toimportGitHubZipFallback(defined insrc/core/github/github.ts) to fetch the zipball. -
Monitor progress: The UI subscribes to
/api/clone/progressfor Server-Sent Events (SSE) updates during the clone operation. -
Select the repository from the Existing repositories list. This updates the workspace model with the
RepoSelectiondata. -
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:
src/client/components/repo-picker.tsx: React component providing the clone UI, GitHub URL detection, and branch selection dropdownsrc/app/api/clone/route.ts: Next.js API route handling clone requests and zipball fallbackssrc/app/api/clone/progress/route.ts: SSE endpoint for real-time clone progress updatessrc/app/api/clone/branches/route.ts: Branch listing and switching endpointsrc/core/git/git-utils.ts: Core library exposinglistClonedRepos,checkoutBranch,getRepoChanges, and repository detection utilitiessrc/core/github/github.ts: GitHub API wrapper for zipball imports when native git is unavailable
Summary
- Routa integrates GitHub repositories by cloning them into
.routa/reposand 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/clonehandle 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →