Background

This started as a joke. After Anthropic accidentally leaked the source of the Claude Code client application, via an NPM source map, certain sections of the internet exploded with people suddenly becoming experts in code review. Some folks ported the code to various languages, some folks embedded malware in forks of it, and some folks tossed the whole thing into an LLM and presumably prompted “Make me look smart on LinkedIn”.

As for me, I had no real interest in snooping around source files. But I did think it would be a hilarious April fools joke to open source a “Claude Code Search” tool which would literally just be a 5 line grep wrapper. I missed April 1 because instead of making a throwaway joke, I accidentally spent a day reverse engineering far more than I expected.

Everything below comes directly from index.js, the minified production binary distributed with Claude Code. No decompilation, no proprietary tools — just grep, pattern matching, and reading minified JavaScript with an LLM.


Methodology

I know what you’re thinking: why grep? To that I can only answer: why not grep? Grep is free, already installed, and when you know what you’re looking for, it’s all you need.

Claude Code ships as an Electron application, which allows for fast and portable development…in Javascript. Its core logic lives in a single minified JavaScript bundle at:

Claude.app/Contents/Resources/app.asar/build/index.js

The approach used with grep throughout was to utilize context windows to extract meaningful code patterns from what is otherwise an unreadable wall of minified JavaScript. For example:

grep -oE '.{80}targetString.{80}' index.js

This gives 80 characters of context on either side of a target string, which is enough to read surrounding logic without a full deobfuscation pass. That is critical for both preserving sanity and not chewing through LLM tokens and context windows needlessly. Where something caught my eye, I would often reiterate a search with a longer context window in one or both directions. Where results were too large, I would focus instead on fine tuning the regex.


Finding 1: KAIROS Is Real and In Production

Like all good stories, this one starts at the beginning: I had heard KAIROS was an internal name for an unreleased feature but that was about it. I hadn’t read others’ findings, hadn’t touched the source code. I suspected that since the application was written in JavaScript, neither would be needed.

grep -o 'kairos[^,;)]*' index.js | head -20
kairosActive:!1
kairosActive:!1

!1 is minified JavaScript for false. KAIROS exists as a disabled feature flag in the production binary. In reverse engineering, you quickly learn that a feature flag is rarely included in a production build unless a significant portion of, or even a complete feature is as well.


Finding 2: The Session State Object

Expanding the context around kairosActive revealed that it lives inside the global session state object (the object that governs every Claude Code session):

grep -o 'kairosActive[^}]*' index.js | head -5

The relevant excerpt (abbreviated):

kairosActive:!1,
strictToolResultPairing:!1,
sdkAgentProgressSummariesEnabled:!1,
userMsgOptIn:!1,
clientType:"cli",
sessionIngressToken:void 0,
sessionBypassPermissionsMode:!1,
scheduledTasksEnabled:!1,
sessionCronTasks:[],
sessionCreatedTeams:new Set,
sessionTrustAccepted:!1,
sessionPersistenceDisabled:!1,
afkModeHeaderLatched:null,
teleportedSessionInfo:null,
isRemoteMode:!1,
directConnectServerUrl:void 0,
parentSessionId:void 0,
agentColorMap:new Map,
agentColorIndex:0

Several flags in this object stand out:

  • sessionBypassPermissionsMode — a mode that explicitly bypasses all permission checks (Yes…we will get there)
  • scheduledTasksEnabled + sessionCronTasks[] — cron-style autonomous task scheduling baked into every session
  • afkModeHeaderLatched — AFK/unattended mode, persistent once set.
  • sessionIngressToken — sessions can be initiated externally via a token
  • isRemoteMode + directConnectServerUrl — sessions can run remotely
  • teleportedSessionInfo — sessions can be migrated between environments
  • parentSessionId — session hierarchy; agents can spawn child agents
  • agentColorMap — multiple concurrent agents per session, each color-coded

KAIROS sits in this object as a session-level behavior switch alongside scheduledTasksEnabled and sessionBypassPermissionsMode

This means when active, it changes how the agent loop operates at the same level those flags do.


