\documentclass[11pt]{article}
\usepackage[margin=2.2cm]{geometry}
\usepackage{hyperref}
\usepackage{chatui}
\usepackage{xcolor}
\usepackage{textcomp}

%% Not breakable: these are short listings (a dozen lines at most), so if
%% one doesn't fit in the remaining page space it should push whole to the
%% next page, not split mid-block and leave an ugly gap.
\newtcolorbox{chatuicode}{%
  enhanced, colback=black!3, colframe=black!25, boxrule=0.4pt,
  arc=1.5mm, left=3mm, right=3mm, top=1.5mm, bottom=1.5mm,
  fontupper=\ttfamily\small
}

\title{\textbf{chatui}: a \LaTeX{} package for typesetting\\AI chat transcripts}
\author{Nilesh Verma \\ \texttt{me@nileshverma.com}}
\date{v1.0.0, 2026/08/21}

\begin{document}
\maketitle

\begin{abstract}
\noindent
\texttt{chatui} typesets AI chat transcripts: user/assistant messages,
reasoning (``thinking'') traces, tool-call traces, and file/image
attachments, styled as a \textbf{terminal}, \textbf{web}, or
\textbf{desktop} chat UI, in light or dark theme. It is meant for papers,
reports, and documentation that need to show a worked conversation with an
AI assistant, including the reasoning and tool calls behind a response,
without hand-rolling \texttt{tcolorbox} code for every figure.
\end{abstract}

\tableofcontents

\section{Installation}

Drop \texttt{chatui.sty} next to your \texttt{.tex} file, or into your
local texmf tree. Requires \texttt{tcolorbox} (\texttt{[most]} libraries),
\texttt{tikz}, \texttt{etoolbox}, \texttt{xparse}, \texttt{kvoptions},
\texttt{xcolor}, \texttt{pifont}, and \texttt{graphicx}, all standard and
present on any full \TeX~Live or MiK\TeX{} install.

\section{Quick start}

\begin{chatuicode}
\begin{verbatim}
\usepackage[style=web]{chatui}   % style = terminal | web | desktop

\begin{chatconversation}[chat.example.com]

\begin{chatuser}[John Doe]
How do I show tool calls in a LaTeX paper?
\end{chatuser}

\begin{chatthinking}
\tstep{User wants a reusable way to render tool-call traces.}
\end{chatthinking}

\begin{chattool}{web_search}
\toolargs{query="latex tool call trace package"}
\toolresult{3 results found.}
\end{chattool}

\begin{chatassistant}
Use the chattool environment: it renders a titled box with a
status glyph, plus \toolargs and \toolresult helpers.
\end{chatassistant}

\end{chatconversation}
\end{verbatim}
\end{chatuicode}

\noindent This renders as:

\begin{chatconversation}[chat.example.com]

\begin{chatuser}[John Doe]
How do I show tool calls in a LaTeX paper?
\end{chatuser}

\begin{chatthinking}
\tstep{User wants a reusable way to render tool-call traces.}
\end{chatthinking}

\begin{chattool}{web\_search}
\toolargs{query="latex tool call trace package"}
\toolresult{3 results found.}
\end{chattool}

\begin{chatassistant}
Use the \texttt{chattool} environment: it renders a titled box with a
status glyph, plus \texttt{\textbackslash toolargs} and
\texttt{\textbackslash toolresult} helpers.
\end{chatassistant}

\end{chatconversation}

\section{Package options}

\begin{description}
\item[\texttt{style}] \texttt{terminal} (monospace, shell-prompt look),
  \texttt{web} (rounded chat bubbles + browser chrome, \emph{default}), or
  \texttt{desktop} (macOS-style window with traffic-light dots).
\item[\texttt{theme}] \texttt{auto} (\emph{default}: \texttt{terminal} is
  dark, \texttt{web}/\texttt{desktop} are light), \texttt{light}, or
  \texttt{dark}. Dark theme uses the same palette across all three styles,
  so switching \texttt{style} under \texttt{theme=dark} doesn't change the
  color scheme, only the chrome.
\end{description}

\section{Environments and commands}

\subsection{\texttt{chatconversation}}

The outer window chrome (terminal title bar, browser bar, or macOS
window). Takes one optional argument, the title text shown in the bar:

\begin{chatuicode}
\begin{verbatim}
\begin{chatconversation}[chat.example.com]
  ...
\end{chatconversation}
\end{verbatim}
\end{chatuicode}

It is \texttt{breakable}: a long conversation flows across pages, and the
chrome is drawn once, on the first page only. See
Section~\ref{sec:pagebreaks}.

\subsection{\texttt{chatuser} / \texttt{chatassistant}}

Message bubbles. Both take one optional argument, the display name shown
above the bubble (styles \texttt{web} and \texttt{desktop}) or as the
shell prompt (style \texttt{terminal}):

\begin{chatuicode}
\begin{verbatim}
\begin{chatuser}[John Doe]
Where does the config file live?
\end{chatuser}

\begin{chatassistant}[Assistant]
It's at ~/.config/app/settings.toml.
\end{chatassistant}
\end{verbatim}
\end{chatuicode}

\subsection{\texttt{chatthinking}}

A reasoning/thinking trace box. Takes two optional arguments: the title
(default \texttt{Reasoning}) and the mode:

\begin{description}
\item[\texttt{steps}] (\emph{default}): arrow-prefixed bullets, one per
  \texttt{\textbackslash tstep\{...\}}.
\item[\texttt{paragraph}]: plain upright prose, for longer chains of
  thought that read better as continuous text than as bullets.
\end{description}

\begin{chatuicode}
\begin{verbatim}
\begin{chatthinking}
\tstep{Need to grep the repo for "auth" and "middleware".}
\tstep{Two candidate files found; the second is a test fixture.}
\end{chatthinking}

\begin{chatthinking}[Reasoning][paragraph]
This reads as ordinary prose instead of stepped bullets.
\end{chatthinking}
\end{verbatim}
\end{chatuicode}

\begin{chatthinking}
\tstep{Need to grep the repo for "auth" and "middleware".}
\tstep{Two candidate files found; the second is a test fixture.}
\end{chatthinking}

\begin{chatthinking}[Reasoning][paragraph]
This reads as ordinary prose instead of stepped bullets, which suits a
longer chain of thought better than a list of short arrow-prefixed lines.
\end{chatthinking}

\subsection{\texttt{chattool}}

A tool-call trace box. Takes two optional arguments (status, kind) and one
mandatory argument (the tool name):

\begin{description}
\item[\texttt{status}] \texttt{ok} (\emph{default}, \checkmark) \textbar{}
  \texttt{error} (\texttimes) \textbar{} \texttt{running} ($\cdots$).
\item[\texttt{kind}] \texttt{api} (\emph{default}, ``tool: name'' chip)
  \textbar{} \texttt{cli} (shell-style ``\$ name'') \textbar{}
  \texttt{code} (function-call style ``\texttt{</>} name'').
\end{description}

Inside, use \texttt{\textbackslash toolargs\{...\}},
\texttt{\textbackslash toolresult\{...\}}, or
\texttt{\textbackslash tooljson\{...\}} for the payload. JSON needs manual
\texttt{\textbackslash\textbackslash} line breaks and
\texttt{\textbackslash quad} for indentation, since \LaTeX{} does not
preserve literal whitespace.

\begin{chatuicode}
\begin{verbatim}
\begin{chattool}[ok][cli]{find . -name "*.log" | head -1}
\toolresult{./data/latest.log}
\end{chattool}

\begin{chattool}[ok][code]{get_weather(city="Austin")}
\toolargs{city="Austin"}
\tooljson{\{\\
\quad "temp_c": 34.2\\
\}}
\end{chattool}
\end{verbatim}
\end{chatuicode}

\begin{chattool}[ok][cli]{find . -name "*.log" | head -1}
\toolresult{./data/latest.log}
\end{chattool}

\begin{chattool}[ok][code]{get\_weather(city="Austin")}
\toolargs{city="Austin"}
\tooljson{\{\\
\quad "temp\_c": 34.2\\
\}}
\end{chattool}

\subsection{Attachments: \texttt{chatimage} and \texttt{chatfile}}

Use inside \texttt{chatuser}/\texttt{chatassistant} (or standalone) to
show an uploaded image or file. \texttt{chatimage} clips the image to the
bubble's own corner radius; \texttt{chatfile} renders a small bordered
chip with a document icon, filename, and size:

\begin{chatuicode}
\begin{verbatim}
\begin{chatassistant}
Here is the generated report:
\chatfile{crash-report.pdf}{212 KB}
\end{chatassistant}
\end{verbatim}
\end{chatuicode}

\begin{chatassistant}
Here is the generated report:
\chatfile{crash-report.pdf}{212 KB}
\end{chatassistant}

\section{Customizing colors}

Every color is a plain \texttt{xcolor} name. Redefine any of them after
loading the package, with a named color, a mix, or a raw hex code:

\begin{chatuicode}
\begin{verbatim}
\usepackage[style=web]{chatui}
\colorlet{chatuiUserBg}{teal}                    % named xcolor
\colorlet{chatuiAssistantBg}{gray!10}             % mixed
\definecolor{chatuiToolAccent}{HTML}{7C5CFC}      % raw hex
\end{verbatim}
\end{chatuicode}

Available color names:

\begin{itemize}
\setlength{\itemsep}{0pt}
\item \texttt{chatuiUserBg}, \texttt{chatuiUserFg}
\item \texttt{chatuiAssistantBg}, \texttt{chatuiAssistantFg},
  \texttt{chatuiAssistantBorder}
\item \texttt{chatuiThinkBg}, \texttt{chatuiThinkBorder},
  \texttt{chatuiThinkFg}
\item \texttt{chatuiToolBg}, \texttt{chatuiToolBorder},
  \texttt{chatuiToolAccent}
\item \texttt{chatuiOk}, \texttt{chatuiErr}, \texttt{chatuiWarn}:
  status glyphs and \texttt{chattool} accents
\item \texttt{chatuiAppBg}, \texttt{chatuiAppText}, \texttt{chatuiAppChrome},
  \texttt{chatuiAppChromeText}: web/desktop window chrome
\item \texttt{chatuiAppPillBg}, \texttt{chatuiAppPillBorder},
  \texttt{chatuiAppPillText}: web browser-bar URL pill
\item the \texttt{chatuiTerm*} family: terminal-style chrome and boxes
\end{itemize}

\section{Customizing fonts}

Two hooks control every font family in the package. Redefine them after
\texttt{\textbackslash usepackage} (and after loading any font package you
want to use):

\begin{chatuicode}
\begin{verbatim}
\usepackage{fourier}
\renewcommand{\chatuiFontSans}{\rmfamily}   % web/desktop bubbles, prose
\renewcommand{\chatuiFontMono}{\ttfamily}   % terminal + tool/code text
\end{verbatim}
\end{chatuicode}

Only sizing is fixed internally, tuned to each box's proportions; the
family is entirely yours to swap.

\section{Long conversations and page breaks}
\label{sec:pagebreaks}

The outer \texttt{chatconversation} window is breakable and splits cleanly
across pages: the chrome (title bar, dots) only draws once, on the
first page, and the border/background continue seamlessly on later pages.
Individual messages, reasoning boxes, and tool calls are each a single
atomic unit (they don't break mid-box), so a page break always falls
\emph{between} two messages, never through the middle of one, matching how
a real chat UI never splits a single message bubble. A single message
longer than a full page is an unsupported edge case.

\section{Known limitations}

\begin{itemize}
\item A single message, reasoning box, or tool call that is itself taller
  than one full page will not render correctly (see
  Section~\ref{sec:pagebreaks}).
\item \texttt{chatimage} loads the whole image once via
  \texttt{\textbackslash includegraphics}; very large source images will
  bloat the PDF as with any \LaTeX{} document.
\item No syntax highlighting for code inside tool results: payloads are
  plain monospace text.
\end{itemize}

\section{Version history}

\begin{description}
\item[v1.0.0 (2026/08/21)] First public release: three styles (terminal,
  web, desktop), light/dark/auto themes, reasoning traces (steps or
  paragraph), tool-call traces (api, cli, or code kinds, JSON payloads),
  image and file attachments, page-break-safe long conversations,
  customizable colors and fonts.
\end{description}

\section{License}

Released under the \LaTeX{} Project Public License (LPPL), version 1.3c or
later. See the \texttt{LICENSE} file.

\end{document}
