SLOPSHOPPER

enigma-relay

Hands a long Claude Code session to a fresh context: handoff, /clear, continue.

newtoast
A shopper browsing a rack in a slop shop
README

<img src="assets/logos/enigma-logo.svg" width="120" /> <h1>Enigma</h1> <h3>Ship better code with your coding agent.</h3> <img src="https://img.shields.io/badge/TypeScript-blue?style=for-the-badge&logo=typescript&logoColor=white"/> <a href="https://github.com/FJRG2007"> <img alt="GitHub" src="https://img.shields.io/badge/GitHub-purple?style=for-the-badge&logo=github&logoColor=white"/></a> <a href="https://ko-fi.com/fjrg2007"> <img alt="Kofi" src="https://img.shields.io/badge/Ko--fi-purple?style=for-the-badge&logo=ko-fi&logoColor=white"></a> <a href="https://fjrg2007.github.io/enigma/">Website</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="#install">Quickstart</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="https://fjrg2007.github.io/enigma/">Install</a> <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span> <a href="https://tpe.li/dsc">Discord</a> <hr />

enigma gives your coding agent a senior engineer's standards, in one command. It installs shared Dynamic Skills - security, testing, git, style, debugging - into Claude Code, OpenAI Codex, opencode and Kimi Code; each one adapts to the agent, re-renders from your config, and loads only when a task needs it. Portable git hooks keep secrets and .env files out of every commit, a local dashboard manages and measures the whole setup, and optional packs add focused harnesses - like the Helio bug-bounty toolkit - in their own isolated context. Fewer wrong turns, fewer re-prompts, cleaner output.

ENIGMA PREVIEW

Install

One command. It installs or updates the enigma command to the latest version, then runs enigma install interactively so you choose what to set up. Re-run it anytime to update:

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/FJRG2007/enigma/main/scripts/install.sh | sh

# Windows (PowerShell)
irm https://raw.githubusercontent.com/FJRG2007/enigma/main/scripts/install.ps1 | iex

Or one-shot, no global install, no prompts - deploy the skills to every supported agent at user level:

npx enigma-cli@latest install --all --yes

<table> <tr> <td width="50%">

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Dynamic Skills, everywhere

Senior-engineering policies (security, testing, git, style, debugging...) on Claude Code, OpenAI Codex, opencode and Kimi Code. Unlike a static skill, each one adapts to the agent, re-renders from your config, loads only when the task needs it, and updates itself. Discard any you don't want - it's gone everywhere until you restore it.

npx enigma-cli@latest install --all --yes

</td> <td width="50%">

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Git security hooks

A portable commit guard for any repo: blocks secrets, .env files and node_modules before they're committed. Set it up once; the whole team inherits it.

enigma security

</td> </tr> <tr> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Token-efficient output

Same answer, fewer tokens. Compress the agent's chat replies (off | lite | full | ultra):

Normal (69 tokens): "The reason your React component is re-rendering is likely because you're creating a new object reference on each render cycle..."

Ultra (19 tokens): "New object ref each render. Inline object prop = new ref = re-render. Wrap in useMemo."

</td> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Multi-account + profiles

Multiple logins per tool, each isolated, switched without logging out. Every account inherits your skills, memory and settings. Profiles pin one account per tool ("work" = claude:acme + codex:acme) and drive every launch.

enigma claude work
enigma profile use work

</td> </tr> <tr> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Auto-detect skills by stack

enigma autoskills reads your stack and installs the matching community skills - React, Next.js, Astro, Prisma, FastAPI, Rails and ~90 more - kept separate from the policy skills. --dry-run previews first.

enigma autoskills
enigma autoskills --dry-run

</td> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Built-in /improve command

A slash command on every agent. Implement mode edits a focused area (ui, security, performance, seo, refactor); advisor mode audits read-only and writes execution-ready plans for another agent to run.

/improve ui
/improve audit

</td> </tr> <tr> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Minimal code

On by default. Pushes the agent toward the simplest solution that works - stdlib and platform features before custom code, the shortest diff. Tune off | lite | full | ultra; security and validation are never cut.

</td> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Context compression

Opt-in. Shrinks large tool outputs, logs and text to far fewer tokens before they reach the model - reversibly. Use enigma compress, or register it as an MCP server.

