This past week I got access to the preview of GitHub Copilot X aka the one with Chat.

I've been heads down delivering my next Pluralsight course on React debugging and between ChatGPT and GitHub Copilot, I can tell you first-hand that AI copilots will change the way developers use your product.

Here's a small but significant example and I figured I'd write it up as it just happened since I have a tendency to write a lot when I shouldn't, like when it's midnight.

GitHub has a new way to configure codespaces called Dev Containers. I've never used them before tonight.

Introduction to dev containers - GitHub Docs
When you work in a codespace, the environment you are working in is created using a development container, or dev container, hosted on a virtual machine.

For my Pluralsight course, I have a full-on learning experience companion app with code challenges, it looks like this:

It's what I use to do all the debugging demos in the course. It's designed to be played with, poked at, and cattle-prodded by learners – even ones outside Pluralsight. It's a learning experiment I wanted to do to try and practice what I preach – gamification, hands-on learning, storytelling – ya know? We'll see how it goes.

Anyway, what I wanted to enable was a "one-click" developer experience so learners could click a button and get this up and running. No local machine shenanigans. No wrestling with config. I want a frictionless DX. Again, that's kinda my thing.

Well, I was able to achieve it using GitHub Codespaces and Dev Containers.

But not right away. You see, the repository itself has a folder structure like this, with materials for the course:

The learning app is all within the demo folder.

By default, the dev container configuration will launch the Codespaces at the root of your repo which most people will want.

But in my case, I needed to launch it so VS Code is displaying the demo folder contents, not the root, because I use different VS Code configurations and, well, it's just confusing. That's not frictionless.

I read the initial getting started documentation and had the following JSON configuration file:

{
  "name": "Node.js",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18",
  "forwardPorts": [3000],
  "postCreateCommand": "npm install"
}

This was easy enough because the file it generated contained code comments with helpful suggestions:

Helpful.

This worked right away, and I could launch my codespace.

But then my next question was, of course, how do I get this to show the right folder in the browser?

Very cool. But wrong root folder...

At first, because old habits die hard, I went to the docs.

GitHub has great comprehensive documentation of this feature but OF COURSE, the actual reference docs for this JSON file are hosted elsewhere and not linked anywhere that I could easily parse in the Great Wall of Docs.

Thankfully, the JSON file itself linked to it.

No easy link to what I am looking for 😑
Actually helpful!

Once I got to the right spot, I spotted two settings that looked promising: workspaceFolder and workspaceMount. However, it was a bit confusing which one did what, and the mount expression was unfamiliar to me.

The docs, in this case, didn't go into further detail.

Wait, what's the difference???

Alarm bell. If a developer gets stuck, there's a decision point. I could soldier on and try to figure it out through trial and error. Or abandon ship.

It's hard to know what goes on in a developer's mind so I'll just tell you what went on in mine:

Dang it. What do I do? These HAVE to be it... there must be some magic value I can pass to one of these or both of them to make it work. Ugggh, it should have been simple why is this so hard. I really want this to work.

I felt like this was the right direction, and I wanted it to work, so I continued. That's me though, I have been on enough support calls in my life to know that many devs (and people, for that matter) will throw up their hands at any sign of resistance – that's when they'll seek help instead of trying to debug the issue. I took on the React Debugging course for a reason, dangit, I AM The Debugger.

In fact, I had an idea 💡

