Skip to content

Latest commit

 

History

244 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

klura

Verified web data for agents — from a signed catalog, or built on demand.

Install a maintained tool for the site and call it. No tool yet? klura builds one from a real session, and it gets the same declared contract. It all runs on your machine.

npm version npm downloads Node.js TypeScript Discord License: BUSL-1.1

klura: install a catalog tool, call it, run it as a bounded collection; then hit a site the catalog lacks, build the tool, and get the same declared contract


What klura does

You want the top GitHub repositories matching "web scraping". Or every product on a search page. Normally that means writing a scraper, then rewriting it the next time the site changes.

klura skips that. Someone has already built and maintained a tool for the site, and you install it:

npm install -g @klura/runtime

klura install github
klura call github.search_repositories --input '{"query":"web scraping"}'

You get back structured data, checked against the shape the tool promised. Not HTML to parse.

search → inspect → install → call once, or run a bounded scrape

Not in the catalog? Point klura at the site. It drives a real session, records what the page actually does, and turns that into a tool with the same declared origins, request budget, and output shape as every catalog tool. You can use it locally right away, or export it and open a pull request; after review it is signed into the catalog for everyone. That is how the catalog grows — see Advanced authoring.

Two ways to use a tool. call does one read and hands you one verified result. run collects a bounded set into a file — it has hard limits on items, pages, requests, and time, and you can leave it running, check on it, cancel it, or resume it.

It runs on your machine. The tool, the browser, the traffic to the site, and the output all stay local. No account, no LLM key, nothing executing on someone else's server. Inside a company that counts twice: what you look up and what comes back never pass through a third-party scraping vendor, and there is no external service to put through procurement or a data-processing review.

Tools say what they will do before they do it. Every tool declares which domains it may reach, how many requests it may make, and what its output looks like. You can read all of that with klura show before installing. The runtime holds it to that declaration.

Nothing counts as success just because it returned. A 200 response, or an empty list, means nothing on its own — sites serve error pages and empty shells with a 200 all the time. The runtime only reports success when the data matches what the tool said it would return.

You pick the version. The catalog is a signed index hosted on GitHub. You choose what to install, and an installed tool never changes underneath you.

Companies can use it internally for free. klura is source-available under BUSL-1.1. Running it on your own machines and inside your company — including for ordinary commercial work — is covered by the Additional Use Grant at no cost, so a team can put it into production without a purchase. The line it draws is reselling: you may not offer klura to third parties as a hosted service or API, or build a competing service on it. Full terms in LICENSE; for a commercial license that lifts those limits, hello@klura.ai.


Quick Start  ·  Advanced Authoring  ·  LIFT  ·  Self-Healing  ·  Map Mode  ·  Benchmarks  ·  Under the Hood  ·  Use Cases  ·  Legal & ToS  ·  Docs  ·  Get Involved


Quick Start

CLI

npm install -g @klura/runtime

klura search products
klura show <package[.capability]>
klura install <package[@version]>
klura call <package.capability> --input '{"...":"..."}'
klura run <package.capability> --input '{"...":"..."}' --output results.ndjson

call returns one typed, verified read result. run writes a bounded local collection and can be detached, inspected, cancelled, or explicitly resumed under the exact installed package digest. klura factory --help is the separate advanced authoring surface; it is never entered automatically when a catalog search has no match.

MCP hosts

Klura also works with Codex, the ChatGPT desktop app, Claude Code, Claude Desktop, Cursor, Windsurf, OpenClaw, and other MCP hosts. The same server exposes the consumer tools first and discovery tools only for explicit authoring.

Codex / ChatGPT desktop

The Codex CLI, IDE extension, and ChatGPT desktop app share one MCP configuration:

codex mcp add klura -- npx -y @klura/mcp

Restart the host after registering.

Claude Code

The fastest path is the CLI:

claude mcp add klura -- npx -y @klura/mcp

That registers klura at user scope. To install per-project, drop it into .mcp.json at the repo root:

{
  "mcpServers": {
    "klura": {
      "command": "npx",
      "args": ["-y", "@klura/mcp"]
    }
  }
}

You can also edit ~/.claude.json directly, but claude mcp add is the supported path. After install, run claude mcp list to confirm klura is registered.