</td> </tr> <tr> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Local agent API

enigma api serves your local coding agents over one OpenAI-compatible HTTP API - Claude Code (and Codex/OpenCode/Kimi Code where installed), with all of their tools, skills, MCP and sessions. One server, many backends: pick per request via the model field. Loopback-only. Point your OpenAI SDK at http://127.0.0.1:8000/v1.

</td> <td>

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> Local dashboard

A loopback browser control panel for all of enigma - accounts, skills, settings, system cleanup - that also shows real Claude usage and measured savings. Nothing leaves your machine.

</td> </tr> <tr> <td colspan="2">

<img src="assets/logos/enigma-logo.svg" width="20" height="20" alt="Enigma"/> SSH connections

Save each server once - key or encrypted password, jump host - then reach it by a short alias or its name. Passwords are stored encrypted and auto-filled with no extra tools (enigma acts as OpenSSH's own SSH_ASKPASS). Tunnels are standalone (bound to a rebindable server): start/stop them on demand with live status, from the CLI or a table in the dashboard.

enigma ssh add lirio-0 --name lirio-prod --host 192.0.2.10 --user deploy --password
enigma ssh lirio-0
enigma ssh tunnel add pg lirio-0 9090:5432 && enigma ssh tunnel start pg

</td> </tr> </table>

The first install is the only one you run by hand: launching a tool through enigma (e.g. enigma claude) auto-syncs the deployed skills and memory to the installed version, so updates apply without re-running enigma install (opt out with enigma config auto-sync off). It never deploys to a new agent on its own, never overwrites skills you edited, and never rewrites a memory file you authored. Skills also update straight from this repo between npm releases, verified by content hash (enigma config remote-skills off to disable).

Configuration

Most features are opt-in or tunable. Configure them from the interactive hub (enigma), the local dashboard (enigma dashboard), or the CLI (enigma config <key> <value>) - whichever you prefer. For the full list of keys, their defaults, and per-feature details, see the documentation.

Requirements

Minimum: Node.js >= 18 (with npm), Git and at least one coding agent. Recommended: add Claude Code, the GitHub CLI, Bun and Warp.

Minimum

<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" alt="Node.js"/></a>>= 18, ships with npm - installs and runs the enigma CLI
<a href="https://git-scm.com"><img src="https://img.shields.io/badge/Git-F05032?style=for-the-badge&logo=git&logoColor=white" alt="Git"/></a>powers the security hooks and the commit guard
<img src="https://img.shields.io/badge/Coding%20agent-555555?style=for-the-badge&logo=claude&logoColor=white" alt="Coding agent"/>at least one of Claude Code, OpenAI Codex, opencode or Kimi Code - the skills need a home

Recommended

Everything in Minimum, plus:

<a href="https://claude.com/claude-code"><img src="https://img.shields.io/badge/Claude%20Code-D97757?style=for-the-badge&logo=claude&logoColor=white" alt="Claude Code"/></a>the agent enigma is most battle-tested with
<a href="https://cli.github.com"><img src="https://img.shields.io/badge/GitHub%20CLI-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub CLI"/></a>gh commits go through the same hooks, and enigma issue opens prefilled reports
<a href="https://bun.sh"><img src="https://img.shields.io/badge/Bun-000000?style=for-the-badge&logo=bun&logoColor=white" alt="Bun"/></a>only needed to build or contribute from source
<a href="https://www.warp.dev"><img src="https://img.shields.io/badge/Warp-01A4FF?style=for-the-badge&logo=warp&logoColor=white" alt="Warp"/></a>a modern terminal where the hub TUI shines

Commands

enigma                 Interactive menu: choose features to set up
enigma install         Install/update agent skills
enigma update          Fetch the latest skills from GitHub, sync deployments,
                       and self-update enigma-cli when a newer release exists
enigma security        Set up git security hooks in the current repo
enigma guard [--all]   Run the commit guard: staged files, --all for all tracked, or
                       --range <base>..<head> for what a commit range touched (pre-push,
                       CI). --json emits one document; exits 1 on findings, 2 if it
                       could not run at all
enigma config [k v]    Show or set runtime toggles (e.g. config commit-emoji off)
enigma <tool> [acct]   Launch claude | codex | opencode | kimi with an account's config
                       (explicit > active profile > tool active; auto-syncs first)
enigma account ...     Manage per-tool accounts   enigma profile ...  Group them
enigma skills ...      List skills, discard one (removed everywhere and skipped
                       by installs/updates) or restore it (list/discard/restore)
enigma issue [type]    Prefilled GitHub issue URL (OS, versions, terminal, agents)
enigma compress [file] Compress JSON/logs/text to fewer tokens (reversible);
                       --retrieve <hash> restores, --stats shows total savings,
                       --clear wipes all dashboard data (stats/history/cache)
enigma verify          Check that work reported as finished actually is: scans the change for
                       unfinished work and broken conventions, and runs your verification
                       command. parity <src> <dst> compares a codebase against a port of it.
                       --json emits one document; exits 1 on findings, 2 when the check
                       could not run. Also runs at turn end, where it additionally checks
                       the reply itself against your output-style level
enigma mcp             Run the context-compression MCP server over stdio
enigma api             Serve a local OpenAI-compatible API for your agents (Claude Code, and
                       Codex/OpenCode/Kimi Code where installed); route per request by the model field.
                       --port, --api-key, --tool (default backend). Loopback-only
enigma dashboard|dash  Open the local dashboard (manage enigma; see savings) in your browser (http://enigma,
                       or http://localhost:24282 if :80/hosts is unavailable)
enigma ssh [alias]     SSH connection manager: connect by alias, or list | add | edit | remove |
                       info; tunnels are standalone: tunnel add <name> <server> <spec>,
                       tunnel start|stop <name>, tunnels (list with live status)
                       (encrypted passwords, saved key/jump/port-forwards; e.g. 9090:db:5432)
enigma seal            Maintenance: (re)compute skill content hashes
enigma check           Integrity gate: verify skills are well-formed and sealed
enigma help | version

Install options

-g, --global         User level    -l, --local   This project
-a, --agent <name>   Target agent(s) (default: auto-detect)
-s, --skill <name>   Skill(s) (default: all)
    --all            Every supported agent, ignoring detection
    --bypass <names> Force approval-prompt bypass (claude,codex,opencode,kimi | all | none)
    --no-bypass      Skip permission bypass for this run (it is on by default)
    --output-style <off|lite|full|ultra>  Token-efficient output level (asked if omitted)
    --hooks <classes>    Which hooks to wire: post-edit, stop | all | none
    --no-hooks           Wire none of them      --no-statusline  Leave statusLine alone
    --ref <tag|sha>      Pin the skills ref (the resolved commit is printed)
    --assets-from <dir>  Install from a staged assets tree (implies --offline)
    --offline            Make no network call at all
    --skills-only / --memory-only / --no-prune / --keep-modified / --dry-run

Every command answers enigma <command> --help with its own usage, flags and exit codes.

Running enigma inside a container or CI runner

ENIGMA_AGENT_CLAUDE=<abs path>   Point the gate at an agent installed off PATH
                                 (also _CODEX, _OPENCODE, _ROVODEV, _PI). The daemon runs
                                 the pipeline, so set it before the daemon starts
ENIGMA_BIN_PATH=<abs path>       Use this enigma binary instead of downloading the release
ENIGMA_SKILLS_REF=<tag|sha>      Default skills ref (install --ref overrides it)
ENIGMA_OFFLINE=1                 No enigma command reaches the network - the skill check,
                                 the update notice and the background linter/dashboard
                                 installs all stand down (install --offline sets it)

gh is needed only by the gate's push, pr and ci steps: enigma gate axi run --skip push,pr,ci and enigma gate init work in an image without it.

Contributing

Contributions are welcome. The development loop, build internals, release flow, the mechanical quality gates (verify, check, guard, seal) and local testing all live in the developer guide - start with CONTRIBUTING.

License

Apache-2.0.

Source 1 files
hooks/register.ts 87 lines
1// Generated by enigma (relay). Do not edit; set with 'enigma config relay' and 'enigma config relay-at'.
2//
3// When a turn ends with the context past RELAY_AT tokens, ask the agent for a handoff
4// (`enigma handoff save`); when the next turn ends with a fresh one saved for this project, run
5// /clear and continue the work from it in the cleared session. Nothing is cleared without a saved
6// handoff, and a handoff marked "STATUS: done" ends the relay instead of continuing it. When a
7// relay keeps the context (nothing saved, or the work is done), it is not asked again until the
8// context has grown by another half of RELAY_AT.
9import type { EngineInterface, Register } from "claude-code";
10
11const RELAY_AT = 300000;
12const LATEST = "/home/user/.enigma/handoff/latest.json";
13/** Relays one session may make: a runaway loop stops instead of clearing forever. */
14const MAX_RELAYS = 20;
15
16interface Latest { root: string; savedAt: number; done: boolean; text: string; meta: string; consumedAt: number | null; }
17
18const ASK = [
19    "[enigma relay] This conversation is past %TOKENS% tokens and every call re-reads all of it.",
20    "Run the /handoff procedure now: save the handoff for the work in progress with `enigma handoff save`",
21    "(goal, done, next, decisions, verify, files), then stop. If the work is finished, save it with the line",
22    "`STATUS: done`. enigma clears the context and continues from the handoff on its own.",
23].join(" ");
24
25const under = (cwd: string, root: string): boolean => {
26    const norm = (p: string): string => p.split("\\").join("/").replace(/\/+$/, "").toLowerCase();
27    const c = norm(cwd);
28    const r = norm(root);
29    return c === r || c.startsWith(`${r}/`);
30};
31
32/** The newest handoff save, from the pointer `enigma handoff save` writes. */
33async function latest($: EngineInterface): Promise<Latest | null> {
34    try { return JSON.parse(await $.fs.read(LATEST)) as Latest; } catch { return null; }
35}
36
37export const register: Register = (on) => {
38    let askedAt = 0;
39    let relays = 0;
40    let nextAt = RELAY_AT;
41
42    on("turn.complete", async ($, e, next) => {
43        const result = await next(e);
44        // The main loop only: a subagent's turns and interrupted ones are not a point to relay at.
45        if (e.agentId !== undefined || e.reason !== "answer" || relays >= MAX_RELAYS) return result;
46
47        if (askedAt) {
48            const asked = askedAt;
49            askedAt = 0;
50            const saved = await latest($);
51            const cwd = await $.session.cwd();
52            const kept = async (): Promise<void> => { nextAt = ((await $.session.usage()).context.tokens ?? 0) + Math.round(RELAY_AT / 2); };
53            if (!saved || saved.savedAt < asked || !under(cwd, saved.root)) {
54                await kept();
55                $.ui.toast("enigma relay: no handoff was saved, so the context was kept.");
56                return result;
57            }
58            if (saved.done) {
59                await kept();
60                $.ui.toast("enigma relay: the work is finished; the context was kept for questions about it.");
61                return result;
62            }
63            relays++;
64            nextAt = RELAY_AT;
65            void (async () => {
66                await $.command.run({ command: "clear" });
67                // The session-start hook delivers the handoff after /clear and marks it consumed; when it
68                // did not (hook off, another host), the page goes in the prompt itself.
69                let delivered = false;
70                try { delivered = (JSON.parse(await $.fs.read(saved.meta)) as Latest).consumedAt != null; } catch { /* unreadable: send it */ }
71                let page = "";
72                if (!delivered) { try { page = `\n\n${await $.fs.read(saved.text)}`; } catch { /* nothing to add */ } }
73                await $.prompt.submit({ text: `[enigma relay] The context was cleared to save tokens. Continue the work from the handoff now, starting at its next step.${page}` });
74            })();
75            return result;
76        }
77
78        const { context } = await $.session.usage();
79        // Back under the threshold (a manual /clear, a compaction): the next crossing asks again.
80        if ((context.tokens ?? 0) < RELAY_AT) nextAt = RELAY_AT;
81        if ((context.tokens ?? 0) < nextAt) return result;
82        askedAt = Date.now();
83        void $.prompt.submit({ text: ASK.replace("%TOKENS%", String(Math.round((context.tokens ?? 0) / 1000) * 1000)) });
84        return result;
85    });
86};
87