In the previous chapter, Environment Selection Strategy, we successfully identified the perfect "building" (server) to run our code.
But there is a problem: the building is empty. Your code is still on your local laptop.
To make the Remote Code Session work, we need to teleport your files to the cloud. You might think, "Why not just use git pull on the server?" The answer is that you often have uncommitted workβmessy, half-written code that you haven't pushed to GitHub yet. The AI needs to see that too!
This chapter introduces State Synchronization, specifically using a technique called Git Bundling.
Imagine you are going on a trip. You need to pack two types of things:
If you only send the "Folded Clothes" (via standard Git), the AI won't see the bug you are currently trying to fix.
teleport uses git bundle to act as a suitcase. It stuffs both the folded clothes (commits) and the messy pile (stashed WIP) into a single file called a bundle. We upload this suitcase to the server, and the server unpacks it, recreating your exact setup.
A Git Bundle is a single file (like a .zip) that contains Git objects (commits, tags, branches).
Normally, Git sends data over a network connection (like SSH or HTTPS). However, git bundle allows Git to treat a file as if it were a remote repository. This allows us to "push" your code into a file, upload that file, and then "pull" from that file on the other side.
We use the function createAndUploadGitBundle to perform this magic. It handles the packing and the uploading in one go.
import { createAndUploadGitBundle } from './gitBundle.js';
// 1. Run the bundler
console.log("Packing your code suitcase...");
const result = await createAndUploadGitBundle(filesApiConfig);
// 2. Check the result
if (result.success) {
console.log(`Success! Bundle ID: ${result.fileId}`);
console.log(`Suitcase size: ${result.bundleSizeBytes} bytes`);
}
Explanation:
This function scans your current folder. It looks for a .git folder, packs up your history, and crucially, grabs your uncommitted changes. It returns a fileId (e.g., file_123...).
You will hand this fileId to the Session later, effectively saying: "Here is the key to my luggage."
You don't need to do anything special. The function automatically detects if you have modified files.
if (result.hasWip) {
console.log("Note: Your uncommitted changes were included!");
}
Explanation:
The system uses a boolean flag hasWip to let you know that it successfully grabbed your work-in-progress files.
This is one of the most sophisticated parts of teleport. It has to be careful not to break your local Git repository while reading from it.
git stash create. This creates a floating commit without actually changing your files.git bundle create to pack that snapshot + your history into a file.
Let's look at gitBundle.ts to see how it handles the "Suitcase Packing Strategy."
We don't want to run git stash push because that would actually hide your files from your editor. Instead, we use git stash create.
// gitBundle.ts
// Create a dangling commit object of current changes
const stashResult = await execFileNoThrowWithCwd(
gitExe(),
['stash', 'create'],
{ cwd: gitRoot }
);
// If successful, we get a hash (SHA) back
const wipStashSha = stashResult.stdout.trim();
Explanation:
git stash create is a plumbing command. It makes a commit object of your changes but does not touch your working directory or HEAD. It returns the ID of that commit, which we save.
Sometimes, a repository is too huge (gigabytes of data) to pack into one suitcase. teleport tries three different suitcase sizes:
--all: Try to pack every branch and tag.HEAD: If --all is too big, just pack the current branch.Squashed: If HEAD is still too big, flatten the history into one single commit (no history, just files).// gitBundle.ts (Simplified)
// Attempt 1: Try to bundle everything
let result = await execGit(['bundle', 'create', bundlePath, '--all']);
// If too big, try Attempt 2: Just the current branch
if (result.size > MAX_BYTES) {
result = await execGit(['bundle', 'create', bundlePath, 'HEAD']);
}
// If still too big, try Attempt 3: Squash history
if (result.size > MAX_BYTES) {
// Create a new single commit with no parents
await execGit(['commit-tree', 'HEAD^{tree}', '-m', 'seed']);
// Bundle that single commit
}
Explanation: This ensures that the upload succeeds even on large repositories. The remote AI usually doesn't need 5 years of historyβit just needs the current files to run the code.
Once the bundle file exists on your disk, we upload it using the uploadFile helper.
// gitBundle.ts
const upload = await uploadFile(
bundlePath,
'_source_seed.bundle',
config
);
return {
success: true,
fileId: upload.fileId // This is what we need!
};
In this chapter, we learned:
createAndUploadGitBundle to generate a fileId.We have now prepared the Session (Room), the Environment (Building), and the Bundle (Suitcase).
We are finally ready to connect everything and start talking to the AI.
Next Chapter: API Communication Layer
Generated by Code IQ