GitHub
Skip to article

Save and reuse workflows

On this page

For terminal examples, run workspace commands from the workspace root. External projects and stack bundles are sibling directories; adjust their relative paths.

TDT can offer to save a reusable workflow during ordinary work. One clearly reusable request is enough for a live offer; the original work continues whether you accept or decline. The proposal names the skill and describes its future behavior. Existing skills and remembered declines are checked first. Stack-builder remains the separate workflow for authoring distributable stacks.

Use /tdt-add-skill with “Save this workflow as a skill I can use again,” or ask your agent directly. The skill also handles approved live workflow suggestions; a history scan is not needed for a live suggestion. Review the proposed steps before approving them, then invoke the saved skill in a fresh session. In Codex, use $tdt-add-skill or the skill picker.

For example, unread-email triage takes a mailbox/filter, time range, summary format and priority criteria. A proposed output could include subject, short summary, priority, evidence and uncertainty. Urgency inferred from wording must be labelled; sender role, explicit deadlines and user criteria supply evidence. Use an available Gmail connector that the user has authorized. If access is missing, explain the requirement. Do not install or connect a connector without authorization. Saving or running a summarization workflow does not authorize sending, deleting, archiving or marking messages read.

Choose your own readable name, such as tdt-unread-triage, for any discovered or new skill. The agent suggests a descriptive name if needed and checks for duplicate names before saving. Names do not need a hash suffix: the separate content ID is only used to review a proposal. If a name is taken, choose another or explicitly request an update to an existing user-owned skill. Core, stack and unmanaged skills cannot be overwritten through this flow. Pending proposals are checked too; refine the existing candidate instead of creating an unrelated workflow under its name. Changing an unsaved proposal's name creates a new review ID; approve only the final candidate. This does not rename an already installed skill.

Find workflows in previous sessions

Ask /tdt-find-skills 5 to look for repeated workflows in up to five completed sessions of this workspace. Your agent needs access to their histories and reliable completion information. If it cannot obtain those, it should explain the gap instead of claiming a complete scan. Review any suggested skills before saving.

Technical reference: propose, review and update a skill

/tdt-add-skill and /tdt-find-skills handle the following commands for live suggestions and history-based proposals. Technical users can use the same commands directly.

Agents use this same path for live suggestions and discovered candidates. Run tdt skill list first: it includes core, stack, unmanaged and user skills in all three local skill directories, plus retained pending/approved/declined proposals. Read relevant overlaps before offering a new name. A matching non-user skill can be invoked; suggest an update through its owning core/stack workflow rather than claiming ownership. Do not rename a declined workflow to offer it again.

Submit a generalized proposal with tdt skill propose (JSON on stdin, at most 16 KiB). Use these fields:

Code
{
  "name": "tdt-unread-triage",
  "description": "Summarize unread email and estimate priority using explicit criteria when asked to triage a mailbox.",
  "instructions": "Ask for the mailbox/filter, time range and priority criteria if missing. Use only an available authorized email reader. Read without changing read status. Output a table of subject, summary, priority, evidence and uncertainty. Infer urgency only with a label; use explicit deadlines and user criteria as evidence. Never send, delete, archive or mark read without separate authorization. If read-only access is unavailable, explain the missing prerequisite and stop.",
  "sources": ["claude:session-id:turn-id"]
}

Instructions should cover reusable steps, variable inputs, output expectations, tool prerequisites and relevant limits. Omit private content, credentials, raw transcripts and incidental values. Use at most 1024 characters for the description and 10000 for the instructions. Include at most 40 source references, each with at most 160 characters. Live suggestions may use an empty source list. Do not store raw approval messages; use a short user-message reference for the decision.

New proposals refuse names already owned by a user skill. For an intentionally requested update, submit the same JSON shape with tdt skill propose --update. This option requires an existing user-owned skill and retains ownership checks.

Show the exact proposal and its returned content ID separately from the skill name. Replace <id>, <id1> and <id2> below with proposal IDs. Replace <user-message-reference> with a quoted reference to the actual decision. After the user approves or declines the displayed proposals, run the matching command:

