In Chapter 4: Redacted Token Security, we learned how to treat the user's GitHub token like a top-secret document. We sealed it inside a RedactedGithubToken envelope so it wouldn't accidentally leak into our logs.
Now, we have reached the final step. We need to take that sealed envelope and securely deliver it to the Claude servers.
Imagine you have a sealed letter for the CEO of a company. You don't just walk into the building, wander the halls, and hope you find the right office. You also need your own ID badge to even get through the front door.
In software, communicating with a backend server involves similar challenges:
If we wrote this logic inside our UI code, it would be messy and insecure. Instead, we create a Backend API Client. This acts as our dedicated Private Courier. The UI simply says "Deliver this," and the Client handles the IDs, the maps, and the secure transport.
Before we can send the GitHub token to the server, we need to prove who we are. We use a helper function prepareApiRequest to get our current Claude authentication headers.
This is the most critical moment in the application. We take the RedactedGithubToken (the sealed envelope), and for a split second, we open it using .reveal() to put the secret data into the secure HTTPS request.
Network requests can fail in many ways (internet down, server error, invalid token). Instead of throwing messy "Exceptions" that crash the app, our client returns a tidy object telling us exactly what happened (e.g., { ok: false, error: 'network' }).
We are working in api.ts. The main function we need is importGithubToken.
The UI code (from Chapter 2) doesn't need to know about URLs or headers. It just calls this function:
// Inside the UI logic
const result = await importGithubToken(userToken);
if (result.ok) {
console.log("Success! Connected as:", result.result.github_username);
} else {
console.log("Something went wrong:", result.error);
}
RedactedGithubToken object.
What happens inside importGithubToken?
.reveal() on the token envelope.axios (an HTTP library) to POST the data to the server.
Let's look at the code in api.ts that handles this sensitive operation.
Before we talk to the server, we ensure the user is logged into Claude.
// file: api.ts
let accessToken: string, orgUUID: string;
try {
// Get our "ID Badge"
({ accessToken, orgUUID } = await prepareApiRequest());
} catch {
return { ok: false, error: { kind: 'not_signed_in' } };
}
prepareApiRequest fails, the user isn't logged into Claude CLI, so we stop immediately.This is where we combine the Headers (ID Badge) and the Body (Secret Token).
const headers = {
...getOAuthHeaders(accessToken), // Attach ID badge
'x-organization-uuid': orgUUID,
};
const response = await axios.post(
url,
{ token: token.reveal() }, // <--- OPENING THE ENVELOPE
{ headers, timeout: 15000 }
);
token.reveal(): This is the only place in the entire application where we uncover the secret. Because axios sends data over HTTPS (encrypted internet traffic), it is safe to reveal it here.
After the token is imported, we want the user to have a cloud computer ready. We have a second function createDefaultEnvironment.
export async function createDefaultEnvironment(): Promise<boolean> {
// If they already have a computer, don't make a new one
if (await hasExistingEnvironment()) {
return true;
}
// Otherwise, ask the server to build one
const response = await axios.post(createUrl, defaultPayload, { headers });
return response.status >= 200;
}
Congratulations! You have completed the Remote Setup tutorial.
Let's review the journey we took to build this feature:
web-setup command and guarding it with feature flags.You now have a fully functional, secure, and user-friendly CLI command that connects a local developer environment to the cloud! ๐
Generated by Code IQ