Reinventing the Development Workspace with Chalk Sandboxes

Aarman Pannu - Forward Deployed Engineer
by Aarman Pannu

How I’m using Chalk Sandboxes, Functions, and Volumes to rethink how I code alongside my agents

November 2, 2026

Using Codex and Claude Code in my terminal has made me faster. It’s also made a mess of my laptop.

The way I write code has changed substantially since 2025. I’m running multiple coding sessions, delegating investigations, and reviewing more work in parallel. That’s a big enough change to rethink my development environment from the ground up. Better agent instructions and more worktrees help, but they still leave me managing all those sessions and environments on my laptop.

Where running my agents locally breaks down

More worktrees, more terminals, and more one-off scripts and temporary READMEs to clean up before they sneak into a PR. I’ll start an investigation in one session, make a change in another, and lose track of which terminal is running tests. Sandboxes get that clutter off my laptop and let work continue when I disconnect. But a remote container isn’t enough if I still need to switch back to inspect code or test an idea. The sandbox needs to be somewhere I can work alongside the agent, not just somewhere it runs.

Engineers care about their setups. A former coworker arrived with a setup script he’d been evolving throughout his career. I recognize the instinct: I want my dotfiles, aliases, CLIs, and Herdr. I prefer Codex; some teammates prefer Claude. Others refuse to use anything but Neovim. Moving into a sandbox shouldn’t mean giving those choices up.

Working with agents is still iterative: designing, investigating, implementing, and testing. I’m questioning the approach and reviewing the code in context, sometimes down to individual lines, not just looking at a diff when the PR is ready. So that’s what I’ve been building with Chalk: my development environment as a callable, configurable Chalk Function. It provisions the tools, repositories, access, and shared storage; I enter through Herdr and work alongside Codex or Claude.

My development environment as a Chalk Function

A Chalk Function is a Python callable deployed with its runtime and resource configuration. Chalk handles running it remotely; I don’t need to build and operate a separate provisioning service.

My Function creates and returns a sandbox. It brings together development tools, repositories, dotfiles, compute resources, credential bindings, and persistent storage. Instead of repeating those steps for every investigation, I call the Function with the settings for that task.

Those decisions live in the Function, where I can review and change them. If I need another CLI, I can add it. If a task needs more memory, I can configure that in the Function. At Chalk, before we migrated to Bazel, we could tell when someone was rebuilding all of LibChalk, our internal C++ library, because we could hear their Mac’s fans. A sandbox can compile thousands of C++ files without announcing it to the rest of the office. Network policies, credential bindings, and mounted Volumes belong in that configuration too. I’ll cover how the credentials work in the next section.

@cc.function(
    name="create-blog-workspace",
    image=provisioner_image(),
    chalk_identity=True,
)
def create_blog_workspace(
    name_suffix: str = "investigation",
    lifetime_minutes: int = 60,
    shared_volume_name: str = "blog-dev-context",
    cpu: str = "1",
    memory: str = "2Gi",
    github_secret_name: str = "",
) -> cc.Sandbox:
    return make_sandbox_workspace(
        name_suffix=name_suffix,
        image=cc.Image.from_json(IMAGE_SPEC),
        cpu=cpu,
        memory=memory,
        lifetime_minutes=lifetime_minutes,
        shared_volume_name=shared_volume_name,
        github_secret_name=github_secret_name,
        chalk_identity=True,
        network_policy=cc.NetworkPolicy(
            allowed_hosts=["api.github.com", "github.com", "*.chalk.ai"]
        ),
resource_detectors=[
cc.ResourceDetector.GITHUB_PULL_REQUESTS],
    )

The Function can expose arguments for the things I change between tasks. For example, this interface lets me name the workspace, choose its lifetime, and select a shared Volume before launching Herdr:

chalk sandbox start create-blog-workspace \
  --arg name_suffix=feature-investigation \
  --arg lifetime_minutes=60 \
  --arg shared_volume_name=blog-dev-context \
  -- herdr

Those arguments are defined by the Function; they aren’t a fixed set of sandbox options. We choose which settings to expose and which defaults to keep in the shared configuration.

Herdr runs inside the sandbox, so I can move between my coding assistant, editor, and shell, with tmux available when I want it. I can inspect the files, run commands, and make changes alongside the agent. I can also run multiple Codex or Claude sessions on different components of the same task, giving each a separate checkout when their changes might overlap.

The Function also gives us one place to maintain the shared setup. We can add a tool or update a policy for future launches without asking everyone to repeat the setup manually. Arguments cover the differences between tasks; editors, aliases, dotfiles, and agent choice can still reflect how each of us works.