Claude Desktop, Cursor, Windsurf, OpenClaw

These hosts share the same MCP config shape. Drop the snippet into the host's MCP config file (e.g. claude_desktop_config.json for Claude Desktop) and restart the client:

{
  "mcpServers": {
    "klura": {
      "command": "npx",
      "args": ["-y", "@klura/mcp"]
    }
  }
}

From a local checkout (development)

If you're working on klura itself, link the local build into your global path so MCP hosts and the klura CLI both see your changes:

cd runtime
npm install
npm run build
npm link

After every code change, re-run npm run build and restart the daemon: klura restart-runtime --force (or pkill -f 'klura.*daemon').

Advanced: author or maintain a tool

When a maintained package does not exist and you explicitly want to author one, klura can run its discovery/factory workflow with an optional LLM provider:

npm install -g @klura/runtime @klura/agent-claude-code   # or @klura/agent-openai
klura chat
> message Adam in the team chat

klura chat is a REPL over the factory tools exposed through MCP. claude-code reuses your Claude Code login; openai supports OpenAI and compatible endpoints such as NVIDIA, Together, Groq, and vLLM:

klura chat --provider claude-code
klura chat --provider openai --model gpt-5

Settings live in the agent block of ~/.klura/config.json. For an OpenAI-compatible provider, set the API key there as agent.api_key — or, if you'd rather keep it out of the file (CI, shared machines), in the KLURA_AGENT_API_KEY environment variable. claude-code needs neither.

{
  "agent": {
    "provider": "openai",
    "model": "gpt-5",
    "base_url": "https://api.openai.com/v1",
    "api_key": "sk-...",
  },
}

Sessions are transcribed to ~/.klura/chat-logs/chat-<timestamp>.jsonl; opt out with agent.log_transcript: false or --no-transcript.

klura execute gets a self-healing mode. klura execute <platform> <capability> --agent runs the saved strategy with no LLM cost when it succeeds; if it fails, the LLM picks up the live session and re-drives to repair the strategy:

klura execute team-chat send_message --args '{"to":"Adam"}' --agent

External MCP hosts supply their own LLM. Standalone providers: @klura/agent-claude-code, @klura/agent-openai.


Advanced authoring: how it works

Browser agents are slow because they keep using the UI as the interface.

Klura treats the UI as a discovery step.

1. First run
   The agent uses the browser normally.

2. Capture
   Klura records traffic, cookies, page state, and action history.

3. Lift
   Klura analyzes the trace and learns the underlying request or script.

4. Later runs
   The saved strategy executes directly.

The saved output is not “agent memory.” It is executable strategy data built from the observed session.


LIFT

LIFT means Learn Interface From Traffic.

It is the analysis pass that turns a captured browser session into a reusable strategy.

Before LIFT:                    After LIFT:
  click button                    POST /api/messages
  wait for UI update              {"text": "hello"}
  read confirmation               ~200ms, 0 LLM tokens

Learn graph: drive the task in the browser, capture traffic, lift into a saved strategy

A saved fetch strategy looks like this:

{
  "strategy": "fetch",
  "method": "POST",
  "baseUrl": "https://chat.so",
  "endpoint": "/api/conversations/v1/send",
  "prerequisites": [
    {
      "kind": "capability",
      "capability": "list_conversations",
      "args": {
        "name": "{{recipient}}"
      },
      "vars": {
        "thread_id": "conversations[0].id"
      }
    }
  ],
  "body": {
    "to": "{{thread_id}}",
    "text": "{{text}}"
  },
  "auth": {
    "type": "session-cookie"
  }
}

On later runs, klura reads this strategy, resolves prerequisites, fills placeholders from the call arguments, and fires the request directly.

Strategies are saved as ordinary JSON files under:

~/.klura/skills/<platform>/

See REFERENCE.md for the full schema and REFERENCE.md#capability-prereq for prerequisite handling.


Strategy Tiers

Klura saves the simplest strategy that actually works.

Tier Strategy Used when
T0 fetch A direct HTTP or WebSocket call is enough
T1 page-script The page must run JavaScript to build, sign, or dispatch the request
T2 recorded-path The safest available path is replaying the UI