Code
tdt skill review <id> --decision approve --user-instruction <user-message-reference>
tdt skill review <id1> <id2> --decision approve --user-instruction <user-message-reference>
tdt skill review <id> --decision decline --user-instruction <user-message-reference>

Select 1–20 distinct IDs, one version per name, per review. Batch preflight refuses all writes if any selected skill conflicts. Refine by submitting a changed proposal and displaying it for approval. Repeated identical submissions retain pending/declined decisions. An approved version that is still installed remains approved. If a different version is now installed, resubmitting the earlier behavior with --update reopens it as pending against current ownership; show it for fresh approval before restoring it. Directly approving the old ID without resubmitting is refused. Do not repeatedly offer unchanged declines. If the user explicitly revisits a declined proposal, their new approval can select the same ID; do not solicit that reversal automatically. Approval is a conversation responsibility: the CLI records the supplied decision reference; it cannot independently authenticate user intent. Never fabricate it.

Approved files live at .tdt/skills/<name>/SKILL.md, where the full name begins with tdt-. Names contain at most 64 lowercase ASCII letters, digits and hyphens. Do not start or end a name with a hyphen, or use consecutive hyphens. The name must match the directory. The writer emits valid quoted YAML frontmatter following the Agent Skills specification. Thin bridges are registered at .claude/skills/<name>/SKILL.md and .agents/skills/<name>/SKILL.md in this workspace only, for enabled hosts. No global or external project registrations are created.

Ownership and up to 100 bounded proposals/decisions live separately in .tdt/state/user-skills.json. Identical behavior has the same ID even when source references change. At the limit the command refuses new proposals; consciously archive decided entries before pruning them, since deleting declines loses that memory. Semantic duplicate detection belongs to the active agent. Creation checks all three workspace skill directories and Claude command collisions, including disabled hosts. Updates to an owned skill use a new proposal and refuse edits/missing files or changed ownership since proposal. Preserve and reconcile edited files explicitly before retrying; do not delete edits to force an update. Core re-bootstrap and stack removal do not own these skills.

If interrupted, run tdt skill recover. It rolls back only files still matching the journal's before/after content, leaving proposals reviewable; conflicts require manual inspection with edits preserved. Then review the same approved proposal again using the existing user authorization. Do not manually expose partial bridges.

Claude uses /tdt-find-skills 5 and /tdt-unread-triage. Codex uses $tdt-find-skills 5 and $tdt-unread-triage (slash selection depends on its UI). Restart/start a new session in the owning workspace if a new skill is not listed; review workspace trust and bootstrap first. Saving a skill does not execute it.

Provide history to the CLI

N means the most recent completed previous sessions of this workspace, not turns, brain notes, or linked-project histories. Supported maximum: 20. History readers support Claude Code conversation JSONL (sessionId, cwd, uuid, message) and Codex rollout JSONL (session_meta, response_item messages). They do not query a global history database, assume a fixed home directory, or parse brain summaries. Host interfaces vary: the active agent must resolve accessible transcript paths and a completion inventory through its available host session listing/export or explicitly identified host files. Do not enumerate unrelated histories looking for a match. If this capability is unavailable, say so and inspect zero sessions.

Pass the known active session ID and a bounded inventory to:

Code
tdt skill history 5 --host claude --active-session <actual-id>
tdt skill history 5 --host codex --active-session <actual-id>

JSON stdin (same 16 KiB command limit). Replace every placeholder, including HOST_COMPLETION_TIMESTAMP with the actual ISO 8601 completion timestamp supplied by the host. HOST_TRANSCRIPT_PATH must be its actual canonical absolute path; for an explicitly supplied export such as ./history/session.jsonl, resolve that relative path from the current working directory before building the inventory. The reader requires absolute paths to avoid ambiguity across host processes:

Code
{
  "sessions": [
    {"id": "previous-session-id", "path": "HOST_TRANSCRIPT_PATH", "completed_at": "HOST_COMPLETION_TIMESTAMP", "completion_evidence": "host session listing identifies this session as ended"}
  ],
  "limitations": ["Only the active host's accessible session inventory is available"]
}

The caller must establish session completion and inventory recency from actual host evidence. Neither file modification time, a Stop hook, nor a completed turn proves the session ended. If only a subset can be located, disclose that the most recent N cannot be established; the output is a partial scan of located sessions. An unavailable provider may be represented with an empty session list and a reason. Do not invent completion dates or use the example IDs as real evidence.

At most 100 inventory entries are accepted. Entries are sorted by completed time; active and duplicate IDs are removed before selecting N. Missing selected histories are reported without silently replacing them with older sessions. Every selected transcript must identify the requested session and exact canonical workspace cwd. Subdirectories/linked projects and unknown metadata are conservatively skipped. Only the selected host is read; the other provider is reported as unscanned.

Each read is capped at 128 KiB, with an incomplete boundary record omitted. Output is capped at 24000 text characters per session and 6000 per message. Malformed, missing, compacted and truncated input is reported. Tool/nontext/sidechain content is omitted; coverage is always labelled partial. Claude duplicate UUIDs are removed; Codex reads response messages only, omitting mirrored event messages. Line references are used when stable message IDs are absent. The agent must still exclude retries, copied context and equivalent duplicated records when counting independent occasions. Raw output is evidence to analyze in the active conversation; never persist it in TDT. Summaries alone cannot establish independent recurrence reliably.

Return at most ten candidates with proposed name, purpose, reusable steps, inputs, recurrence count, source session/turn references, limitations, overlapping skills and why reuse helps. Two separate occasions may be in one session or several; multiple tool calls for one request count once. Discovery never creates skills until the user selects and approves them. If none qualify, show an empty result and coverage limitations. Installing the discovery skill does not grant access to conversation history.

Enabled integrations

Approved skills always keep their full content in .tdt/skills/. Bridges are created only for enabled hosts. Ask your agent to enable the other integration when needed; there is no dedicated enablement skill. Terminal alternatives: tdt agent enable claude or tdt agent enable codex adds all existing skills to that host and keeps their original ownership. Restart the host session for discovery. If a pending update reports changed integration ownership, propose it again before reviewing it.

MCP skill inspection and decisions

When the workspace-bound MCP server is available, tdt_skill_proposals lists retained proposals (pending by default; approved, declined and all are explicit filters). tdt_skill_proposal_read reads the complete proposal by its exact content ID, including sources, decision reference and original/current recorded ownership. Read complete content before discussing a decision; increase the result budget if needed. Cursors expire when proposal or ownership state changes. A retained approval does not establish that its version is currently installed, and ownership metadata does not verify files on disk. These tools neither execute instructions nor access host history. The everyday profile also exposes tdt_skill_propose with the same proposal fields and an explicit update boolean (default false), and tdt_skill_review with one id, decision (approve/decline) and actual user_instruction reference. CLI review still supports batches. Both return small ID/status receipts that fit the minimum budget; read complete proposals before review. After uncertainty, inspect the retained proposal and live inventory before retry or CLI fallback. Repeated proposals can reopen historical behavior against current ownership; never retry blindly. Interrupted transactions require CLI recovery and fresh reads. Proposal/review use the shared CLI core, exclusive lock and ownership checks. Registry reads and proposed writes are capped at 2 MiB before mutation.

Use tdt_skill_inventory before proposing skills to compare live content from canonical, Claude and Codex skill folders, including unmanaged entries. Follow all pages and also read tdt_skill_proposals with status: all. Content prefixes are capped at 16384 characters; truncated entries are incomplete evidence. Owner labels follow CLI attribution and do not verify hashes or grant overwrite permission. Cursors bind the visible inventory, including prefixes and ownership; changes beyond a truncated prefix are not detected. The shared CLI inventory refuses scans over 1000 directory entries, user registries over 2 MiB, stack registries over 1 MiB and interrupted skill/stack transactions. MCP reads hold a shared workspace lock and never execute skills or inspect host history.