> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tasks

> With a single command, Thor can summarize, assign, categorize and organize your tasks.

export const McpResult = ({children}) => <div className="hidden group-data-[chat=mcp]:block font-mono text-[13px] leading-relaxed mt-4">
    <div className="mb-1.5 flex items-center gap-2">
      <span className="rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide bg-[#1f6feb]/25 text-[#79c0ff] border border-[#1f6feb]/40">
        thor
      </span>
      <span className="text-[11px] text-[#8b949e]">response</span>
    </div>
    <div className="rounded-md border border-[#1f6feb]/35 bg-[#0d1117] px-3 py-2.5 border-l-[3px] border-l-[#1f6feb]">
      <div className="min-w-0 text-[#c9d1d9] whitespace-pre-wrap">{children}</div>
    </div>
  </div>;

export const McpPrompt = ({children}) => <div className="hidden group-data-[chat=mcp]:block font-mono text-[13px] leading-relaxed">
    <div className="mb-1.5 flex items-center gap-2">
      <span className="rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide bg-[#238636]/25 text-[#3fb950] border border-[#238636]/40">
        you
      </span>
      <span className="text-[11px] text-[#8b949e]">prompt</span>
    </div>
    <div className="rounded-md border border-[#30363d] bg-[#161b22] px-3 py-2.5">
      <div className="flex gap-2">
        <span className="shrink-0 select-none text-[#3fb950] font-bold">›</span>
        <div className="min-w-0 text-[#e6edf3]">{children}</div>
      </div>
    </div>
  </div>;

export const Mention = ({children}) => <>
    <span className="text-[#1264A3] dark:text-[#1D9BD1] font-medium group-data-[chat=teams]:hidden group-data-[chat=mcp]:hidden">
      @{children}
    </span>
    <span className="hidden group-data-[chat=teams]:inline-flex items-center rounded px-1 mx-0.5 text-[#5B5FC7] dark:text-[#A6A7DC] bg-[#5B5FC7]/10 dark:bg-[#5B5FC7]/20 font-medium">
      @{children}
    </span>
  </>;

export const Message = ({name, bot = false, self = false, time, color, avatar: avatarUrl, children}) => {
  const thorAvatar = "/images/thor-icon.svg";
  const youAvatar = "/images/you-avatar.jpg";
  const resolvedName = bot ? "Thor" : self ? "You" : name || "Alex";
  const resolvedColor = color || "#5095dd";
  const imageAvatar = avatarUrl || (bot ? thorAvatar : self ? youAvatar : null);
  const imagePad = bot && !avatarUrl;
  const avatarNode = () => {
    if (imageAvatar) {
      return <>
          <img src={imageAvatar} alt={resolvedName} className={`h-9 w-9 rounded-lg object-cover shrink-0 group-data-[chat=teams]:hidden ${imagePad ? "bg-[#D9E3E6] p-1.5 object-contain" : ""}`} />
          <img src={imageAvatar} alt={resolvedName} className={`hidden h-8 w-8 rounded-full object-cover shrink-0 group-data-[chat=teams]:block ${imagePad ? "bg-[#E8E8F0] dark:bg-[#2B2B36] p-1 object-contain" : ""}`} />
        </>;
    }
    return <>
        <div className="h-8 w-8 rounded-lg shrink-0 flex items-center justify-center text-white text-xs font-semibold group-data-[chat=teams]:hidden" style={{
      backgroundColor: resolvedColor
    }}>
          {resolvedName.slice(0, 1).toUpperCase()}
        </div>
        <div className="hidden h-8 w-8 rounded-full shrink-0 items-center justify-center text-white text-xs font-semibold group-data-[chat=teams]:flex" style={{
      backgroundColor: resolvedColor
    }}>
          {resolvedName.slice(0, 1).toUpperCase()}
        </div>
      </>;
  };
  return <>
      <div className="flex gap-2.5 items-start rounded-lg px-2 py-1.5 hover:bg-zinc-50 dark:hover:bg-white/5 group-data-[chat=teams]:hidden group-data-[chat=mcp]:hidden">
        {avatarNode()}
        <div className="min-w-0 flex-1">
          <div className="flex items-baseline gap-2 flex-wrap">
            <span className="text-[15px] font-bold text-zinc-900 dark:text-zinc-100">
              {resolvedName}
            </span>
            {bot ? <span className="rounded px-1 py-px text-[10px] font-bold uppercase tracking-wide bg-[#E8F5FA] text-[#1264A3] dark:bg-[#1D9BD1]/20 dark:text-[#1D9BD1]">
                App
              </span> : null}
            {time ? <span className="text-[12px] text-zinc-500">{time}</span> : null}
          </div>
          <div className="text-[15px] leading-relaxed text-zinc-800 dark:text-zinc-200 mt-0.5">
            {children}
          </div>
        </div>
      </div>

      <div className="hidden group-data-[chat=teams]:flex gap-2.5 items-start">
        {avatarNode()}
        <div className="min-w-0 max-w-[92%]">
          <div className="flex items-baseline gap-2 mb-1">
            <span className="text-[13px] font-semibold text-zinc-900 dark:text-zinc-100">
              {resolvedName}
            </span>
            {bot ? <span className="rounded px-1 py-px text-[10px] font-semibold uppercase tracking-wide bg-[#5B5FC7]/15 text-[#5B5FC7] dark:text-[#A6A7DC]">
                Bot
              </span> : null}
            {time ? <span className="text-[11px] text-zinc-500">{time}</span> : null}
          </div>
          <div className={`rounded-md px-3 py-2 text-[13px] leading-relaxed text-zinc-800 dark:text-zinc-100 shadow-sm ${bot ? "bg-white dark:bg-[#292929] border border-[#5B5FC7]/25" : "bg-white dark:bg-[#292929]"}`}>
            {children}
          </div>
        </div>
      </div>
    </>;
};