The tier reflects where the saved code runs:

  • fetch is a static templated HTTP call, fired from Node. Possible when every input — body, headers, tokens — can be reconstructed without the page.
  • page-script runs JavaScript inside the live, already-authenticated browser tab. It can call functions the site itself defines: request signers, header rotators, MQTT codecs, WebSocket encoders, the in-page fetch wrapper. That makes lift possible for sites where the real request only exists as the output of in-page code, with no way to reproduce it from outside.
  • recorded-path replays UI actions through the browser driver. Slower, but works when the request can't be cleanly isolated.

If a site cannot be lifted cleanly to fetch or page-script, klura still saves a recorded-path.

That is slower than a direct API call, but still avoids replanning the page from scratch. The same skill can later be re-lifted into a faster tier.


Self-Healing

Websites change. Endpoints move. Tokens rotate. Response shapes drift.

Klura treats those as repairable failures.

Execute graph: saved strategy fires; on stale-shape failure klura relearns and patches the strategy

When a saved strategy fails, klura classifies the failure:

Failure type What happens
Structural Klura returns a clear error the agent can act on
Stale strategy Klura routes back through capture and LIFT to patch the skill
Auth or session issue Klura asks for the minimum required human help

The goal is not silent retries. The goal is loud, structured failure and repair.


Map Mode

You do not need to start with a specific task.

Klura can scout a site first.

map this CRM with klura

The agent walks the surface area — pages, forms, settings, search, account flows — while klura records what it sees in a platform logbook.

Map graph: scout a platform and build a persistent logbook of pages and observed capabilities

The logbook lives under:

~/.klura/workdir/<platform>/

It stores things like:

  • URL graph nodes
  • form observations
  • observed capabilities
  • page notes
  • useful surface-area hints for future sessions

No strategy is saved in map mode. Mutating actions require explicit consent.

The next real task starts with klura already familiar with the platform.

See docs/logbook.md.


Why Klura Exists

The UI is the human layer over requests, tokens, state, and event streams. Klura captures that lower layer once and reuses it.

Browser agent Klura
First run Browser exploration Browser exploration + network capture
Learning step None Optional LIFT pass
Later runs Browser exploration again Saved strategy
Tokens Paid every run Paid once, then zero in runtime
Latency Seconds per UI step Direct strategy execution

The agent keeps judgment; the runtime takes over once execution becomes mechanical.


Benchmarks

Each live-site task runs once with raw Playwright and once with an empty klura skill directory. After discovery, the saved strategy is executed directly.1

Task Result requirement Plain browser agent2 klura cold3 Runtime replay4
IKEA stock availability Stock evidence for all four Berlin stores 2m 17s 9m 43s 1.14s
ASOS filtered search Five products plus both selected facets 1m 35s 6m 57s 67.9ms
Airbnb search Five Berlin stays with exact dates and guest count 2m 48s 13m 19s 2.17s
Amazon product search Top-three titles, prices, and ASINs/URLs 3m 05s 6m 52s 3.46s

ASOS replays with fetch; IKEA, Airbnb, and Amazon use page-script. Replay is the median of five sequential executions, all validated against the requested content rather than HTTP status alone.


Under the Hood

Klura is built around a few constraints:

  • Keep the LLM in charge of judgment.
  • Keep the runtime boring where possible.
  • Never silently accept broken strategies.
  • Prefer real observed traffic over guesses.
  • Fall back safely when a clean lift is not possible.

Runtime and Agent

The runtime provides tools, captures data, validates output, executes strategies, and handles recovery.

The agent performs the reasoning: deciding what task is being done, choosing capabilities, composing prerequisites, and resolving ambiguity.

There is no heavy workflow engine. Capability composition happens in the agent turn, where user context already lives.

Example:

message Bob in team chat

may compose:

list_conversations(name="Bob")
send_message(thread_id=..., text=...)

The runtime executes the saved pieces.

Audits

Every saved strategy passes a structural audit before it hits disk.

The audit checks for problems like:

  • dynamic values baked into static requests
  • missing arguments
  • missing auth assumptions
  • weak or non-generalized selectors
  • response-shape mismatches
  • unsafe endpoint behavior

Issues are batched into one rejection so the agent can fix everything in one retry.

