LogoFreestyle

Git Repositories

Clone git repositories into your VMs automatically.

Overview

Freestyle automatically clones git repositories into your VMs during creation. Repositories are cloned using a read-only mechanism optimized for fast startup times.

Basic Usage

import { freestyle } from "freestyle-sandboxes";

const { vm } = await freestyle.vms.create({
  gitRepos: [
    {
      repo: "https://github.com/owner/repo-name",
      path: "/app",
    },
  ],
});

// Repository is ready to use
await vm.exec("ls /app");

Specifying Repository Format

You can use several formats to specify repositories:

Full GitHub URL

gitRepos: [
  {
    repo: "https://github.com/facebook/react",
    path: "/repos/react",
  },
]

Freestyle Repository ID

If you've imported a repository into Freestyle, use its ID:

gitRepos: [
  {
    repo: "repo_abc123",
    path: "/app",
  },
]

Branches, Tags, and Commits

Clone specific branches, tags, or commits using the rev parameter:

Branch

gitRepos: [
  {
    repo: "https://github.com/owner/repo",
    path: "/app",
    rev: "develop",
  },
]

Tag

gitRepos: [
  {
    repo: "https://github.com/owner/repo",
    path: "/app",
    rev: "v1.2.3",
  },
]

Commit SHA

gitRepos: [
  {
    repo: "https://github.com/owner/repo",
    path: "/app",
    rev: "a1b2c3d4e5f6",
  },
]

If rev is not specified, the default branch (usually main or master) is cloned.

Multiple Repositories

Clone multiple repositories into different paths:

const { vm } = await freestyle.vms.create({
  gitRepos: [
    {
      repo: "https://github.com/company/frontend",
      path: "/app/frontend",
    },
    {
      repo: "https://github.com/company/backend",
      path: "/app/backend",
    },
    {
      repo: "https://github.com/company/shared-lib",
      path: "/app/shared",
    },
  ],
});

With Templates

Include git repositories in templates for caching:

import { freestyle, VmTemplate } from "freestyle-sandboxes";

const template = new VmTemplate({
  gitRepos: [
    {
      repo: "https://github.com/owner/repo",
      path: "/app",
    },
  ],
  systemd: {
    services: [
      {
        name: "install-deps",
        mode: "oneshot",
        exec: ["npm install"],
        workdir: "/app",
        after: ["freestyle-git-sync.service"], // Wait for git clone
        wantedBy: ["multi-user.target"],
      },
    ],
  },
});

const { vm } = await freestyle.vms.create({ template });

Timing and Dependencies

Repositories are cloned by the freestyle-git-sync.service systemd service. If your services need repositories to be present, add a dependency:

systemd: {
  services: [
    {
      name: "my-service",
      mode: "service",
      exec: ["npm start"],
      workdir: "/app",
      after: ["freestyle-git-sync.service"], // Ensure git clone completes first
    },
  ],
}

Read-Only Access

Repositories are cloned in read-only mode. To make changes:

Temporary changes (lost on restart)

await vm.exec("git config --global --add safe.directory /app");
await vm.exec("cd /app && git checkout -b my-branch");
await vm.exec("cd /app && echo 'hello' > test.txt");

Persistent changes

For development workflows, consider:

  1. Making changes and pushing to a branch
  2. Forking the VM to preserve state
  3. Using persistent storage

Working Directory

Set the working directory to your repository path:

const { vm } = await freestyle.vms.create({
  gitRepos: [
    {
      repo: "https://github.com/owner/repo",
      path: "/app",
    },
  ],
  workdir: "/app", // Commands execute here by default
});

// No need to cd
await vm.exec("npm install");
await vm.exec("npm start");

Private Repositories

To access private repositories, you need to import them into Freestyle first:

// Import the repository (one-time setup)
const { repo } = await freestyle.repos.create({
  url: "https://github.com/company/private-repo",
  // Authentication handled via GitHub App or OAuth
});

// Use in VMs
const { vm } = await freestyle.vms.create({
  gitRepos: [
    {
      repo: repo.id, // Use the Freestyle repository ID
      path: "/app",
    },
  ],
});

Common Patterns

Monorepo structure

gitRepos: [
  {
    repo: "https://github.com/company/monorepo",
    path: "/workspace",
  },
],
workdir: "/workspace/packages/api", // Work in specific package

Dev server setup

gitRepos: [
  {
    repo: "https://github.com/owner/webapp",
    path: "/app",
  },
],
systemd: {
  services: [
    {
      name: "install",
      mode: "oneshot",
      exec: ["npm install"],
      workdir: "/app",
      after: ["freestyle-git-sync.service"],
      wantedBy: ["multi-user.target"],
    },
    {
      name: "dev-server",
      mode: "service",
      exec: ["npm run dev"],
      workdir: "/app",
      after: ["install.service"],
      env: {
        PORT: "3000",
      },
    },
  ],
}

Testing specific commits

// Test a specific commit
const { vm } = await freestyle.vms.create({
  gitRepos: [
    {
      repo: "https://github.com/owner/repo",
      path: "/app",
      rev: process.env.COMMIT_SHA, // From CI/CD
    },
  ],
});

On this page

Freestyle AI

Documentation assistant

Experimental: AI responses may not always be accurate—please verify important details with the official documentation.

How can I help?

Ask me about Freestyle while you browse the docs.