export const Conversation = ({channel = "general", type = "channel", defaultPlatform, platforms = "slack,teams,mcp", children}) => {
  const available = platforms.split(",").map(p => p.trim()).filter(Boolean);
  const initial = defaultPlatform && available.includes(defaultPlatform) ? defaultPlatform : available[0] || "slack";
  const [platform, setPlatform] = useState(initial);
  const thorAvatar = "/images/thor-icon.svg";
  const isDm = type === "dm";
  const title = isDm ? "Thor" : channel.replace(/^#/, "");
  const showTabs = available.length > 1;
  const tabClass = active => `inline-flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-xs font-medium transition-colors ${active ? "bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm" : "text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`;
  const slackIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M4.5 12.7a1.6 1.6 0 1 1-1.6-1.6h1.6v1.6zm.8 0a1.6 1.6 0 1 1 3.2 0v4a1.6 1.6 0 1 1-3.2 0v-4zM7.3 4.5a1.6 1.6 0 1 1 1.6-1.6v1.6H7.3zm0 .8a1.6 1.6 0 1 1 0 3.2h-4a1.6 1.6 0 1 1 0-3.2h4zM15.5 7.3a1.6 1.6 0 1 1 1.6 1.6h-1.6V7.3zm-.8 0a1.6 1.6 0 1 1-3.2 0v-4a1.6 1.6 0 1 1 3.2 0v4zM12.7 15.5a1.6 1.6 0 1 1-1.6 1.6v-1.6h1.6zm0-.8a1.6 1.6 0 1 1 0-3.2h4a1.6 1.6 0 1 1 0 3.2h-4z" />
    </svg>;
  const teamsIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M11.2 4.2a2.4 2.4 0 1 1 2.5 2.4h-.1a2.4 2.4 0 0 1-2.4-2.4zm-6.3.6a2.1 2.1 0 1 1 2.2 2h-.1a2.1 2.1 0 0 1-2.1-2zm6.5 3.4h4.2c.8 0 1.4.6 1.4 1.4v4.1a3.4 3.4 0 0 1-3.4 3.4h-.3A4.3 4.3 0 0 0 17 13.2V8.8c0-.9-.7-1.6-1.6-1.6h-4zm-6.6.3h4.6c.7 0 1.3.6 1.3 1.3v5.1A3.7 3.7 0 0 1 7 18.6H6.3A3.7 3.7 0 0 1 2.6 14.9V9.8c0-.7.6-1.3 1.3-1.3z" />
    </svg>;
  const mcpIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M4 5.5A1.5 1.5 0 0 1 5.5 4h9A1.5 1.5 0 0 1 16 5.5v9a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 4 14.5v-9zM6 7v1.5h1.75V7H6zm3.25 0v1.5H11V7H9.25zM12.5 7v1.5H14.25V7H12.5zM6 10v1.5h8.25V10H6zm0 3v1.5h5V13H6z" />
    </svg>;
  let frame;
  if (platform === "mcp") {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-700 shadow-sm not-prose bg-[#0d1117]">
        <div className="flex items-center gap-2 border-b border-zinc-700/80 bg-[#161b22] px-3 py-2">
          <div className="flex items-center gap-1.5">
            <span className="h-2.5 w-2.5 rounded-full bg-[#ff5f56]" />
            <span className="h-2.5 w-2.5 rounded-full bg-[#ffbd2e]" />
            <span className="h-2.5 w-2.5 rounded-full bg-[#27c93f]" />
          </div>
          <div className="min-w-0 flex-1 text-center font-mono text-[11px] text-[#8b949e] truncate">
            thor mcp — cursor / claude
          </div>
          <div className="w-10" />
        </div>
        <div className="px-4 py-4 space-y-1 min-h-[7rem]">
          <div className="font-mono text-[11px] text-[#8b949e] mb-3">
            <span className="text-[#79c0ff]">mcp</span>
            <span className="text-[#8b949e]">:</span>
            <span className="text-[#a5d6ff]">thor</span>
            <span className="text-[#8b949e]">$ </span>
            <span className="text-[#c9d1d9]">ask</span>
          </div>
          {children}
          <div className="font-mono text-[13px] text-[#7ee787] mt-4 animate-pulse">
            ▍
          </div>
        </div>
      </div>;
  } else if (platform === "teams") {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm not-prose">
        <div className="flex items-center gap-2.5 bg-[#5B5FC7] px-3 py-2.5">
          {isDm ? <img src={thorAvatar} alt="" className="h-6 w-6 rounded-full bg-white/90 p-0.5 object-contain" /> : <div className="flex h-6 w-6 items-center justify-center rounded bg-white/15 text-white text-xs font-bold">
              #
            </div>}
          <div className="min-w-0">
            <div className="text-sm font-semibold text-white truncate">
              {title}
            </div>
            <div className="text-[11px] text-white/70">
              {isDm ? "Chat · Microsoft Teams" : "Microsoft Teams"}
            </div>
          </div>
        </div>
        <div className="bg-[#F5F5F5] dark:bg-[#1F1F1F] px-3 py-3 space-y-3">
          {children}
        </div>
      </div>;
  } else {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm not-prose">
        <div className="flex items-center gap-2 border-b border-zinc-200 dark:border-zinc-700 bg-white dark:bg-[#1A1D21] px-3 py-2.5">
          {isDm ? <img src={thorAvatar} alt="" className="h-5 w-5 rounded bg-[#D9E3E6] p-0.5 object-contain" /> : <span className="text-zinc-500 dark:text-zinc-400 text-lg leading-none">
              #
            </span>}
          <span className="text-sm font-bold text-zinc-900 dark:text-zinc-100">
            {title}
          </span>
        </div>
        <div className="bg-white dark:bg-[#1A1D21] px-2 py-3 space-y-1">
          {children}
        </div>
      </div>;
  }
  return <div className="my-4 not-prose group" data-chat={platform}>
      {showTabs ? <div className="mb-2 inline-flex flex-wrap items-center rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 p-0.5">
          {available.includes("slack") ? <button type="button" onClick={() => setPlatform("slack")} className={tabClass(platform === "slack")}>
              {slackIcon()}
              Slack
            </button> : null}
          {available.includes("teams") ? <button type="button" onClick={() => setPlatform("teams")} className={tabClass(platform === "teams")}>
              {teamsIcon()}
              Teams
            </button> : null}
          {available.includes("mcp") ? <button type="button" onClick={() => setPlatform("mcp")} className={tabClass(platform === "mcp")}>
              {mcpIcon()}
              MCP
            </button> : null}
        </div> : null}

      {frame}

      {platform === "mcp" && showTabs ? <p className="mt-2 text-xs text-zinc-500 dark:text-zinc-400">
          Same workflows via Thor's{" "}
          <a href="/usecases/mcp" className="underline underline-offset-2">
            MCP server
          </a>{" "}
          in Cursor, Claude, or any MCP client.
        </p> : null}
    </div>;
};

# Pre-requisites

To have Thor perform task management features you will need to connect at least one task management platform. Currently Thor supports **GitHub** and **Linear** issues.

# Use cases

## Convert a thread into a task

Thor can automatically summarize and extract any important action items from a long thread, and convert it into a task for you:

<Conversation channel="eng">
  <Message name="Sam" color="#E01E5A" time="2:14 PM">
    Okay so to recap — we need to fix the flaky auth redirect on mobile, add a
    regression test, and ping design once it's up. Who can take this?
  </Message>

  <Message self time="2:15 PM">
    Hey <Mention>Thor</Mention>, can you create a task for the team based on this discussion?
  </Message>

  <Message bot time="2:15 PM">
    Created **Linear ENG-1842**: Fix flaky auth redirect on mobile. Description includes the regression test ask and the design follow-up from this thread. Want me to assign it to someone?
  </Message>

  <McpPrompt>
    Use the Thor MCP to create a task from the #eng discussion about the flaky auth redirect on mobile.
  </McpPrompt>

  <McpResult>
    Created Linear ENG-1842: Fix flaky auth redirect on mobile
    Includes regression-test ask + design follow-up from the thread.
  </McpResult>
</Conversation>

If you don't have a default repository configured, Thor will prompt you to choose one.

## Search for existing tasks

Have Thor retrieve an existing task based on a freeform query:

<Conversation type="dm">
  <Message self time="10:21 AM">
    Hey <Mention>Thor</Mention>, do we have any tasks logged for the authentication bug yet?
  </Message>

  <Message bot time="10:21 AM">
    Yes — **ENG-1842** ("Fix flaky auth redirect on mobile") was created earlier today from the #eng thread. Status: Todo. Want me to open it or assign it?
  </Message>

  <McpPrompt>
    Use the Thor MCP to find any tasks logged for the authentication bug.
  </McpPrompt>

  <McpResult>
    ENG-1842 — Fix flaky auth redirect on mobile (Todo)
    Created earlier today from the #eng thread.
  </McpResult>
</Conversation>

## Assign and categorize tasks

Have Thor automatically assign and categorize your tasks:

<Conversation type="dm">
  <Message self time="10:24 AM">
    Hey <Mention>Thor</Mention>, assign issue #123 to @John and tag it with any relevant labels.
  </Message>

  <Message bot time="10:24 AM">
    Done — assigned #123 to John and added labels **bug**, **auth**, and **mobile**.
  </Message>

  <McpPrompt>
    Use the Thor MCP to assign issue #123 to John and apply relevant labels.
  </McpPrompt>

  <McpResult>
    Assigned #123 → John
    Labels: bug, auth, mobile
  </McpResult>
</Conversation>

## Delegate to coding agents

<iframe className="w-full aspect-video rounded-xl" src="https://www.youtube.com/embed/ajQsvq4ZKEI" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

Have Thor assess if a task is suited for delegation to your favorite AI coding assistant. Currently supported coding agents are Cursor, Claude, Tembo and Charlie.

<Conversation type="dm">
  <Message self time="11:05 AM">
    Hey <Mention>Thor</Mention>, is issue #123 a good candidate for a coding agent? If yes, assign it to Cursor.
  </Message>

  <Message bot time="11:05 AM">
    Yes — it's well-scoped, has clear acceptance criteria, and doesn't need product judgment. Assigned #123 to Cursor and attached the related thread context.
  </Message>

  <McpPrompt>
    Use the Thor MCP to check if issue #123 is a good coding-agent candidate, and if so assign it to Cursor.
  </McpPrompt>

  <McpResult>
    Yes — well-scoped, clear acceptance criteria.
    Assigned #123 → Cursor (thread context attached).
  </McpResult>
</Conversation>

For tighter integration, you can also connect Cursor or Claude to Thor's [MCP server](/usecases/mcp), which lets your coding agent pull issue context, related discussions and prior decisions directly from Thor.

## Task Subscriptions

Thor can monitor tasks for important updates, comments and changes, then notify you via DM when this occurs:

<Conversation type="dm">
  <Message self time="4:40 PM">
    Hey <Mention>Thor</Mention>, let me know when someone starts work on issue #145.
  </Message>

  <Message bot time="4:40 PM">
    Got it — I'll DM you when #145 moves out of Todo or gets an assignee. You can also ask me to watch for blocked or completed.
  </Message>

  <McpPrompt>
    Use the Thor MCP to notify me when someone starts work on issue #145.
  </McpPrompt>

  <McpResult>
    Subscribed to #145 — will alert when it leaves Todo or gets an assignee.
  </McpResult>
</Conversation>

Other examples:

<Note>Hey `@Thor`, notify me when github.com/microsoft/vscode/issues/145 is completed</Note>
<Note>Hey `@Thor`, alert me if issue #42 gets blocked or closed</Note>