The point is to make my setup easy to recreate, extend, and configure without making everyone work the same way.

Giving the workspace the right access

I need to clone private repositories, open PRs, and query models and services without switching back to my laptop. That shouldn’t mean copying all my credentials into every sandbox; a bug fix in one repository doesn’t need access to the rest.

For GitHub, I can store a token in Chalk Secrets and bind it to requests for api.github.com. The sandbox uses a placeholder; Chalk substitutes the real credential into the configured request headers for that host. With resource detection configured, supported PR-creation requests also produce durable PR artifacts linked to the sandbox. The result isn’t just a URL buried in terminal output; I can easily find the PR in Chalk after the sandbox is gone.

Snowflake is another example. Installing snow is easy; authenticating a CLI in a remote sandbox is usually the annoying part. My laptop’s browser session doesn’t automatically carry over, and I don’t want to distribute passwords or private keys to every workspace. Chalk supports Snowflake workload identity, so the CLI can authenticate using the sandbox’s identity once Snowflake is configured to trust it. Snowflake still controls which roles, warehouses, and data that identity can access.

Network policy sits alongside those credential bindings. I can allow the hosts the task needs, while the credential’s permissions determine what it can do there. As an FDE, I also need to keep privileged customer access separate; checking out a repository shouldn’t silently grant access to production systems.

For model requests, Chalk’s Model Gateway lets the sandbox authenticate through workload identity rather than requiring a provider API key in every workspace.

These integrations let me do the work inside the sandbox rather than keep an authenticated terminal open on my laptop for every service. The access is configured for the workspace; it doesn’t come from copying everything my laptop can reach.

Working alongside the agent

For a bug fix, I need to reproduce the failure before asking for a patch.

At Chalk, we use Coder extensively for development and testing. I might start with a failure reproduced there, then work with Codex or Claude in the sandbox to trace the code and write a regression test. We confirm it fails for the reason we expect, then work on the fix.

In Herdr, the coding session sits beside my editor and shell. I can check another caller or try an input the agent missed while it works on the patch. We’re looking at the same files! If its approach is wrong, I can redirect it or edit the code immediately rather than wait for a finished PR to discover we went in the wrong direction.

Sharing a workspace also makes verification easier to inspect. I can run the relevant Bazel tests or validate in Coder, then review the patch against those results. The agent can help write and test the change; I still decide whether it fixes the issue and is safe to ship, especially around authentication, permissions, or sensitive data.

Once ready, the agent opens the PR. Chalk’s resource detection records supported PR creation as a durable artifact linked to the sandbox. The workspace can be temporary without making its output hard to find.

[Show Herdr with the coding session, editor, and test output, followed by the detected PR artifact in Chalk.]

For a larger feature, parallel sessions let us work on different components without waiting for every change to happen in sequence. But they still need an agreed design and clear boundaries. I can delegate implementation while staying involved in the interfaces and behavior that make those components fit together.

Keep the useful context; leave the scratch work behind

The work also needs continuity beyond any one session. Multiple sandboxes can mount the same Chalk Volume, so the plan, findings, test results, and outstanding questions don’t belong to just one workspace.

For example, I might investigate a performance regression in one sandbox while several other sandboxes test candidate fixes in parallel. Each gets its own checkout, dependencies, and compute resources. I publish the reproduction steps, benchmark inputs, and baseline results to the shared Volume; the other sandboxes reload them and test their approaches against the same baseline. Each can publish results under its own path, so I can compare what worked before deciding which approach to take.

Another engineer can mount that Volume too, without reconstructing the investigation from terminal history. Publishing and reloading are explicit; running sandboxes reload to see the latest committed version.

Example of my Herdr setup with dummy data

Example of my Herdr setup with dummy data

That also lets me be less precious about scratch work. My Codex sessions seem to love writing one-off Python scripts. Those scripts and temporary design notes can stay in the sandbox unless we decide they’re worth keeping. When it’s terminated, the scratch work goes with it; the PR, its artifact record, and anything published to the Volume remain.

Our development tools need to catch up

Moving my workflow into Chalk hasn’t meant giving up my editor, aliases, or preferred coding assistant. It’s changed how I create workspaces, give them access, and carry useful context between tasks.

I can start a workspace from a Function, work alongside the agent in Herdr, and preserve the results without keeping every experiment on my laptop. The same baseline is reusable across the team without making everyone work the same way.

Our coding tools have changed how much work we can take on. Our development environments should help us manage that work, not become another thing to manage.


Want to stay up-to-date with Chalk?

Subscribe for updates on what we’re building (and shipping!) at Chalk