Finding 3: The Permission Mode System

Being a security professional is a career dedicated to pattern matching. These patterns exist in people, systems, and code. But you don’t need to spend a career in security to know that when something says “BypassPermissions”, that should perk your ears. Digging into the area around it I did not find the smoking gun I was hopeful to find, however I did find acceptEdits which led me straight into the permissions model:

grep -oE '.{60}acceptEdits.{60}' index.js | head -10
var zc=(t=>(t.Default="default",t.AcceptEdits="acceptEdits",
t.Plan="plan",t.Bypass="bypassPermissions",t.Auto="auto",t))(zc||{})
nur=yi(["default","acceptEdits","bypassPermissions","plan","dontAsk","delegate","auto"])

The full permission mode enum (zc) contains seven values:

Mode Meaning
default Normal — ask for everything
acceptEdits Auto-accept file edits, ask for other actions
plan Plan-only, no execution
bypassPermissions Bypass all permission checks
dontAsk Don’t prompt, but not full bypass
delegate Delegate permission decisions to another agent
auto Fully autonomous

delegate is the outlier. It does not appear in the set of valid default modes — it can be set at runtime but not persisted as a user default. Its meaning is explained in Finding 8.


Finding 4: The Trust Architecture

The bypass guard was the find I didn’t expect. Digging around sessionBypassPermissionsMode I was hoping to find where it gets flipped on and I suspect it might have to do with defaultMode — instead I found a warning log that told me more than any code path would have. In plain English: When a system logs "only user-level or managed settings can set auto/bypass as default", someone made a deliberate decision and wanted it documented…in plain English. That single string mapped the entire trust hierarchy.

Settings Source Hierarchy

The binary contains two distinct settings source hierarchies:

CLI context:

["userSettings","projectSettings","localSettings","session","cliArg"]

Desktop app context:

["userSettings","projectSettings","localSettings","flagSettings","policySettings"]

The Bypass Guard

Searching for bypass led me to a valuable store of next steps.

grep -o '"[^"]*bypass[^"]*"' index.js | sort -u
,{scheme:"
")]).optional(),
bypassPermissionsModeEnabled:Dt().optional(),
autoPermissionsModeEnabled:Dt().optional(),
dockBounceEnabled:Dt().optional(),
coworkWebSearchEnabled:Dt().optional(),
coworkDisabledTools:Qt(Pe()).optional(),
keepAwakeEnabled:Dt().optional(),
wakeSchedulerEnabled:Dt().optional(),
wakeSchedulerApprovedThisCycle:Dt().optional(),
wakeSchedulerRegisteredAtVersion:Pe().optional(),
wakeSchedulerCourtesyFlippedKeepAwake:Dt().optional(),
coworkOnboardingResumeStep:qt({step:Do([di("
==0||l===n)&&a.has(f)){$.warn(`[CCD] Ignoring defaultMode "${f}" from ${i[l]}
— only user-level or managed settings can set auto/bypass as default`);continue}

This guard explicitly prevents projectSettings, localSettings, flagSettings, and cliArg from setting bypassPermissions or auto as a persistent default mode. Only userSettings (index 0) and policySettings (the managed enterprise setting) can do so. My hope was that we could target this setting, but someone at Anthropic already thought of that.

Practical implication: A malicious repository containing a .claude/ settings file cannot escalate itself to bypass mode. The attack surface requires writing to ~/.claude/ (user settings) or enterprise policy configuration.

Per-Project Trust

I kept reading through the bypass output until I noticed hasTrustDialogAccepted. Any time a program is querying a trust boundary is a valuable area to explore further.

grep -o '.hasTrustDialogAccepted[^}]*}' index.js | head -10
.hasTrustDialogAccepted)return!0;let s=t;
if(e){const l=(o=r.projects)==null?void 0:o[s];
  return(l==null?void 0:l.hasTrustDialogAccepted)===!0}
for(;s!==null;){
  const l=(c=r.projects)==null?void 0:c[s];
  if(l!=null&&l.hasTrustDialogAccepted)return!0;
  const u=Ae.resolve(s,"..");s=u===s?null:u
}

This output gave us a lot of information. Specifically it shows the trust hierarchy:

  1. Check global bypassPermissionsModeAccepted — if set, trust everything immediately
  2. Check the specific project directory path for hasTrustDialogAccepted
  3. Walk up the directory tree checking each parent directory
  4. Stop at filesystem root

Trust granted to a parent directory propagates to all children. Trust granted to /Users/you/projects would cover every project underneath it.


Finding 5: Chrome/Browser Permission System

The Chrome permission system wasn’t something I went looking for directly. It surfaced during the scheduled tasks investigation (discussed in Finding 6) in the form of chromePermissionMode. It kept appearing as a field on every scheduled task object, stored independently alongside approvedPermissions. That raised an obvious question: if scheduled tasks have their own Chrome permission state, what does that state actually control?

The permission mode enum from Finding 3 had already shown auto and bypassPermissions at the aggressive end of the scale. The question was whether Chrome had its own independent gate on those modes, or whether it just followed whatever the session said. The answer was worse than expected.

grep -oE '.{60}chromePermissionMode.{60}' index.js | head -5

The chromePermissionMode field accepts exactly three values:

zr.enum(["ask","skip_all_permission_checks","follow_a_plan"])

With an optional chromeAllowedDomains allowlist.

The critical automatic escalation:

(p===zc.Auto||p===zc.Bypass)&&{chromePermissionMode:"skip_all_permission_checks"}

When a session’s main permissionMode is auto or bypassPermissions, Chrome automatically receives skip_all_permission_checks. Browser permissions escalate automatically with session permissions — they are not independently gated.

There is also a classifier for browser actions:

[canUseTool:CIC] computer(wait) → harmless action

An internal classifier (CIC) evaluates browser actions and can auto-allow those it determines to be “harmless” without user confirmation.

Note: this is functionally similar to the remediation steps I listed in the ROTA attack post.


Finding 6: Scheduled Tasks With Independent Permission Modes

By this point the session state object had shown scheduledTasksEnabled and sessionCronTasks[] sitting right next to sessionBypassPermissionsMode. That combination is what made me stop. Cron jobs are unattended, by definition, they fire when you’re not there. Pairing that with a bypass permissions flag in the same object isn’t subtle. The question now was whether scheduled tasks had their own permission configuration or just inherited from the session. Turns out it’s neither: they have their own full permission lifecycle, and it grows over time.

grep -oE '.{100}scheduledTask.{100}' index.js | grep -i 'permission\|bypass\|mode'

Scheduled tasks (sessionCronTasks) are full session configurations with their own permission lifecycle:

  • Each scheduled task stores its own approvedPermissions[] list, persisted to disk
  • shouldAutoApprovePermission() auto-approves tools that were previously approved for that task
  • addApprovedPermission / removeApprovedPermission — permissions accumulate across runs
  • chromePermissionMode is stored independently per scheduled task
  • Two separate scheduled task systems exist: CoworkScheduledTasks and CCDScheduledTasks
"Argument "scheduledTaskId" at position 0 to method "removeApprovedPermission" 
in interface "CoworkScheduledTasks" failed to pass validation"
"Argument "scheduledTaskId" at position 0 to method "clearChromePermissions" 
in interface "CoworkScheduledTasks" failed to pass validation"

A scheduled task can run with bypassPermissions mode, accumulate approved tools over time, and operate the browser with skip_all_permission_checks — entirely without user interaction.


Finding 7: teleportToCloud

teleportedSessionInfo was one of those flags in the session state object that just stuck out. “Teleported” is not standard infrastructure vocabulary which means that someone named it deliberately - or accidentally. The grep confirmed it’s exactly what it sounds like: a method that picks up a running local session and moves it to Anthropic’s cloud infrastructure mid-flight. It checks for a clean git tree before allowing the migration, which tells me that this was an intended feature and not an afterthought.

grep -oE '.{100}teleport.{100}' index.js | head -10
async teleportToCloud(e,r,n){
  const i=await this.sessionManager.getSession(e);
  ...
  r.sshConfig?{ready:!1,...,error:"SSH sessions cannot be teleported to the cloud."}
  :await p0(tI[Jl()])?
    await this.hasDirtyWorkingTree(r.cwd)?
      {ready:!1,needsCommitAndPush:!0,...}
    :{ready:!0,...}
  :{ready:!1,...,needsAuth:!0}

teleportToCloud(sessionId, environmentId) migrates a local Claude Code session to Anthropic’s cloud infrastructure. Pre-conditions:

  • Session cannot be SSH-based
  • Working tree must be clean (no uncommitted changes)
  • User must be authenticated

After teleportation, the session continues running remotely. This explains isRemoteMode and directConnectServerUrl in the session state — post-teleport, the local client connects back to the remote session.


Finding 8: Operon — The Full Autonomous Agent Platform

Everything up to this point had been individual flags and subsystems. Bypass permissions, scheduled tasks, Chrome escalation, cloud teleportation — interesting in isolation, but not what I was after. The thread that tied it together was OPERON_DISABLE_AUTO_MODEL_EFFORT, which surfaced during the search_agents grep.

Grepping OPERON directly confirmed it: what looked like a feature flag is actually a fully embedded autonomous agent platform with its own name, its own database, its own Python runtime, and its own tool registry.

The name is Operon. KAIROS is the product layer on top of it.

Infrastructure

grep -oE '.{100}OPERON.{100}' index.js | head -20

Operon maintains its own infrastructure entirely separate from Claude Code’s main session:

~/.operon/operon.db       — SQLite database
~/.operon/workspace/      — Workspace directory  
~/.operon/conda/          — Managed Conda/Python environment

Environment variables:

OPERON_DB_PATH            — Override database location
OPERON_WORKSPACE_BASE     — Override workspace location
OPERON_CONDA_HOME         — Override Conda location
OPERON_ARTIFACTS_DIR      — Override artifacts location
OPERON_SANDBOXED_NETWORK  — Enable network sandboxing ("operon-desktop" vs "operon-cli")
OPERON_ENABLE_LLM_CLASSIFIER — Enable a separate LLM safety classifier on tool calls
OPERON_ENV                — "production" vs other environments
OPERON_DISABLE_AUTO_MODEL_EFFORT — Disable automatic model effort selection
OPERON_CLI_MODE           — Running in CLI vs desktop context

The Tool Registry

grep -oE '.{100}tool_router.{100}' index.js | head -10

Operon exposes a complete tool suite via a tool_router:

Agent & skill discovery:

  • search_agents — find agents in the registry by capability
  • search_skills — find available skills
  • list_frames — list execution frames

Execution & planning:

  • generate_plan — create a multi-phase execution plan
  • update_step_status — track plan step completion
  • submit_output — submit results
  • ask_user — request human input when needed

Skills & dashboards:

  • create_skill — create new reusable skills
  • render_dashboard / patch_dashboard / read_dashboard — live dashboards

Artifacts:

  • display_artifacts — surface artifacts to the user
  • read_artifact_lineage — trace artifact provenance

Permission escalation:

  • request_network_access — request network access
  • request_host_access — request host filesystem access

Delegation:

  • delegate_to — synchronous delegation to a named agent
  • delegate_subtask — async delegation; child runs in background, sends completion notification

Concierge (conversation/project access):

  • get_conversation_detail
  • list_artifacts
  • list_notes
  • list_folders
  • search_project

When an agent has access to search_agents, the system injects RULES_DELEGATION into its system prompt. When it has delegate_subtask, it gets RULES_SUBTASK. The rules are injected dynamically based on available tools.

The Agent Registry

grep -oE '.{100}agentExists.{100}' index.js | head -10
class lkn{
  constructor(){
    this._cache=new Map,
    this._builtinToolSchemas=[],
    this._services={}
  }
  agentExists(e){return this._cache.has(e.toUpperCase())}
  getAgent(e){return this._cache.get(e.toUpperCase())??null}

Agents are stored by uppercased name in an in-memory cache. The registry supports:

  • agentExists(name) — check if an agent is registered
  • getAgent(name) — retrieve agent configuration
  • Child agent rehydration — crashed or paused agents can be rehydrated from state
  • MCP server attachment to specific agents

The delegate Permission Mode — Resolved

{error:"delegate_to requires 'agent' and 'task' arguments"}
n={
  agent:{type:"string",enum:e,description:"The agent to delegate to. Use search_agents to find suitable agents."},
  task:{type:"string",description:"The task description for the sub-agent"}
}

delegate permission mode means Claude hands off permission decisions to another agent in the Operon registry. This enables a hierarchical permission model where a supervisor agent can approve or deny actions on behalf of child agents.

Academic Research Integration

The API integrations bundled with Operon reveal its intended use case:

ELSEVIER_INST_TOKEN
SPRINGER_API_KEY
SEMANTIC_SCHOLAR_API_KEY
NCBI_API_KEY
CORE_API_KEY
OPERON_CONTACT_EMAIL
OPERON_EZPROXY_URL / OPERON_EZPROXY_COOKIE

Semantic Scholar, NCBI (PubMed), Elsevier, Springer, CORE, and EZProxy (institutional library proxy) — this is infrastructure for autonomous academic research workflows, not just coding assistance.

The Safety Classifier

OPERON_ENABLE_LLM_CLASSIFIER
const i=process.env.OPERON_ENABLE_LLM_CLASSIFIER??"";
if(!["1","true","yes"].includes(i.toLowerCase()))return["safe",null];

A separate LLM runs as a safety classifier on Operon tool calls. It is disabled by default and must be explicitly enabled via environment variable. When enabled, it evaluates tool calls and returns a safety classification before execution.

Arbitrary JavaScript Restriction

"Arbitrary JavaScript execution is disabled in unsupervised mode."
e?t?t.permissionMode==="auto"||t.permissionMode==="bypassPermissions"?
  {decision:"block",reason:"Arbitrary JavaScript execution is disabled in unsupervised mode."}
  :{decision:"allow",...}

In auto or bypassPermissions mode, arbitrary JavaScript execution is blocked. However, the browser agent continues to run with skip_all_permission_checks in these modes — browser actions are not subject to this restriction.

One More Thing

Buried in the same production bundle, between certificate parsing and VM diagnostics:

"Run the trap, drop the bass"

Someone at Anthropic is having fun. Further exploration of electronic music is an exercise left to the reader.


The Complete Autonomous Pipeline

Putting all findings together, the full unattended autonomous operation stack:

  1. A scheduled task (sessionCronTasks) is configured with a cronExpression, a prompt, and a permissionMode — potentially bypassPermissions or auto
  2. At the scheduled time, a session is created with those permissions. sessionIngressToken enables external initiation.
  3. If the session mode is bypass or auto, the browser agent automatically receives skip_all_permission_checks
  4. The agent operates via Operon’s tool registry — planning, executing, accessing files, the web, academic APIs
  5. The agent can delegate_subtask to other registered agents asynchronously — child agents run in background and send completion notifications
  6. Approved permissions accumulate per task and auto-approve on future runs — the permission surface grows over time
  7. If needed, the session can teleportToCloud to continue running on Anthropic infrastructure
  8. A parent agent with delegate permission mode can approve or deny child agent actions

KAIROS is the product name for this orchestration layer. The infrastructure is already present in the production binary. The feature flag kairosActive:!1 is the only thing standing between the current state and this system being generally available.


What This Means

Beyond the utility of grep, what this brief investigation revealed is a coherent autonomous agent platform that is implemented, present in production code, and gated behind a single feature flag.

The question that I am left with is simple: when KAIROS ships, what does the threat model look like for accumulated scheduled task permissions + browser bypass + cloud teleportation in combination?


Found something I missed, or want to tell me I got something wrong? liminalstack@proton.me

Anthropic — if any of this is inaccurate, you know where to find me. Same address.

Research conducted via static analysis of a publicly distributed binary. No systems were accessed beyond the researcher’s own machine.