Curlex API Client — User Guide

Curlex is a fast, local-first, no-nonsense API client for macOS and Windows. No cloud account required. No telemetry. Just a powerful desktop tool for building, testing, and documenting your APIs.


Table of Contents

  1. Introduction
  2. Installation & Setup
  3. User Interface Overview
  4. Workspaces
  5. Collections & Folders
  6. Building & Sending Requests
  7. Request Body
  8. Authentication
  9. Pre-Request & Test Scripts
  10. Environment Variables
  11. Response Panel
  12. Request History
  13. Collection Runner
  14. Import & Export
  15. Console
  16. GitHub Sync
  17. Settings
  18. Keyboard Shortcuts

1. Introduction

Curlex is an open-source desktop API client built with React, TypeScript, and Tauri. It provides a complete environment for designing, testing, and debugging HTTP APIs — all without sending any data to external servers.

Key Highlights

FeatureDescription
🚀 Local-firstAll data stored locally in IndexedDB. No account needed.
🔐 Secure credentialsPasswords and tokens stored in the OS keychain.
📁 CollectionsOrganise requests into nested folders and collections.
🌍 EnvironmentsSwitch variable sets (base URLs, API keys) with one click.
📝 ScriptsRun JavaScript before requests and validate responses with test scripts.
🔄 GitHub SyncBack up and sync all data to a private GitHub repository.
🎨 ThemesDark and light modes with a fully customisable editor.
🖥️ Native desktopPackaged as a native .dmg (macOS) or .exe (Windows).

2. Installation & Setup

Prerequisites

ToolPurposeDownload
Node.js ≥ 18 LTSJavaScript runtimenodejs.org
npmPackage manager (bundled with Node.js)
GitVersion controlgit-scm.com

Verify your installation:

node -v   # e.g. v20.11.0
npm -v    # e.g. 10.2.4
git --version

Running from Source

# 1. Clone the repository
git clone https://github.com/nilandev/Curlex.git
cd Curlex

# 2. Install dependencies
npm install

# 3. Start in development mode (Vite + Tauri)
npm run dev

The application window opens automatically. Vite's hot-reload is active for the renderer process.

Building for Production

