Skip to content
Lifetime license: $99, paid once. No subscription, no renewals. Get it →

Documentation

Install the binary, activate your license, scan. Everything runs on your machine.

Quickstart

Three commands from nothing to protected:

# 1 · install (macOS / Linux)
curl -fsSL https://gettalyx.dev/install.sh | sh

# 2 · activate the license from your purchase email
talyx activate <YOUR-LICENSE-KEY>

# 3 · scan this project + your user-level agent config
talyx scan --project .

When you're ready to enforce, run talyx init --project ~. That's the only command that writes to an agent config, and it backs each one up first.

Install

macOS / Linux

curl -fsSL https://gettalyx.dev/install.sh | sh

Installs talyx and talyx-shim to ~/.talyx/bin. It does not touch your shell profile unless you pass --modify-path.

Windows (PowerShell)

irm https://gettalyx.dev/install.ps1 | iex

npm

npm install -g talyx

From source

git clone https://github.com/rynald0cst0ltziam/talyx
cd talyx
cargo build --release
./target/release/talyx --help

Activate a license

Talyx is a paid tool with a lifetime license. After purchase you receive a key by email (it is also on your Lemon Squeezy order page) in the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Activate it once per machine:

talyx activate <YOUR-LICENSE-KEY>

This makes one HTTPS call to Lemon Squeezy to bind the key to this machine, then writes ~/.talyx/license.json. You can activate on up to 3 machines. To free a slot:

talyx license deactivate     # release this machine's slot
talyx license status         # show machines used, key status, offline grace

scan and status run without a license so you can evaluate. init requires an active license. The enforcement shim never checks one, so protection you have already set up keeps working.

Commands

talyx scan

Discover, score and report every artifact. Read-only.

  • --project <path> — project root to scan (default .). User-level config is always included.
  • --level quiet|balanced|strict — how aggressively to flag (default balanced).
  • --fetch-registry — download & statically scan the real code behind npx/uvx servers. Opt-in; makes outbound registry calls.
  • --format text|sarif, --sarif-file <path>, --exit-code — CI output.

talyx status

One-screen summary: agents detected, artifact counts, what needs review.

talyx init

Scans, caches your decisions, and rewrites configs so approved MCP servers launch through the shim and blocked ones are removed. The only mutating command. Requires a license.

  • --project <path> — project root (default .). Only configs inside it are rewritten unless you add --include-user-config.
  • --level quiet|balanced|strict — decision preset (default balanced): which risk bands become Block / Ask / Allow, and the proxy's inspection level when --live is set.
  • --include-user-config — also rewrite configs outside the project (e.g. ~/.claude.json, ~/.cursor/mcp.json). A user-level config affects every project, so this is opt-in.
  • --fetch-registry — download & statically scan the real code behind npx/uvx servers before enforcing (outbound registry calls).
  • --live — also keep the shim between the agent and each approved MCP server for the session and inspect its JSON-RPC traffic. See Live traffic inspection.
  • --store <path> — override the decision store location.

talyx allow <id>

Approve an artifact flagged ASK/BLOCK — from now on the shim lets it run and a removed remote entry is restored to the config exactly as it was. --store <path> to point at a non-default store.

talyx why <id>

Full reasoning behind a cached decision — every capability, every score contribution, the band and the final decision.

talyx guardrails check|list|example

Validate the live-proxy guardrails file, list the rules it would load, or print a commented starter. See Guardrails.

talyx advisories list|check|refresh

Inspect the known-bad advisory feed. list prints every advisory (id, severity, detail, references). check <package> [--version <v>] [--registry npm|pypi] tests one package name against the feed and exits non-zero on a match. refresh [--url <u>] downloads a newer feed over HTTPS and writes it to ~/.talyx/advisories.json (validated first — a bad download never overwrites the local file); the copy bundled in the binary is never touched. See The advisory feed.

talyx activate <key> · talyx license status|deactivate

See Activate a license.

