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 (defaultbalanced).--fetch-registry— download & statically scan the real code behindnpx/uvxservers. 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 (defaultbalanced): which risk bands become Block / Ask / Allow, and the proxy's inspection level when--liveis 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 behindnpx/uvxservers 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
- Every config file is checksummed and backed up before the first rewrite.
- 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. - 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.
- Malicious skills — and project-scoped instruction files (
.cursorrules,GEMINI.md, a projectCLAUDE.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. 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 range —
min_affected/max_affected/ an explicitaffectedlist /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 likenpx -y foo@1.2.3is 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 handshake —
initialize,tools/list,resources/list,prompts/listresponses 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/lista 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 results —
tools/callandresources/readresults (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.
| Level | Poisoned handshake / rug pull | Poisoned tool result |
|---|---|---|
quiet | log the finding, forward unchanged | log, forward unchanged |
balanced | replace the response with a JSON-RPC error (-32001) — the agent never sees the poisoned content; session continues | log the finding, forward unchanged (a real result often contains phrases that trip a detector) |
strict | replace the response, then end the session | redact — 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:
| Action | Effect |
|---|---|
allow | forward the message and skip the built-in scan for it |
warn | log it, keep checking |
redact | replace each matched string with a marker, forward the rest |
block | the 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=1in the agent's environment — a hard per-launch kill switch; the shim does a plainexecand 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
| Variable | Effect |
|---|---|
TALYX_LICENSE_KEY | Validate against this key without consuming an activation slot — for CI. Set it in the job environment. |
TALYX_STORE | Path to the decision store (default ~/.talyx/decisions.json). The tool baseline is written as a sibling tool_baselines.json. |
TALYX_LICENSE_FILE | Path to the cached license (default ~/.talyx/license.json). |
TALYX_REGISTRY_CACHE | Directory 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_LEVEL | quiet | balanced | strict — the live proxy's inspection level (default balanced). |
TALYX_PROXY_LOG | Path to write a full classified JSON-RPC transcript of a proxied session (debugging). |
TALYX_SESSIONS_DIR | Directory for the proxy's findings log (default ~/.talyx/sessions/). |
TALYX_GUARDRAILS | Path to the guardrails file, overriding the ~/.talyx/ and <project>/.talyx/ defaults. |
TALYX_ADVISORIES | Path to an advisory feed file, overriding the bundled one and ~/.talyx/advisories.json. See The advisory feed. |
TALYX_ADVISORIES_URL | Feed 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 byscan/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-backupnext to each agent config the first timeinitrewrites it.
Changelog
Unreleased
- Live traffic inspection (opt-in).
talyx init --livekeeps 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 allowreverses any of it. talyx activate/licensecommands.