Sessions Persist

Browser sessions persist between runs.

Cookies, login state, and storage stay warm because the daemon outlives any single conversation. A site that asks for 2FA once a week should not require login every time an agent starts a new task.

Token Refresh

Klura tracks estimated token lifetimes and refreshes before expiry when possible.

The goal is to avoid the common failure mode where long-running automation fails only after a CSRF token, nonce, or session value has already expired.

Network Stack Selection

Some sites work over plain Node fetch.

Others reject anything that does not look like the real browser stack.

Klura picks the execution path per request and can fall back to an in-browser path when needed.

Streams

Klura supports listener-style capabilities for push streams:

  • WebSocket
  • Server-Sent Events
  • polling feeds

Saved skills like on_new_message are first-class.

Human Handoff

Some interruptions need a human:

  • CAPTCHA
  • 2FA
  • “confirm this is you”
  • password prompts
  • account recovery walls

Klura opens a live viewer of the in-progress browser session. You solve the blocker, and the agent continues from the same state.

Password handling resolves in this order:

  1. remote viewer
  2. user-supplied shell command
  3. ask-in-chat as a last resort

See docs/remote.md and docs/interruptions.md.


Reverse Engineering Toolkit

Most sites are simple. Some are not.

For signed requests, binary protocols, minified encoders, rotating IDs, and hidden request builders, klura exposes deeper tools to the agent.

Examples:

  • find the request builder in bundled JavaScript
  • set breakpoints when a request fires
  • inspect signing functions from the live page
  • locate WebSocket encoders
  • compare binary payloads by structure instead of exact bytes
  • classify failed probes as getting closer, stuck, or oscillating

Klura can handle even the toughest sites, and could even one-shot Facebook Messenger's binary MQTT /ls_req send path, regenerating rotating BigInt fields and replaying the frame through the page's authenticated socket in 2.365s.

The runtime does not brute-force endpoints, enumerate IDs outside the user's scope, or fuzz inputs.

See docs/reverse-engineering.md.


Use Cases

Klura is useful when the task is repetitive, browser-based, and not well-served by a public API.

Good fits:

  • internal tools
  • legacy admin panels
  • SaaS products behind login
  • web apps with private APIs but no public API
  • repeated form submissions
  • customer support workflows
  • message sending
  • issue creation
  • CRM updates
  • dashboard reads
  • workflows that currently require brittle Playwright scripts

Bad fits:

  • one-off tasks
  • sites you are not authorized to use
  • high-scale scraping
  • endpoint or ID enumeration
  • tasks that violate platform policy
  • flows where the UI is intentionally the security boundary

What klura isn't

  • A scraping framework. Klura targets your own logged-in sessions, not unauthenticated pages at scale. If you're comparing it to Botasaurus, undetected-chromedriver, playwright-stealth, or Apify, that's a different category of tool.
  • Code you write. Strategies are reverse-engineered from one observed browser run by the LLM driving the session. There's no Python or JS script for you to author or maintain.
  • An anti-detect toolkit. Stealth fingerprint patches are supported; behavioral evasion (humanlike cursor jitter, residential proxies, CAPTCHA-solving services) isn't part of the mainline.

Model Variance and Reliability

Klura depends on the model driving it.

Discovery quality varies by model; saved strategies replay deterministically.

Current snapshot:

Model Status
GPT-5.6 Sol (gpt-5.6-sol) Very strong across ordinary and complex LIFTs
Sonnet 4.6 Strong across ordinary and complex LIFTs
GLM 4.7 Solid across most ordinary tasks

Legal & ToS

Klura drives a real browser session you are already logged into and replays the same kinds of calls your own UI makes on your own account.

That is generally on the authorized side of unauthorized-access law.

Platform Terms of Service are separate.

Many major platforms restrict automation. Whether your usage triggers enforcement depends on the platform and how you use klura.

Practical guidance:

  • read the policy of any site you automate
  • stay within your own account and authorization scope
  • avoid doing at scale what you would not reasonably do manually
  • do not enumerate endpoints
  • do not enumerate IDs outside your own scope
  • do not fuzz inputs
  • use klura's policy tools to cap strategy tiers per platform

See docs/policy.md, docs/trust.md, and docs/principles.md#stealth-not-bot-evasion.


Configuration

Runtime settings live in:

~/.klura/config.json

You can edit the file directly or ask your agent to use klura's configuration tools:

  • describe_config
  • configure
  • restart_runtime

A few knobs that are worth knowing about up front:

  • pool.driver (default unset → bundled Playwright driver) — switches the browser driver. Set to "@klura/driver-playwright-stealth" to enable stealth fingerprint patches (puppeteer-extra-plugin-stealth) for sites with stricter bot detection. BYO drivers can be installed by package name or absolute path.
  • pool.connect (default off) — drive a normally-launched Chrome over CDP instead of letting Playwright launch it. A Chrome launched the ordinary way clears managed browser challenges that a Playwright-launched one loops on forever — the tell is the launch profile, not the CDP connection. { "enabled": true, "mode": "spawn" } spawns a real Chrome with a persistent profile; "mode": "attach" connects to a Chrome you started with --remote-debugging-port. See docs/drivers.md#connect-mode.
  • remote.auto_open ("always" | "on_local" | "never", default "on_local") — when the remote viewer URL is reachable from the runtime host, klura spawns the OS URL handler so your default browser opens the viewer automatically. Skips the LLM-relay channel where long signed URLs tend to get a single byte garbled. Set to "never" for headless / SSH setups.
  • remote.short_url (boolean, default true) — surface a short single-use redirect URL (≈16 chars, 60s TTL) to the agent instead of the full JWT URL. Survives chat-renderer rewrites where the long URL doesn't.

See docs/run-lifecycle.md#settings-reference-kluraconfigjson and REFERENCE.md#configure.


Docs

Start here:


Get Involved

Klura is new and moving fast. If the idea resonates:

  • ⭐ Star the repo to follow along.
  • 💬 Join the Discord — discovery walkthroughs, what's breaking, what's next.
  • 🐛 Open an issue naming a site you wish your agent could just use. Real workflows drive what gets built.
  • 🔧 Contribute a driver, transport, prerequisite method, or validation improvement — see Contributing.

The single most useful thing you can do: point klura at the most annoying internal tool you have, watch run 1 versus run 2, and tell us what broke.


Built By

Narek Mailian — freelance engineer.

Klura is a standalone project.

Commercial licensing, strategic partnerships, or integration conversations:

hello@klura.ai


Contributing

Before opening a PR, skim docs/principles.md.

Contributions that fit especially well:

  • drivers
  • pool backends
  • listener transports
  • prerequisite methods
  • validation improvements
  • focused test fixtures
  • better docs for real workflows

Please avoid:

  • endpoint probing
  • ID enumeration outside the user's own scope
  • mainline bot-evasion features
  • platform-specific runtime heuristics
  • brand names in agent-facing docs

Contributors sign the klura Individual Contributor License Agreement before a PR can be merged.

Full text: CLA.md.


License

Business Source License 1.1 with an Additional Use Grant.

The Licensed Work converts to the Apache License, Version 2.0 on the Change Date specified in LICENSE.

See LICENSE and NOTICE for the full terms.

You may copy, modify, and use the Licensed Work freely for non-production use.

Production use is permitted under the Additional Use Grant, except that you may not:

  • offer the Licensed Work, in whole or in part, to third parties as a hosted or managed service;
  • expose the Licensed Work's functionality to third parties via an API, SDK, or other interface;
  • use the Licensed Work to build, offer, or operate a Competing Service; or
  • sublicense, sell, or resell access to the Licensed Work or its functionality.

For a commercial license that lifts these restrictions, contact:

hello@klura.ai

Footnotes

  1. All rows used GPT-5.6 Sol (gpt-5.6-sol) through Codex. ↩

  2. Agent-reported after the raw Playwright run completes without a blocker. ↩

  3. Klura cold time includes browsing, capture, triage, LIFT, validation, and saving the reusable strategy. It is the one-time learning cost. ↩

  4. klura.execute() with no agent SDK in the loop; median of five sequential calls. A conversational host still spends tokens deciding to make the call. ↩

About

Klura watches what the browser actually does — requests, responses, tokens — and turns it into a reusable API call.

Resources

Stars

60 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages