/** * The tmux "surface" CommandMate publishes on its own sessions (Issue #2317). * * Everything here is a pure argument builder or a pure predicate — no * `child_process`, no `@/` path alias, and one constants import. Three * constraints put it here rather than under `lib/tmux/`, and all three are * load-bearing: * * 1. **`tsconfig.cli.json` sets `"paths": {}`.** The CLI bundle resolves nothing * through `@/…`, so a module the `attach` command needs may only reach the * rest of `src/` through relative specifiers. `lib/tmux/tmux.ts` cannot be * that module — it imports `@/lib/cli-tools/validation` and `@/lib/logger`. * 2. **The Issue #1922 import guard.** `.eslintrc.json` forbids `src/cli/**` * from importing anything matching `**‍/tmux/**`, and its allowlist is * explicitly one-way ("may only shrink"). A pure argv builder is not the kind * of tmux access that guard exists to stop — it issues no command and opens * no session — but the rule is a path pattern, so the module lives on a path * the CLI may read. Nothing here can reach tmux: the executors are in * `lib/tmux/`, and those are what the guard still covers. * 3. **One wire form, two callers.** The server writes `@cm_status` from the * status poll and the CLI writes `@cm_delegated` from `attach --live`. If * each spelled its own `set-option` argv, the two could disagree about the * target form (`=name:` vs `name`), and a bare name prefix-matches — the * Issue #1156 leak, in a new place. Tests assert the builders, so a change to * the wire form is a change to exactly one line. * * ## What is deliberately NOT here * * Anything server-global. Every builder below takes a session name and produces * a `-t ` form: `set-option -g`, `bind-key` and `set-hook -g` are * absent on purpose (Issue #2317 決定事項 2 — the only global tmux mutation * CommandMate makes is #1623's `bind-key`, and it stays where it is, in * `lib/tmux/read-mode.ts`). */ /** * Session-name prefix every CommandMate tmux session carries. * * `lib/tmux/read-mode.ts` owns a constant of the same name for #1623's key * binding; `tests/unit/tmux/session-surface-2317.test.ts` pins the two together * so a rename breaks a test instead of silently turning a guard into a permanent * "never fire". Not imported from `cli-tools/base.ts` because it is a template * literal there, not a constant. */ export declare const MCBD_SESSION_PREFIX = "mcbd-"; /** * Exact-match tmux target for a session (Issue #1156's `=name:` form). * * The same string `exactTarget()` in `lib/tmux/tmux.ts` produces — that function * stays the one the server-side module uses, and the test above pins the two to * each other so this copy cannot drift. It exists at all because `tmux.ts` is * unreachable from the CLI bundle (see the module docblock). * * @param sessionName - Exact tmux session name * @returns `=:` — exact session match, valid as both a session and a * window/pane target */ export declare function exactSessionTarget(sessionName: string): string; /** True when `sessionName` looks like a session CommandMate created. */ export declare function isCommandMateSession(sessionName: string): boolean; /** User option carrying the session's status word. */ export declare const CM_STATUS_OPTION = "@cm_status"; /** User option carrying the worktree id the session belongs to. */ export declare const CM_WORKTREE_OPTION = "@cm_worktree"; /** User option carrying the CLI tool id running in the session. */ export declare const CM_TOOL_OPTION = "@cm_tool"; /** User option carrying the agent instance id. */ export declare const CM_INSTANCE_OPTION = "@cm_instance"; /** User option carrying the ISO timestamp of the last status write. */ export declare const CM_UPDATED_OPTION = "@cm_updated"; /** * User option set to `1` while a human client owns the session's geometry * (Phase D). Read by the server so it can stand down from resizing and from * saving a scraped reply off a terminal-sized frame. */ export declare const CM_DELEGATED_OPTION = "@cm_delegated"; /** * Every `@cm_*` option this feature writes, in the order they are removed. * * The opt-out path (`CM_TMUX_STATUS=off`) iterates this list rather than * re-typing names, so an option added above cannot be left behind on a user's * tmux server. */ export declare const CM_SESSION_OPTIONS: readonly string[]; /** * The session-scoped `status-right` CommandMate installs. * * A tmux FORMAT, not an interpolated string: the values come from the `@cm_*` * options above, so the status line re-renders on every status write without a * second write for the line itself. `window_width`x`window_height` is on it * because the whole Issue is about a window whose size the reader cannot see — * during Phase D delegation it is the fastest way to tell whether the geometry * handover actually happened. */ export declare const CM_STATUS_RIGHT_FORMAT = "[CommandMate #{@cm_tool}/#{@cm_instance} #{@cm_status}] #{window_width}x#{window_height}"; /** `tmux set-option -t `. */ export declare function buildSetSessionOptionArgs(sessionName: string, option: string, value: string): string[]; /** `tmux set-option -u -t ` — remove a session-scoped value. */ export declare function buildUnsetSessionOptionArgs(sessionName: string, option: string): string[]; /** * `tmux show-options -t `. * * Deliberately WITHOUT `-v`: the empty-vs-set distinction is the whole point of * the call at the `status-right` site. Measured on tmux 3.5a — a session that * has never had `status-right` set answers with empty stdout and exit 0, and one * that has answers `status-right "…"`. `-v` would print an empty line for the * first case too, and "the user already customised this session" would become * indistinguishable from "nobody has". */ export declare function buildShowSessionOptionArgs(sessionName: string, option: string): string[]; /** * `tmux show-options -v -t ` — the VALUE alone. * * The right shape when only the value matters (`@cm_delegated` is `1` or it is * nothing). {@link buildShowSessionOptionArgs} is the right shape when the * distinction between "set to empty" and "never set" matters, which is the * `status-right` case. */ export declare function buildShowSessionOptionValueArgs(sessionName: string, option: string): string[]; /** `tmux set-option -t status-right ''`. */ export declare function buildSetStatusRightArgs(sessionName: string, format: string): string[]; /** `tmux set-option -u -t status-right`. */ export declare function buildUnsetStatusRightArgs(sessionName: string): string[]; /** Environment variable that turns the Phase B surface off. */ export declare const TMUX_STATUS_ENV = "CM_TMUX_STATUS"; /** * True unless the operator set `CM_TMUX_STATUS` to `off` / `0` / `false`. * * Read at CALL time from an injected environment rather than at module load, so * a test can flip it without module-registry surgery and so a process started * with the variable set is not at the mercy of import order. */ export declare function isTmuxStatusEnabled(env?: Record): boolean; /** * `tmux set-hook -t `. * * The command is passed as ONE argv element. Do not fold an `if-shell -F` into * it: measured on tmux 3.5a (Issue #2317 技術検証), a hook body of the shape * `if-shell -F '#{…}' 'display-popup …'` is accepted and then silently never * fires. A `run-shell -b '