Skip to content

Share one Context across commands, CLIs and runtimes - #1635

Merged
zechengz merged 3 commits into
mainfrom
claude/unify-context
Oct 17, 2026
Merged

zechengz merged 3 commits into
mainfrom
claude/unify-context

Conversation

@bytecii

@bytecii bytecii commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Commands, CLI leaves and runtime executions each received the same facts (the session's files, the live session, processes, cwd, env, stdin, argv, flags) under a type of their own: CommandOpts (plus ExecContext from the workspace to the mount), CLIInvocation with its CLIView, and RuntimeContext. This PR makes them one Context, read as ctx, on both hosts.

command:  fn(accessor, paths, texts, ctx)
CLI leaf: fn(config,   paths, texts, ctx)
runtime:  RuntimeContext.ctx

A cleanup step toward MIRAGE-21 (S15). Commands keep their accessor and mount plumbing (index, io, mount_prefix) for now; no behavior changes.

What changed

  • Context (commands/config.py, commands/config.ts) replaces CommandOpts, ExecContext, CLIInvocation and CLIView. Shared fields: vfs, session (was session_view), processes, cwd, env, stdin, argv, flags, spec, shell. The command's own fields stay beside them.
  • CLI leaves take (config, paths, texts, ctx): the account config sits where a command has its accessor. Helpers that took an invocation now take only what they read.
  • RuntimeContext holds a ctx: Context instead of its own copies of vfs, session_view, cwd, env and processes.
  • Mount.run_command(..., ctx, limit_override): the workspace's context is extended with the mount's facts (replace/spread) instead of being copied field by field, and the limit override is its own argument.
  • Context.runtime is typed by the RuntimeIdentity protocol, so the shared type imports no runtime class and RuntimeContext can hold it without an import cycle (both hosts, type-only cycles stay at 0).
  • TypeScript's command cwd is a PathSpec, as Python's and the CLIs' already were (ROOT_CWD is a PathSpec on both hosts now).
  • A CLI's ctx.shell is the commands' shell(line, stdin=None).
  • opts, inv and view are renamed ctx throughout. No TYPE_CHECKING guards are added.
  • The two parity tests that pinned ExecContext and CLIView against CommandOpts are removed (one type now). The TypeScript test fixture cliInvocation is context().
  • Docs (cli/custom.mdx, cli/index.mdx, vfs/new.mdx, both languages), examples, integ fixtures and CLAUDE.md follow the new shape. The public barrels export Context in place of CLIInvocation/CLIView.

Notes for review

  • The diff is mostly mechanical, but CLI handlers grow: a one-line (inv) signature became four parameters, and TypeScript's formatter puts each on its own line (CLI directories are about +840 lines in TypeScript, +250 in Python, where the four fit on one line). Command modules are line-neutral.
  • One TypeScript-only detail: git's per-verb ambiguity warnings were keyed by the CLIView object; they are now keyed by the argv array verb gives each call, which a derived context ({ ...ctx, flags }, as stash show builds for diff) keeps. Python uses ContextVars and needed no change.

Verification

  • Python: mypy clean (2,193 files), pytest 32,201 passed / 0 failed, ruff clean.
  • TypeScript: tsc clean in every package; vitest core 22,756 passed / 0 failed, node 3,963, browser 310, server 501, dsh 260, agents 197, cli 127, opencode 2.
  • Gates: layout parity, symbol parity (baseline lowered 3650 → 3649), import direction (0 edges, 0 runtime and 0 type-only cycles), barrel surface, spec parity (117 commands, 10 CLI trees), CLI cold start, test PathSpec discipline, case targets; pre-commit run --all-files with CI's skips.
  • Not run locally: the integ batteries (no observable shell behavior changes), and the integ package typecheck (its Prisma clients are not generated in this checkout).

🤖 Generated with Claude Code

@bytecii
bytecii requested a review from zechengz as a code owner October 17, 2026 00:41
@greptile-apps

greptile-apps Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5 Tier: apex

[High impact] The PR appears safe to merge; the earlier concerns are addressed and no new actionable issues remain.

Summary

Commands, CLI handlers, and runtimes now share Context in Python and TypeScript.

  • Commands, CLI leaves, and runtimes share one context.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Session["Session files, state and input"] --> Context["Context"]
  Context --> Mount["Mount adds index, io and prefix"]
  Mount --> Command["fn(accessor, paths, texts, ctx)"]
  Context --> CLI["fn(config, paths, texts, ctx)"]
  Context --> Runtime["RuntimeContext.ctx"]
Loading

Reviews (3) · Last reviewed commit: "Hand the cross-mount ls relay's profile ..." · Reviewed by Greptile

zechengz and others added 2 commits October 16, 2026 17:51
Commands, CLI leaves and runtime executions each carried the same facts
under their own type: CommandOpts (plus ExecContext from the workspace to
the mount), CLIInvocation with its CLIView, and RuntimeContext. They are
now one Context, read as `ctx`, on both hosts:

- A command handler is fn(accessor, paths, texts, ctx) and a CLI leaf
  fn(config, paths, texts, ctx). The account config takes the place the
  accessor has for a command; commands keep their accessor and mount
  plumbing (index, io, mount_prefix) for now.
- ctx carries files (vfs), the live session (session, was session_view),
  processes, cwd, env, stdin, argv, flags, spec and shell; the command's
  own facts stay beside them.
- RuntimeContext holds the same Context instead of copies of vfs,
  session_view, cwd, env and processes.
- ExecContext folds into Context; run_command takes the caller's limit
  override as its own argument. TypeScript's command cwd is a PathSpec,
  as Python's and the CLIs' already were.
- Context.runtime is typed by the RuntimeIdentity protocol, so the shared
  type imports no runtime class and the runtime binding can hold it
  without an import cycle.
- A CLI's shell is the one commands get, shell(line, stdin=None).
- opts, inv and view are renamed ctx; the parity tests that pinned
  ExecContext and CLIView against CommandOpts are gone with those types.

No behavior change. Docs, examples, integ fixtures and CLAUDE.md follow
the new shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cli_ref battery loads the tally CLI from .mjs and .js too, whose
leaves still read the old invocation; they take (config, paths, texts)
now, as the .ts and .py twins do. The browser suite's pause leaf reads
ctx.env. The eslint flag-bag selectors matched `opts.flags` and
`inv.flags`, names no handler uses any more, so they match `ctx.flags`;
the probe test follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread typescript/packages/core/src/workspace/executor/command/cli.ts
Comment thread typescript/packages/core/src/commands/config.ts
@bytecii
bytecii force-pushed the claude/unify-context branch from 6219386 to 8016528 Compare October 17, 2026 00:53
The TypeScript relay still spread the session view as sessionView, a key
Context no longer has, so a cross-mount ls -l printed - for owner and
group in a named-profile session. Both hosts now pin the profile columns
for a listing that spans mounts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zechengz
zechengz merged commit ce5dacb into main Oct 17, 2026
66 checks passed
@zechengz
zechengz deleted the claude/unify-context branch October 17, 2026 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants