Laika

A VS Code extension for browsing and firing .http file requests — a visual companion to the plain-text HTTP workflow, without leaving the editor.
Getting started
- Install the extension.
- Open any workspace that contains
.http files.
- Click the Laika icon in the Activity Bar (the astronaut helmet).
- Expand a file in the sidebar to see its requests.
- Click ▶ next to a request to open the request panel.
- Click Send Request — the response appears below with the status code, headers, and highlighted body.
The Laika panel has two views:
- HTTP Files — lists every
.http file found in the workspace. Files are watched automatically — add, delete, or save one and the tree updates instantly. Use the ↻ button to force a refresh.
- History — shows the last 100 sent requests, newest first. Click any entry to open a read-only detail panel. Use the 🗑 button to clear the log.
The request panel
Opening a request shows the resolved URL, headers, and body (all {{variables}} already substituted) before you send anything. After sending:
- Status is colour-coded: green (2xx), yellow (3xx), orange (4xx), red (5xx)
- Response headers are collapsible
- Body is pretty-printed with JSON syntax highlighting
The panel stays open when you switch tabs. Clicking a different request updates it in place rather than opening a new tab.
Laika uses the same format as the REST Client extension, so existing .http files work without changes.
@baseUrl = https://api.example.com
@token = abc123
### List users
# @name listUsers
GET {{baseUrl}}/users
Authorization: Bearer {{token}}
Accept: application/json
###
### Create user
# @name createUser
POST {{baseUrl}}/users
Content-Type: application/json
{
"name": "Laika",
"role": "first dog in space"
}
| Syntax |
Meaning |
### |
Separator between requests |
### Label |
Separator with a display name |
# @name Foo |
Request name (overrides separator label) |
# Description text |
Markdown description shown in the request panel |
# @pre ./path/script.js |
Run a JavaScript file before sending the request |
# @post ./path/script.js |
Run a JavaScript file after receiving the response |
@var = value |
File-scoped variable declaration |
{{var}} |
Variable substitution (URL, headers, body) |
Key: Value |
Request header |
| (blank line) |
Marks the end of headers; everything after is the body |
Request descriptions
Any # or // comment lines that appear before the HTTP method line (and aren't @ annotations like @name) are treated as a markdown description and displayed in the request panel:
### Get Pokémon
# Fetches a single Pokémon from the PokeAPI.
# Supports **name** or numeric *ID* as the path parameter.
# @name GetPokemon
GET https://pokeapi.co/api/v2/pokemon/{{name}}
Supported formatting: **bold**, *italic*, `inline code`, - bullet list.
Environments
Laika uses the same environment file format as Visual Studio 2022, so any existing http-client.env.json file works without changes.
Environment file
Create a file named http-client.env.json in your workspace root (or anywhere in the directory tree above your .http files — Laika searches upward, just like Visual Studio). The file is a JSON object whose keys are environment names:
{
"$shared": {
"API_VERSION": "v1"
},
"dev": {
"BASE_URL": "http://localhost:3000",
"API_KEY": "dev-key"
},
"staging": {
"BASE_URL": "https://api.staging.example.com",
"API_KEY": "stg-key"
}
}
$shared is a special key whose variables act as defaults for every environment. A specific environment can override any $shared variable by re-defining it.
User-specific overrides
Place a http-client.env.json.user file alongside the main file for values you don't want to commit (personal tokens, local ports, etc.). Variables in .user override the shared file for the same environment. Add *.user to .gitignore.
{
"dev": {
"API_KEY": "my-local-key"
}
}
Selecting an environment
The HTTP Files view shows an Environment item at the top that displays the currently active environment. Click it (or the $(server-environment) toolbar button, or run Laika: Select Environment from the Command Palette) to open the picker. Choose <none> to use only in-file @var declarations. The selection persists across sessions and updates the tree item label immediately.
Variable priority
When a request is sent, variables are resolved in this order (highest wins):
- Inline
@var declarations inside the request block
- File-level
@var declarations at the top of the .http file
.user file — active environment block
http-client.env.json — active environment block
.user file — $shared block
http-client.env.json — $shared block
Example
### Health check
GET {{BASE_URL}}/{{API_VERSION}}/health
Authorization: Bearer {{API_KEY}}
Switch to dev → sends to http://localhost:3000/v1/health. Switch to staging → sends to https://api.staging.example.com/v1/health. No file edits needed.
Scripts
Pre and post request scripts let you run JavaScript before and after any HTTP request — for tasks like injecting authentication tokens, logging response data, or chaining values from one request into the next.
Per-request scripts
Add # @pre and/or # @post annotations to a request block. Paths are relative to the .http file's directory:
### Login
# @name login
# @pre ./scripts/addTimestamp.js
# @post ./scripts/saveToken.js
POST {{baseUrl}}/auth/login
Content-Type: application/json
{"username": "{{user}}", "password": "{{pass}}"}
Environment-level scripts
Add a $scripts key to http-client.env.json to run scripts for every request in an environment. Use $shared for scripts that apply to all environments, or scope them to a named environment:
{
"$scripts": {
"pre": "./scripts/global-pre.js",
"post": "./scripts/global-post.js"
},
"$shared": { "baseUrl": "https://api.example.com" },
"dev": {
"$scripts": { "pre": "./scripts/dev-pre.js" },
"baseUrl": "http://localhost:3000"
}
}
Execution order
Scripts run in this order for every request:
$shared.$scripts.pre
- Active environment
$scripts.pre
- Request
# @pre
- → HTTP request fires ←
- Request
# @post
- Active environment
$scripts.post
$shared.$scripts.post
Script API
Scripts receive a context object as their global scope. All properties are accessible as top-level variables.
Pre-script context:
request: {
url: string // mutable
method: string // mutable
headers: Record<string, string> // mutable
body: string | undefined // mutable
}
variables: Record<string, string> // mutable — changes written back to .http file
env: Record<string, string> // read-only environment variable snapshot
console: { log, warn, error } // output to "Laika Scripts" channel
Post-script context:
request: { url, method, headers, body } // read-only
response: {
status: number
statusText: string
headers: Record<string, string>
body: string
duration: number
json(): unknown // parses body as JSON, returns null if invalid
}
variables: Record<string, string> // mutable — changes written back to .http file
console: { log, warn, error }
Example — inject a timestamp header (pre-script):
request.headers['X-Timestamp'] = String(Date.now());
Example — save a token for the next request (post-script):
const data = response.json();
variables.token = data.access_token;
To write back a variable, it must be declared in the .http file (e.g. @token =). Variables that exist only in the environment file are not written back.
Variable write-back
When a script mutates variables, any changed values that have a file-level @var declaration are written back to the .http file automatically after the request completes. This enables request chaining:
@token =
### Step 1 — login, save token
# @post ./scripts/saveToken.js
POST {{baseUrl}}/login
###
### Step 2 — use saved token
GET {{baseUrl}}/profile
Authorization: Bearer {{token}}
async / await
Scripts support top-level await:
const result = await someAsyncOperation();
variables.data = result.value;
Timeout
Each script invocation has a configurable timeout. Set laika.scriptTimeout in VS Code settings (default: 10 seconds, range: 1–300).
Notes
- Scripts run in a Node.js
vm sandbox — there is no require or module system available. Use only plain JavaScript and the provided context API.
- Pre-script failures abort the request and show an error in the panel. Post-script failures are logged but do not suppress the response.
- Script
console.log/warn/error output appears in the Laika Scripts Output channel (always visible — no setting required).
Contributing
npm install
npm run compile # type-check + lint + bundle
npm run watch # rebuild on save
Press F5 in VS Code to open an Extension Development Host with Laika loaded.