PlatformCommandOutput
macOSnpm run package-macdist/*.dmg
Windowsnpm run package-windist/*.exe

3. User Interface Overview

Curlex main interface

Curlex uses a three-zone layout:

┌─────────────────────────────────────────────────────────────────┐
│  Header Bar         [Workspace selector]         [Import]        │
├──────┬──────────────────────────────────────────────────────────┤
│      │  Sidebar Content           │  Main Content Area          │
│ Rail │  (Collections / History /  │  (Tabs + Request/Response)  │
│      │   Runner / Environments)   │                             │
├──────┴──────────────────────────────────────────────────────────┤
│  Status Bar              [Cookies]  [Console]                   │
└─────────────────────────────────────────────────────────────────┘

The narrow icon strip on the far-left switches the sidebar panel:

IconPanel
📋 CollectionsBrowse and search all saved requests
🕐 HistoryView previously sent requests
▶️ Collection RunnerExecute entire collections automatically
🌍 EnvironmentsManage environment variable sets
🗂️ WorkspacesSwitch between separate workspaces
⚙️ SettingsApplication settings
❓ HelpQuick reference and runbook

Header Bar

  • Workspace selector — Switch the active workspace or create a new one.
  • Import — Import requests from cURL, OpenAPI, Postman, or Curlex format.
  • Sync button (when GitHub Sync is enabled) — Trigger a manual sync.
  • Environment badge — Shows the active environment; click to switch.

Status Bar (Bottom)

  • Cookies — View and manage cookies stored by the cookie jar.
  • Console — Toggle the Console log panel (`Ctrl/Cmd + ``).

4. Workspaces

Workspaces let you maintain completely separate sets of collections, environments, and settings — ideal for separating work projects, clients, or personal experiments.

Creating a Workspace

  1. Click the workspace name in the top-left header.
  2. Choose Manage Workspaces.
  3. Click + New Workspace and enter a name.
  4. Click the workspace name to make it active.

Switching Workspaces

Click the workspace name in the header and select another workspace from the dropdown. All sidebar content (collections, history) refreshes instantly.

Tip: GitHub Sync backs up all workspaces together, so data from every workspace is preserved.


5. Collections & Folders

Collections sidebar

Collections are the primary way to organise and save your API requests. A collection can contain both requests and folders (with unlimited nesting depth).

Creating a Collection

  1. Click the + button at the top of the sidebar.
  2. Enter a collection name and press Enter.

Creating a Folder

  1. Right-click an existing collection or folder.
  2. Select New Folder.
  3. Enter a folder name.

Creating a Request

  • From scratch: Click the + button on the sidebar toolbar, or right-click a collection / folder and choose New Request.
  • From an open tab: After building a request, press Ctrl/Cmd + S or click More → Save.

Context Menu Actions

Right-click any collection, folder, or request for quick access to:

ActionDescription
RenameEdit the name inline
DuplicateClone the item with all settings
DeleteRemove permanently
Move to…Relocate to another collection or folder
ExportDownload as JSON
Copy as cURLGenerate a cURL command for the request
Add to FavoritesPin collection to the top of the list

Searching Collections

Use the Search collections box at the top of the sidebar to filter requests by name or URL in real time.


6. Building & Sending Requests

Request builder

Opening a Request

Click any request in the sidebar to open it in a new tab. Each tab is independent and can be sent, modified, and saved without affecting other open tabs.

Request Toolbar

The toolbar at the top of the request panel contains:

ElementDescription
Method selectorChoose GET, POST, PUT, PATCH, DELETE, HEAD, or OPTIONS (colour-coded)
URL barEnter the full URL; supports {{variableName}} substitution
SendExecute the request (Ctrl/Cmd + Enter)
More ▾Access Save, Generate Code, View Variables

Query Parameters (Params Tab)

The Params tab displays all query parameters in a key-value table:

  • Enable/disable individual parameters with the checkbox.
  • Click + Add Param to add a new row.
  • Toggle Bulk Edit for a raw key=value text editor.
  • Parameters are automatically appended to the URL.
# Example: URL with parameters
https://api.example.com/users?page=1&limit=20

Headers Tab

Add any custom HTTP headers:

  • Enable/disable individual headers with the checkbox.
  • Common headers like Content-Type and Authorization are set automatically by the Body and Auth configuration.
  • Toggle Bulk Edit to paste multiple headers as text.

Environment Variable Substitution

Use {{variableName}} anywhere in the URL, headers, or body to inject values from the active environment:

URL:     https://{{baseUrl}}/api/v1/users
Header:  Authorization: Bearer {{apiToken}}
Body:    { "userId": "{{currentUserId}}" }

7. Request Body

Request body — JSON editor

Select the Body tab in the request panel to configure the request payload.

Body Types

TypeUse case
NoneGET, HEAD, and DELETE requests with no body
raw → JSONSend a JSON payload (sets Content-Type: application/json)
raw → TextPlain text, HTML, or XML payloads
form-dataMultipart form uploads including file attachments
x-www-form-urlencodedClassic HTML form submissions
BinaryUpload a raw file from disk

JSON Editor Features

When using raw → JSON, the built-in CodeMirror editor provides:

  • Syntax highlighting with bracket matching.
  • Auto format — click the format button to pretty-print the JSON instantly.
  • Wrap lines — toggle for long-line visibility.
  • Line numbers on the left gutter.

Sending a File

  1. Select form-data body type.
  2. Click + Add Param.
  3. Set the key name.
  4. In the value column, click the file icon to browse and attach a file.

8. Authentication

Auth type selector

The Auth tab provides built-in support for all common authentication schemes. Curlex sets the appropriate Authorization header automatically — you never need to construct it manually.

Supported Auth Types

None

No authentication header is added. Use for public endpoints.

Inherit

The request inherits the authentication configured on its parent collection. This is the recommended default — set auth once on the collection and all requests inherit it automatically.

Basic Auth

Encodes username:password as Base64 and sends it as:

Authorization: Basic <base64>

Fields:

  • Username — Supports {{variable}} substitution
  • Password — Stored securely in the OS keychain when persistence is enabled

Bearer Token

Bearer token form

Sends the token in the Authorization header:

Authorization: Bearer <token>

Paste your JWT or OAuth access token in the Token field. The textarea supports multi-line tokens.

API Key

Sends an arbitrary key-value pair either as a header or as a query parameter:

FieldExample
KeyX-API-Key
Valuesk-abc123...
Add toHeader or Query Params

OAuth 1.0

Generates a valid OAuth 1.0 signature and appends it to the request.

Required fields:

  • Consumer Key & Consumer Secret
  • Access Token & Token Secret
  • Signature Method: HMAC-SHA1, HMAC-SHA256, or PLAINTEXT

OAuth 2.0

Sends an access token with configurable token type and header prefix.

Fields:

  • Access Token — Paste the token directly
  • Token Type — Bearer (default) or MAC
  • Header Prefix — Customise the prefix (default: Bearer)

Supported Grant Types (configured via the advanced OAuth 2.0 flow form):

Grant TypeDescription
Authorization CodeStandard server-side flow
Authorization Code + PKCEMobile/SPA flow with S256 or plain code challenge
Client CredentialsServer-to-server authentication
PasswordResource owner password flow
ImplicitLegacy browser-based flow

9. Pre-Request & Test Scripts

Scripts panel

Curlex includes a JavaScript scripting engine that runs before and after each request. The API is compatible with the Postman pm API.

Pre-Request Scripts

Pre-request scripts run before the request is sent. Use them to:

  • Dynamically generate tokens or timestamps.
  • Set environment variables that will be substituted in the request.
  • Modify request parameters programmatically.
// Set a timestamp variable before sending
fc.environment.set('timestamp', Date.now());

// Generate a random UUID
fc.environment.set('requestId', crypto.randomUUID());

Test Scripts

Test scripts run after the response is received. Use them to:

  • Assert that the response matches expectations.
  • Extract values from the response and store them for subsequent requests.
  • Validate headers, status codes, and body content.

Scripting API Reference

fc.test(name, fn)

Define a named test case with assertions inside.

fc.test("Status code is 200", function () {
    fc.response.to.have.status(200);
});

fc.expect(value) — Chai-style BDD assertions

fc.expect(value).to.equal(expected);         // Strict equality
fc.expect(value).to.eql(expected);           // Deep equality
fc.expect(value).to.include(substring);
fc.expect(value).to.be.true;
fc.expect(value).to.be.above(number);
fc.expect(value).to.be.below(number);
fc.expect(value).to.be.oneOf([...values]);
fc.expect(array).to.have.length(n);
fc.expect(object).to.have.property("key");
fc.expect(object).to.have.nested.property("a.b.c");
fc.expect(value).not.to.equal(other);        // Negation

fc.response — Access response data

Property / MethodDescription
fc.response.codeHTTP status code (number)
fc.response.statusHTTP status text (string)
fc.response.responseTimeDuration in milliseconds
fc.response.text()Response body as string
fc.response.json()Response body parsed as JSON
fc.response.headers.get("Name")Get a response header value

Response assertion shorthands

fc.response.to.have.status(200);
fc.response.to.have.status("OK");
fc.response.to.have.header("Content-Type");
fc.response.to.have.header("Content-Type", "application/json");
fc.response.to.have.body("expected text");
fc.response.to.be.ok;          // 2xx
fc.response.to.be.serverError; // 5xx

fc.environment — Read and write environment variables

var baseUrl = fc.environment.get("baseUrl");
fc.environment.set("authToken", "new-token-value");

fc.collectionVariables — Collection-scoped variables

var token = fc.collectionVariables.get("auth_token");
fc.collectionVariables.set("auth_token", responseToken);

Complete Script Example

// 1. Make a login request and store the token for other requests
fc.test("Login succeeds", function () {
    fc.expect(fc.response.code).to.equal(200);
});

fc.test("Token is present in response", function () {
    var json = fc.response.json();
    fc.expect(json).to.have.property("token");
    // Store for subsequent requests
    fc.environment.set("authToken", json.token);
});

fc.test("Response time is acceptable", function () {
    fc.expect(fc.response.responseTime).to.be.below(2000);
});

10. Environment Variables

Environment manager

Environments let you define sets of variables (such as base URLs or API keys) and switch between them without modifying your requests. This is essential for testing against Development, Staging, and Production APIs.

Opening the Environment Manager

  • Click the Environments icon (🌍) in the sidebar rail.
  • Or press Ctrl/Cmd + E.

Creating an Environment

  1. In the left panel of the Environment Manager, type a name in the New environment name field.
  2. Click the + button to create it.
  3. The new environment opens in the right panel for editing.

Adding Variables

  1. Select an environment from the left list.
  2. Click + Add Variables to add a row.
  3. Enter the Key and Value.
  4. Use the checkbox to enable or disable a variable without deleting it.
  5. Changes are saved automatically.
# Example environment variables
baseUrl       = https://dev.api.example.com
apiKey        = dev-secret-key-abc123
timeout       = 5000

Activating an Environment

Click the environment name in the left panel; the active environment is marked with an Active badge. Only one environment can be active at a time.

Using Variables in Requests

Wrap the variable name in double curly braces anywhere in the request:

# URL
https://{{baseUrl}}/api/v1/users

# Header value
Authorization: Bearer {{apiKey}}

# Body
{ "source": "{{environment}}", "timeout": {{timeout}} }

Switching Environments Instantly

In the tab bar, click the environment badge (top-right of the main content area) to switch the active environment. All open tabs immediately use the new variable set.


11. Response Panel

After sending a request, the response panel populates below (or beside) the request panel depending on your layout setting.

Response Metadata Bar

Displays at a glance:

IndicatorMeaning
Status codee.g. 200 OK (green), 404 Not Found (orange), 500 (red)
TimeTotal response time in milliseconds
SizeResponse body size in KB

Response Tabs

Body

The default view. Curlex auto-detects the content type and renders it appropriately:

Content TypeRendering
JSONPretty-printed tree view with expand/collapse, JSONPath filtering, copy-to-clipboard
XML / HTMLSyntax-highlighted code view
ImagesInline preview (PNG, JPEG, GIF, SVG, WebP)
PDFInline PDF viewer
Audio / VideoMedia player with controls
BinaryHex/raw inspection view

JSON-specific controls:

  • Pretty / Raw toggle — switch between formatted tree and raw text.
  • 🔍 JSONPath filter — type a JSONPath expression (e.g. $.data[*].name) to extract and display matching values only.
  • Copy — copy the full response body to the clipboard.
  • Wrap lines — toggle word-wrap for long lines.

Headers

A table of all response headers with their values. Click any value to copy it.

Cookies

Displays cookies received in Set-Cookie response headers with full attributes: Name, Value, Domain, Path, Expires, HttpOnly, Secure.

Timeline

Visualises the full request lifecycle and HTTP redirect chain:

  • Each redirect hop shown with its status code and URL.
  • Per-hop timing: DNS lookup, TCP connection, TLS handshake, Time to First Byte (TTFB), Download.
  • Total timing waterfall for the complete request.

Tests

If a Test Script was configured for the request, results appear here after the response is received:

  • Green — test passed
  • Red — test failed (with error message)
  • Total pass/fail count summary

12. Request History

History panel

Curlex automatically records every request you send in a chronological history.

Accessing History

Click the History icon (🕐) in the sidebar rail.

Using History

  • Search — Use the search box to filter history by request name or URL.
  • Open — Click any history entry to open the full request in a new tab.
  • Right-click — Context menu with options to open in a new tab or copy as cURL.

History Details

Each entry shows:

  • Request name (or URL if unnamed)
  • HTTP method with colour coding
  • Timestamp of when the request was sent

Tip: History is workspace-scoped. Switching workspaces shows only that workspace's history.


13. Collection Runner

Collection Runner

The Collection Runner executes all requests in a collection sequentially, records results, and optionally retries failed requests — ideal for smoke testing, regression testing, and API monitoring.

Accessing the Collection Runner

Click the ▶️ Collection Runner icon in the sidebar rail.

Running a Collection

Step 1 — Select a Collection

Choose a collection from the Collection dropdown. All collections in the active workspace are listed.

Step 2 — Configure Run Sequence (Optional)

Click Configure Run to open the sequence panel:

  • Checkboxes — enable or disable individual requests.
  • Drag handles — reorder requests via drag-and-drop.
  • By default all requests are selected in their original order.

Step 3 — Select an Environment (Optional)

Choose an environment from the Environment dropdown to substitute {{variables}} in requests. Select No Environment to run without variables.

Step 4 — Configure Run Options

Click the Options expander for advanced settings:

OptionDefaultDescription
Delay Between Requests0 msPause between each request (useful for rate-limited APIs)
Retry Failed Requests0Number of retry attempts for non-2xx responses
Retry Delay1000 msWait between retry attempts
Stop on First FailureOffHalt the entire run on the first failed request

Step 5 — Run

Click the Run button. The button shows a spinning animation while executing. A toast notification appears when the run starts and when it completes.

Step 6 — Stop (Optional)

Click Stop at any time to halt execution. The run is marked as stopped in the history.

Reading Results

Left panel — Run History

Each run entry displays:

  • Collection name
  • Environment used
  • ✅ count of successful requests (2xx)
  • ❌ count of failed requests (non-2xx)
  • ⏱ total execution time

A ⏹ stop icon appears for manually stopped runs.

Right panel — Run Details

Selecting a run from history shows:

Summary bar:

  • Total requests, passed (green), failed (red)
  • Total time and total data transferred

Results table:

ColumnDescription
MethodHTTP method with colour coding
RequestName and URL
StatusHTTP status code + ✅/❌ indicator
TimeResponse time in ms
SizeResponse size in KB

Exporting Results to PDF

  1. Hover over a completed run in the history panel.
  2. Click the 📥 Download icon.
  3. A PDF report is saved containing: run metadata, configuration, summary statistics, and per-request details.

Request Execution Order

  1. All root-level requests in the collection (top to bottom)
  2. All requests in the first folder (depth-first, recursively)
  3. Subsequent folders in order

Using Test Scripts with the Runner

Test scripts attached to individual requests are executed after each response. Results are shown in the Tests column of the results table and in the console.


14. Import & Export

Import dialog

Importing Requests and Collections

Click Import in the header bar. Curlex supports four import formats:

cURL

Paste a cURL command to instantly create a request with the correct method, URL, headers, and body:

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer mytoken" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

After pasting:

  1. Edit the auto-generated Request name.
  2. Select an existing Target collection or create a new one.
  3. Click Import.

OpenAPI

Import an OpenAPI 3.x or Swagger 2.x specification. Curlex generates a complete collection with one request per endpoint, grouped by tags.

Postman

Import a Postman Collection (v2.0 / v2.1 JSON export). All requests, folders, headers, bodies, and auth settings are preserved.

Curlex

Import a previously exported Curlex collection JSON file.


Exporting Collections

Right-click any collection or folder in the sidebar and select Export. A JSON file is downloaded that can be re-imported into Curlex or shared with team members.

Copy as cURL

Right-click any request and select Copy as cURL to get a ready-to-run terminal command that mirrors the exact request (method, URL, headers, body, and auth).

Code Generation

In the request toolbar, click More → Generate Code to generate equivalent code in:

  • cURL
  • JavaScript (Fetch / Axios)
  • Python (requests)
  • …and more languages

15. Console

Console panel

The Console displays detailed logs for every request and response — essential for debugging auth issues, redirect chains, and script errors.

Opening the Console

  • Click the Console button in the status bar (bottom-right).
  • Or press `Ctrl/Cmd + ``.

Console Log Levels

LevelColourTypical Content
INFOBlueRequest dispatched, response received
WARNYellowRedirects, deprecation notices
ERRORRedNetwork errors, script exceptions
TRACEGreyLow-level timing and TLS details

Console Toolbar

ButtonAction
🗑 ClearRemove all log entries
📋 CopyCopy all logs to clipboard
💾 DownloadSave logs as a .log file
🔽 FilterShow/hide log level filter panel
✕ CloseHide the console panel

Tip: When using the Collection Runner, keep the console open to see per-request details including timing, headers, and any script console.log() output.


16. GitHub Sync

GitHub Sync lets you back up your entire Curlex workspace to a private GitHub repository and synchronise data across multiple machines.

Security note: Always use a private repository. Your collections may contain sensitive API keys and tokens.

Setup

Step 1 — Create a GitHub Personal Access Token (PAT)

  1. Go to GitHub Settings → Tokens.
  2. Click Generate new token (classic).
  3. Give it a name (e.g. Curlex Sync).
  4. Select the repo scope.
  5. Set an expiry date (90 days recommended).
  6. Click Generate token and copy it immediately.

Step 2 — Create a Private Repository

  1. On GitHub, create a new private repository (e.g. curlex-backup).

Step 3 — Configure in Curlex

  1. Open Settings → Git Sync (Ctrl/Cmd + ,).
  2. Paste your PAT and click Store (stored securely in the OS keychain).
  3. Enter:
    • Repository Owner — your GitHub username or organisation
    • Repository Name — the repository name
    • Branch — default main
    • Sync Format — Multi-File (recommended) or Single File (legacy)
  4. Click Test Connection to verify.
  5. Enable the GitHub Sync toggle.

Sync Triggers

TriggerDescription
On saveAny collection, environment, or workspace change triggers sync after a 5-second debounce
ManualClick the Sync button in the header toolbar
On startupCurlex pulls the latest data from GitHub when the app opens

Sync Data Structure

.curlex/
  ├── manifest.json       # File index and sync timestamps
  ├── collections.json    # All collections
  ├── environments.json   # All environments
  ├── tabs.json           # Open tab state
  ├── workspaces.json     # Workspace definitions
  └── settings.json       # App settings

Single-File Format (Legacy)

curlex-data.json         # All data in one file

Recommendation: Use Multi-File format. It avoids GitHub's 100 MB file limit and scales better as your collections grow.

Conflict Resolution

Curlex uses a last-write-wins strategy: whichever device syncs last overwrites earlier data. Sync manually before switching devices to avoid data loss.

For full details, see the GitHub Sync documentation.


17. Settings

Open Settings with the ⚙️ icon in the sidebar rail or press Ctrl/Cmd + ,.

Settings — General

General

SettingOptionsDescription
ThemeDark / LightApplication colour scheme
Two-pane ViewVertical / HorizontalLayout of request/response panels
Request Timeoutms (0 = never)Maximum time to wait for a response
Discard unsaved changesOn / OffSkip the "save?" prompt when closing a tab
Font FamilyAny font nameEditor font (applies to all code panes)
Font Size8–36 pxEditor font size
Send no-cache headerOn / OffAdds Cache-Control: no-cache and Pragma: no-cache
Send UUID correlation IDOn / OffAppends Curlex-Correlation-ID: <uuid> to every request
Follow redirectsOn / OffAutomatically follow HTTP redirects
Max redirectsNumber (0 = unlimited)Redirect depth limit

Data

Manage local data: export all data, import a backup, or wipe data to start fresh.

Git Sync

Configure GitHub Sync credentials and repository settings. See Section 16 for full instructions.

Certificates

Manage client TLS certificates on a per-domain basis. Upload .pem / .p12 certificates for mutual TLS (mTLS) APIs.

Logging

Control log verbosity:

  • Log level — INFO, WARN, ERROR, TRACE
  • Log requests — Include full request/response detail in logs

Shortcuts

Keyboard shortcuts reference

Visual reference for all keyboard shortcuts. See Section 18 for the full table.

About

Displays the Curlex version number and a brief description.


18. Keyboard Shortcuts

Keyboard shortcuts

ActionmacOSWindows / Linux
Send request⌘ EnterCtrl Enter
Save request⌘ SCtrl S
Close tab⌘ WCtrl W
Close all tabs⌘ ⇧ WCtrl Shift W
Import⌘ OCtrl O
Manage Environments⌘ ECtrl E
Open Settings⌘ ,Ctrl ,
Toggle Console`⌘ ```Ctrl ``
Open in new tab⌘ ⇧ EnterCtrl Shift Enter
Find in Response⌘ FCtrl F

Curlex includes a persistent cookie jar that stores cookies set by API responses (via Set-Cookie headers). Cookies are:

  • Stored per domain automatically.
  • Sent with subsequent requests to the same domain.
  • Viewable and editable via Status Bar → Cookies.

The cookie jar uses tough-cookie for RFC-compliant cookie handling, including Secure, HttpOnly, SameSite, and expiry attributes.


Appendix B — Troubleshooting

ProblemLikely CauseSolution
Request hangs indefinitelyTimeout set to 0 / server not respondingSet a timeout in Settings → General or verify the server is running
Variables not substitutedNo active environment / typo in variable nameCheck Environments panel; variable name must match exactly (case-sensitive)
Test scripts not runningScripts tab empty or syntax errorOpen the Scripts tab and check for JavaScript errors in the Console
GitHub Sync failingInvalid PAT / wrong repo nameRun Test Connection in Settings → Git Sync; verify PAT has repo scope
Certificate errorSelf-signed cert / mTLS requiredAdd the certificate in Settings → Certificates
Response body emptyServer returned 204 or HEAD methodExpected behaviour; no body for 204 No Content or HEAD responses

Appendix C — Data Storage

All Curlex data is stored locally on your machine:

DataStorage
Collections, environments, workspaces, settingsIndexedDB (browser storage inside the desktop webview)
GitHub PAT and other secretsOS keychain (macOS Keychain / Windows Credential Manager / Linux libsecret)
Large response bodiesLocal filesystem via desktop artifact service
LogsIn-memory (cleared on restart unless downloaded)

No data is ever sent to Curlex servers. The only external network calls made by the application are:

  1. Your own API requests.
  2. GitHub API calls when GitHub Sync is enabled.

Curlex is open-source software. Contributions, bug reports, and feature requests are welcome on GitHub.