How enforcement works

  1. Every config file is checksummed and backed up before the first rewrite.
  2. Approved servers get their launch command rewritten to call talyx-shim <id> -- <original command>. The shim re-checks the cached decision, then execs the real server.
  3. Blocked local servers get the same treatment but the shim refuses to exec. Blocked remote servers are removed from the config entirely and their original entry is stored.
  4. Malicious skills — and project-scoped instruction files (.cursorrules, GEMINI.md, a project CLAUDE.md) with a prompt-injection or exfiltration directive in them — are moved into a .talyx-quarantine/ directory next to where the agent looks for them, so it stops loading them. Your own user-level instruction files are scored and reported but never moved unless you pass --include-user-config.
  5. talyx allow <id> or restoring from the backup reverses any of this. Your real secrets and hook commands are never written into a rewritten file.

The advisory feed

Most detections score an artifact on its behaviour — what the code does, what the text says. The advisory feed adds the other half: artifacts the security community has already disclosed as malicious or vulnerable, matched by identity, not behaviour.

It ships as a small, hand-curated file compiled into the binary. Every entry carries at least one public reference URL. Matchers:

  • npm / PyPI package + version rangemin_affected / max_affected / an explicit affected list / fixed. The version is conservative: an unknown or dist-tag version (foo@latest) still flags unless it is provably at or past the fixed version. A spec like npx -y foo@1.2.3 is split so the bare name matches and the pin drives the range check.
  • npm publisher — every package from a named account.
  • npm name pattern — a regex, for typosquat shapes.
  • remote host — a registrable host for a remote MCP server.
  • source-repo owner (+ optional repo name).

A malicious match adds a decisive penalty, suppresses any reputation discount (a trust-seeded publisher in the known-bad list means the account or package is compromised) and forces a block. An advisory match — a CVE fixed in a later version, a review-before-use pattern — forces at least a review (ASK), whatever the protection level's band mapping would otherwise say.

Inspect and test it:

talyx advisories list
talyx advisories check postmark-mcp --version 1.0.17   # exits 1 — match
talyx advisories check mcp-remote --version 0.1.20      # exits 0 — clear

It works fully offline. To pull a newer copy, run talyx advisories refresh — it downloads over HTTPS, validates the feed (a malformed or unreachable download never overwrites your local file), and writes ~/.talyx/advisories.json, which scan and init then prefer over the bundled copy. You can also just drop a file there yourself, or point TALYX_ADVISORIES at one. Delete it to fall back to the feed compiled into the binary. The format is versioned and documented in the repo's data/advisories.json.

Live traffic inspection

The launch-time scan checks an MCP server before it starts. It can't see a server that behaves at launch and turns malicious mid-session, a tool definition that's swapped after you approved it, or a tool result crafted to steer the model. talyx init --live closes that gap: the shim stays between the agent and each approved server for the whole session and inspects every JSON-RPC message.

It is opt-in while it builds real-session mileage, and it fails open — if the proxy ever hits an internal error it falls back to exactly the launch-time protection you'd have without --live (the blocked-server config removal still stands). It never leaves you worse off than the gate alone.

Turn it on

talyx init --project ~ --live
# or at a specific level:
talyx init --project ~ --live --level strict

This writes talyx-shim <id> --proxy -- <command> into the config instead of the plain shim form. Running plain talyx init again downgrades those entries back in place; both directions are idempotent. Restart your agent after either.

What it inspects

  • The handshakeinitialize, tools/list, resources/list, prompts/list responses are run through the same prompt-injection / hidden-Unicode / encoded-payload / exfil-directive detectors as a skill file, before the agent sees them.
  • Tool drift (trust-on-first-use) — the first clean tools/list a server serves becomes its baseline (~/.talyx/tool_baselines.json). A tool that appears, or whose description or input schema changes, mid-session is a rug pull and is flagged.
  • Tool resultstools/call and resources/read results (up to 64 KiB) are scanned for an injection payload smuggled back as "file contents".

Levels

Set with TALYX_PROXY_LEVEL (or inherited from init --live --level …). Default balanced.

LevelPoisoned handshake / rug pullPoisoned tool result
quietlog the finding, forward unchangedlog, forward unchanged
balancedreplace the response with a JSON-RPC error (-32001) — the agent never sees the poisoned content; session continueslog the finding, forward unchanged (a real result often contains phrases that trip a detector)
strictreplace the response, then end the sessionredact — each flagged text block becomes a marker; clean blocks and non-text content pass through

Guardrails — your own rules

The three levels are a blunt instrument. Guardrails are a local policy file — ~/.talyx/guardrails.yaml, <project>/.talyx/guardrails.yaml, or $TALYX_GUARDRAILS — that the proxy runs on every JSON-RPC message, in addition to the built-in detectors. Each rule matches by direction, method and one or more path conditions, and takes an action:

ActionEffect
allowforward the message and skip the built-in scan for it
warnlog it, keep checking
redactreplace each matched string with a marker, forward the rest
blockthe message never reaches its peer — a JSON-RPC error goes back to the sender (a blocked client tools/call → error to the agent, the server never sees it)
# ~/.talyx/guardrails.yaml
version: 1
rules:
  - name: block-secret-path-args
    direction: client-to-server
    method: tools/call
    any:
      - path: params.arguments.*
        contains: "/.ssh/"
      - path: params.arguments.*
        contains: "/.aws/"
    action: block
    message: "tool call argument references a credential path"

  - name: redact-aws-keys-from-results
    direction: server-to-client
    method: tools/call
    any:
      - path: "result.content[*].text"
        regex: "AKIA[0-9A-Z]+"
    action: redact

Path conditions use a dotted JSON path with * (any key) and [*] (any array element) wildcards, then one operator: contains, not_contains, regex, glob, equals, in, exists, gt, lt. Manage the file with:

talyx guardrails example > ~/.talyx/guardrails.yaml
talyx guardrails check      # validate — names the offending rule
talyx guardrails list       # show what the proxy would load

Turn it off

  • TALYX_NO_PROXY=1 in the agent's environment — a hard per-launch kill switch; the shim does a plain exec and the proxy code never runs.
  • talyx init --project ~ (no --live) — permanently downgrades the config entries.

What's recorded, and what leaves your machine

Nothing leaves your machine. Findings are appended to ~/.talyx/sessions/<date>-<pid>.jsonl (one JSON object per finding) and echoed to the server's stderr. talyx status prints a summary of recent ones. For debugging, TALYX_PROXY_LOG=/path/to/log.jsonl captures a full classified transcript of every message both directions.

Only messages up to 256 KiB are inspected before being forwarded; a larger message (a big tool result — file contents, command output) is forwarded first and only classified for the transcript afterwards, so the proxy adds no latency to bulk traffic. The proxy is the same process your agent already spawns for the server — there is no daemon.

Use in CI

Fail a build when a poisoned artifact lands in a PR:

# .github/workflows/talyx.yml
- run: talyx scan --project . --format sarif --sarif-file talyx.sarif --exit-code
- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: talyx.sarif
    category: talyx

--exit-code returns 2 on any Block/Quarantine, 1 on any Ask, 0 otherwise. In CI, activate with a machine license via TALYX_LICENSE_KEY in the job environment.

Offline & air-gapped

After activation, Talyx works offline for 30 days before it asks to re-verify. For fully air-gapped machines, enterprise licenses ship an offline activation file — email hello@gettalyx.dev.

Environment variables

VariableEffect
TALYX_LICENSE_KEYValidate against this key without consuming an activation slot — for CI. Set it in the job environment.
TALYX_STOREPath to the decision store (default ~/.talyx/decisions.json). The tool baseline is written as a sibling tool_baselines.json.
TALYX_LICENSE_FILEPath to the cached license (default ~/.talyx/license.json).
TALYX_REGISTRY_CACHEDirectory for --fetch-registry package downloads (default under ~/.talyx/).
TALYX_NO_PROXY=1 forces the shim to exec the real server directly even for a --live entry — a per-launch kill switch for the proxy.
TALYX_PROXY_LEVELquiet | balanced | strict — the live proxy's inspection level (default balanced).
TALYX_PROXY_LOGPath to write a full classified JSON-RPC transcript of a proxied session (debugging).
TALYX_SESSIONS_DIRDirectory for the proxy's findings log (default ~/.talyx/sessions/).
TALYX_GUARDRAILSPath to the guardrails file, overriding the ~/.talyx/ and <project>/.talyx/ defaults.
TALYX_ADVISORIESPath to an advisory feed file, overriding the bundled one and ~/.talyx/advisories.json. See The advisory feed.
TALYX_ADVISORIES_URLFeed URL for talyx advisories refresh (default: the advisories.json asset of the latest $TALYX_REPO release).
TALYX_DEV=1 skips the license gate — debug builds only, compiled out of release binaries. For working on Talyx itself.

Files Talyx writes

Everything lives under ~/.talyx/. Nothing is sent anywhere.

  • decisions.json — the decision cache: every scanned artifact's id, capabilities, score, band and decision. Written by scan/init, read by the shim.
  • tool_baselines.json — trust-on-first-use snapshot of each server's approved tool list (live proxy).
  • license.json — cached license status and the 7-day / 30-day trust timers.
  • sessions/<date>-<pid>.jsonl — live-proxy findings, one JSON object per line.
  • A .talyx-quarantine/ directory next to an agent's skills folder or a flagged instruction file — blocked skills and project-scoped instruction files are moved here (not under ~/.talyx/, so the move stays within the same repo and is easy to inspect / undo).
  • A <file>.talyx-backup next to each agent config the first time init rewrites it.

Changelog

Unreleased

  • Live traffic inspection (opt-in). talyx init --live keeps the shim between the agent and each approved MCP server for the session — handshake-response scanning, a trust-on-first-use tool baseline that catches a mid-session rug pull, tool-result scanning, and custom guardrail rules you write in a local YAML file (block / redact / allow, matched by JSON-path conditions). See Live traffic inspection.
  • Known-bad advisory feed. Confirmed-malicious and vulnerable MCP artifacts matched by identity (package + version range, publisher, host, repo owner, typosquat pattern) — bundled, offline, overridable, refreshable over HTTPS. Forces a block or a review regardless of behaviour score. talyx advisories list|check|refresh. See The advisory feed.
  • Tree-sitter AST + source-to-sink taint for JS/TS, Python and Ruby — function-scoped and interprocedural (follows a secret through helper returns and parameters to a network sink). Now the authoritative capability pass for those languages; the regex rules are the parse-failure fallback.
  • Plugin & extension ecosystems — Claude Code plugins, Gemini CLI extensions and Antigravity plugins: every enabled one's bundled MCP servers, hooks, skills, agents, LSP servers and monitors are discovered and scored.
  • Warp added (27 agents). ~/.warp/.mcp.json, flat-root shape.
  • Remote-code-execution detection for hooks and skill code blocks (curl … | sh, irm … | iex).
  • MCP tool-description poisoning detection; tool-shadowing & typosquat detection across all discovered servers.
  • SARIF 2.1.0 output + GitHub Action; capability-drift re-review.
  • Skill & instruction-file content analysis: prompt injection, invisible Unicode, encoded payloads, exfiltration directives — and a flagged, project-scoped instruction file (.cursorrules, GEMINI.md) is quarantined, not just reported.
  • Config-rewrite enforcement for every discovered agent, local and remote MCP servers; skills and repo-delivered instruction files quarantined; talyx allow reverses any of it.
  • talyx activate / license commands.

You audit your dependencies. Your agent doesn't.

Five minutes to install, one command to scan. Then every MCP server, plugin and skill your agents load is checked and gated — for a one-time $99, with a license that never expires.

Secure Lemon Squeezy checkout · 14-day refund · activate on 3 machines · scan free, forever