use serde_json::{Value, json};
use super::tool;
pub(super) fn session_tools() -> Vec<Value> {
vec![
tool(
"session_new",
"Spawn a new managed Claude Code (or trusty-code) session in an \
isolated, freshly-provisioned workspace cloned from `repo_url` at \
`ref`. The daemon creates the tmux host, deploys agents/skills, and \
launches the harness with the given `task`. Returns the new managed \
session id, tmux name, workspace path, lifecycle state, and the \
`tmux attach-session` command.",
json!({
"type": "object",
"properties": {
"repo_url": {
"type": "string",
"description": "Repository URL to clone into the session workspace."
},
"ref": {
"type": "string",
"description": "Git branch or ref to check out."
},
"task": {
"type": "string",
"description": "Human-readable task description handed to the harness."
},
"name_hint": {
"type": "string",
"description": "Optional name hint overriding the auto-generated tmux session name."
},
"runtime": {
"type": "string",
"enum": ["claude-code", "tcode"],
"description": "Optional runtime backend; defaults to claude-code."
},
"ephemeral": {
"type": "boolean",
"description": "Tag this as an EPHEMERAL (test/throwaway) session eligible for bulk teardown and age-based auto-reap. Defaults to false (a durable session the automatic teardown paths never touch)."
}
},
"required": ["repo_url", "ref", "task"],
"additionalProperties": false
}),
),
tool(
"session_stop",
"Stop a managed session's runtime (kills the tmux session and harness \
process) while PRESERVING its workspace on disk and its record, so it \
can be resumed later with `session_resume`. This is NOT a teardown — \
use `session_decommission` to remove the workspace permanently.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
}
},
"required": ["session_id"],
"additionalProperties": false
}),
),
tool(
"session_resume",
"Resume a previously-stopped managed session: re-create the tmux host \
rooted at the still-on-disk workspace and re-spawn the SAME runtime \
backend the session was created with (no re-clone). Returns the \
updated session record.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
}
},
"required": ["session_id"],
"additionalProperties": false
}),
),
tool(
"session_decommission",
"Permanently tear down a managed session: kill the runtime, REMOVE the \
workspace directory from disk, and mark the record Decommissioned. \
This is terminal — the session can NOT be resumed afterwards. A \
tombstone record is retained for audit.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
}
},
"required": ["session_id"],
"additionalProperties": false
}),
),
tool(
"session_delete",
"Hard-delete a managed session's RECORD from the store — distinct \
from `session_decommission`, which stops the runtime and may remove \
the workspace but always leaves a Decommissioned tombstone behind. \
`session_delete` permanently drops the record itself. FAIL-CLOSED: \
a RUNNING session (Active/Provisioning) is REFUSED unless `force` is \
true. Never touches the workspace directory on disk — this is a \
store-only operation.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
},
"force": {
"type": "boolean",
"description": "Bypass the running-session guard and delete the record anyway. Defaults to false (the fail-closed default)."
}
},
"required": ["session_id"],
"additionalProperties": false
}),
),
tool(
"session_activity",
"Inspect a managed session's recent activity. ALWAYS returns the raw \
tmux pane content (last `lines` lines, default 60) plus structured \
lifecycle fields (`runtime_active`, `pending_decision`, \
`proposed_default`) so the caller can do its own inference WITHOUT an \
LLM key. When OPENROUTER_API_KEY is configured the daemon also \
returns an LLM `classification` of the session state.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
},
"lines": {
"type": "integer",
"minimum": 1,
"maximum": 500,
"description": "Number of trailing pane lines to capture (default 60)."
}
},
"required": ["session_id"],
"additionalProperties": false
}),
),
tool(
"session_send",
"Send a line of text into a managed session's tmux pane (followed by \
Enter), e.g. to answer a prompt or drive the harness. Returns a \
confirmation with the target tmux session name.",
json!({
"type": "object",
"properties": {
"session_id": {
"type": "string",
"description": "Managed session id (UUID)."
},
"text": {
"type": "string",
"description": "Text to inject into the session's pane."
}
},
"required": ["session_id", "text"],
"additionalProperties": false
}),
),
tool(
"session_decommission_ephemeral",
"Tear down EVERY ephemeral (test/throwaway) managed session in one \
shot: kill each runtime, remove its workspace, and tombstone the \
record. REAL sessions default `ephemeral=false` and are NEVER touched \
by this tool. Returns the count decommissioned. Use this from e2e \
harnesses or to clean up after a test run.",
json!({
"type": "object",
"properties": {},
"additionalProperties": false
}),
),
tool(
"session_prune",
"Prune managed sessions by state and compact tombstones. `state` \
selects which records to target: `ephemeral` (test sessions), \
`stopped`, `decommissioned` (drop existing tombstones from the store), \
or `all` (every NON-running record). A RUNNING session is NEVER torn \
down unless `include_active` is true. With `dry_run` the tool REPORTS \
what would be pruned without mutating anything. This is the tool to \
purge legacy stale records that predate the ephemeral flag.",
json!({
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["ephemeral", "stopped", "decommissioned", "all"],
"description": "Which records to target."
},
"dry_run": {
"type": "boolean",
"description": "Report what WOULD be pruned without mutating anything (default false)."
},
"include_active": {
"type": "boolean",
"description": "Also tear down RUNNING (Active/Provisioning) sessions. Off by default — the fail-closed safety gate."
}
},
"required": ["state"],
"additionalProperties": false
}),
),
tool(
"session_context_catchup",
"Return a STRUCTURED (JSON, not prose) resume digest for `project_dir`: \
paused sessions (native trusty-mpm + legacy claude-mpm formats), \
recent git commits, and recent memory-palace activity — the same \
three sources `tm session catchup` renders as markdown, restructured \
as typed fields. This is a manual PEEK: it NEVER advances the \
incremental-catchup watermark (only automatic session-start \
injection does that), so calling it repeatedly is always safe and \
`watermark_advanced` in the result is always `false`.",
json!({
"type": "object",
"properties": {
"project_dir": {
"type": "string",
"description": "Absolute path to the project directory to scan. Required — the stdio bridge forwards no cwd, so the daemon cannot infer it."
},
"session_id": {
"type": "string",
"description": "Optional session id used only to resolve `resolved_snapshot` (the snapshot this specific session would resume from)."
},
"all_projects": {
"type": "boolean",
"description": "Also scan every project in the legacy claude-mpm registry, merging their sessions/commits/memory into the same arrays. Defaults to false (project_dir only)."
},
"full": {
"type": "boolean",
"description": "Ignore the watermark and return full history instead of just activity since the last catch-up. Defaults to false."
}
},
"required": ["project_dir"],
"additionalProperties": false
}),
),
tool(
"session_context_pause",
"Write a session-pause snapshot for `project_dir`: a \
`session-YYYYMMDD-HHMMSS.md` file in the SAME section format the \
catch-up reader already parses (`## Summary` / `## Completed` / \
`## In Progress` / `## Next Steps` / `## Git Context` / \
`## Tmux Window`), plus an appended `pause` line in the \
append-only `sessions-log.jsonl`. Also prunes orphaned managed-session \
git worktrees in-process (same engine as `tm session prune-worktrees`) \
unless `prune_worktrees` is set to `false`. Does NOT touch tmux — \
window realignment on resume stays a PM-side `tmux select-window` step.",
json!({
"type": "object",
"properties": {
"project_dir": {
"type": "string",
"description": "Absolute path to the project directory to snapshot."
},
"session_id": {
"type": "string",
"description": "Stable id for the originating session; keys the append-only pause-log entry."
},
"summary": {
"type": "string",
"description": "The `## Summary` section body — required, human-readable current-state prose."
},
"completed": {
"type": "array",
"items": { "type": "string" },
"description": "Bullet items for the `## Completed` section. Omitted entirely from the file when empty."
},
"in_progress": {
"type": "array",
"items": { "type": "string" },
"description": "Bullet items for the `## In Progress` section. Omitted entirely from the file when empty."
},
"next_steps": {
"type": "array",
"items": { "type": "string" },
"description": "Bullet items for the `## Next Steps` section. Omitted entirely from the file when empty."
},
"tmux_window": {
"type": "string",
"description": "`session_name:window_index:window_id` captured via `tmux display-message`, when inside tmux. Omitted entirely from the file when absent."
},
"prune_worktrees": {
"type": "boolean",
"description": "Also prune orphaned managed-session git worktree directories as part of pause wrap-up. Defaults to true."
}
},
"required": ["project_dir", "session_id", "summary"],
"additionalProperties": false
}),
),
]
}