I certainly have no idea what to do, what if GitHub Copilot can tell me what to do? This would put its hype to the test. I'll be honest, I didn't think it could help me, despite me using it just the other day to write a duration formatting function that I hooted for joy in the dead of night in my basement when it worked and I didn't even need to Google anything. Despite the fact that earlier today it uncovered a bug in my sample code I didn't intend (shh, you didn't hear that!).

No – I remained skeptical.

On the right side of my editor, I opened up the Copilot Chat and started to tell it what I wanted.

I began... a conversation. I'll reproduce it formatted below, emojis representing my reactions:

😕
How can I have the devcontainer start the browser editor within the demo subfolder?
🤖
To have the devcontainer start the browser editor within the demo subfolder, you can set the workspaceFolder property in the devcontainer.json file to /demo as it is already set in the provided excerpt.

This will make the demo subfolder the root folder of the workspace.

Here is an example of what your settings.json file could look like:

[example]
🙃
I have workspaceFolder set to /demo but the browser is still loading VS Code at the root of the repo instead of the demo subfolder
🤖
If you have set the workspaceFolder property in the devcontainer.json file to /demo, but the browser is still loading VS Code at the root of the repo instead of the demo subfolder, you can try setting the workspacePath property in the .devcontainer/devcontainer.json file to /demo. This will set the workspace path to the demo subfolder.

Here is an example of what your devcontainer.json file could look like:

[example]
🙄
Unfornately that isn't allowed
🤖
I'm sorry to hear that my previous suggestion did not work for you. Can you please provide more information about the issue you are facing? Are you receiving any error messages or unexpected behavior?

In the meantime, you can try setting the workspaceFolder property to "./demo" instead of "/demo". This will set the workspace folder to the demo subfolder relative to the root of the repository.

Here is an example of what your devcontainer.json file could look like:

[example]
😔
If I try to use workspacePath it says the property is not allowed according to the JSON schema. I tried the ./demo for workspaceFolder but it still doesn't work when the container rebuilds. Is there a different way to configure the codespaces editor?
🤖
I apologize for the confusion. The workspacePath property is not allowed in the devcontainer.json file.

If setting the workspaceFolder property to "./demo" did not work for you, you can try setting the workspaceMount property to mount the demo subfolder as the root of the workspace. This will ensure that the demo subfolder is the root folder of the workspace, and the browser editor will open in that folder.

Here is an example of what your devcontainer.json file could look like:

[example]

This will mount the demo subfolder as the root of the workspace, and the workspaceFolder property is set to "." to ensure that the workspace is not nested within the demo subfolder.
🤔
It seems like using . shows me the root of the container filesystem
🤖
If using "." as the workspaceFolder property shows you the root of the container filesystem, you can try setting the workspaceFolder property to "./demo" instead. This will set the workspace folder to the demo subfolder relative to the root of the repository.

Here is an example of what your devcontainer.json file could look like:

[example]

This will mount the demo subfolder as the root of the workspace, and the workspaceFolder property is set to "./demo" to ensure that the workspace is not nested within the demo subfolder.
🤔
The /workspace folder successfully contains the demo subfolder, but the workspace itself still seems to be rooted at the root of the container, not /workspace
🤖
If the workspace still seems to be rooted at the root of the container instead of /workspace, you can try setting the workspaceFolder property to /workspace in the devcontainer.json file. This will set the workspace folder to the /workspace directory.

Here is an example of what your devcontainer.json file could look like:

[example]

This will mount the demo subfolder as the demo subdirectory of the /workspace directory, and the workspaceFolder property is set to /workspace to ensure that the workspace is rooted at the /workspace directory.
😍
That worked!
🤖
I'm glad to hear that setting the workspaceFolder property to /workspace and mounting the demo subfolder as the demo subdirectory of the /workspace directory worked for you! If you have any other questions or issues, feel free to ask.

OK. A few things.

At the start, like I feared, the answer wasn't helpful – I already had the config setting it said to try.

Then, it got worse – it hallucinated.

🧠
Hallucinate: When a generative AI goes rogue and tries to be creative and helpful by generating an untrue answer without mentioning it. I call this "generative gaslighting."

Because workspacePath is a non-existent JSON property. I could see this in the editor because VS Code was also saying it wasn't an allowed property.

Me robot, me make shit up.

Luckily, it understood when I gave it some more context. As as last ditch effort, I asked if there was another way. I was thinking perhaps some other JSON file or configuration hidden somewhere.

That's when it got interesting.

When it asked me to modify the workspaceFolder to . it changed what I was seeing in the browser. Suddenly, something happened.

I could see that maybe this was on the right path, because all we needed to do, me and my new best robo friend, was change the folder from the root of the container to /workspace which did have the contents of the demo folder now.

I perked up.

It only took one more try, actually reverting back to the default value of /workspace (which the docs never mention, btw).

This gave us:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
  "name": "Node.js",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18",
  "workspaceFolder": "/workspace",
  "workspaceMount": "source=${localWorkspaceFolder}/demo,target=/workspace,type=bind,consistency=cached",
  "forwardPorts": [3000],
  "postCreateCommand": "npm install"
}

The magic was really the source=${localWorkspaceFolder}/demo bit. That, plus having the right value for workspaceFolder.

When this worked, I was ecstatic. This whole conversation probably took 15 minutes since I had to push each change and test it.

The story could end there but as I wrote this up, I realized something. Maybe you did too, if you paid close enough attention (I bet you didn't).

The answer was in the docs.

Here, let me highlight it for you:

oh for the love of--

WHY DIDN'T I SEE IT?

Well, why didn't you see it?

I think it's a combination of things.

  • We scan, we don't read unless there's something we decide warrants attention.
  • The code is all inline instead of formatted nicely in a code block
  • It doesn't explain the example, so there was no call to pay attention
  • The workspaceFolder setting doesn't mention the default value either
  • I was trying to comprehend what I was reading, I didn't know yet what the code block might be communicating because I had never seen it before

So let's take a step back now.

What does this all mean? Besides being a gripping story between man and machine where machine helps man triumph and cause him to stay up late (again) writing a longform blog post.

What does it mean, besides that?

It means: the way developers will interact with your product, your education, your... experience, is going to change.

Even though the answer was in plain sight, as a human being, I didn't see it. The machine did. Actually, I have no idea if it did, but it eventually led to the right answer with enough back-and-forth context narrowing, like a funnel where the ping-pong ball has no choice but to end up at the end.

Now it was possible the answer was "You can't do that," but that's a sufficient answer. At least I wouldn't wonder – I'd need to find an alternative way. But as the expert developer, based on my experience, I reasoned it was possible – just that I didn't know the exact details of how to make it work.

So anyway, GitHub Copilot is the real deal.

Look for my new React Debugging course in a few weeks, you can follow me on Pluralsight directly and of course, I'll announce it through the list.

Have a lovely day,
Kamran

GitHub Copilot is the real deal

Want devs to love your product?

Hi 👋 I'm Kamran. I'm a consulting developer educator who can help your DevRel team increase adoption with better docs, samples, and courseware.
jamie@example.com
Sign up