Skip to content

Conversation

@ElleNajt
Copy link
Contributor

@ElleNajt ElleNajt commented Oct 24, 2025

This PR implements automatic transcript saving that captures complete conversation history for archival purposes.

Features

Auto-saves transcripts as conversations progress:

  • User prompts with timestamps
  • Agent responses (streamed in real-time)
  • Tool calls with status, commands, and output

Enabled by default - transcripts save to .agents/transcripts/{timestamp}.txt

Note on format: Transcripts are optimized for human readability (timestamped, formatted text). [Edit: This next sentence is wrong - ACP does support restoring sessions] While ACP doesn't currently support restoring sessions, a future enhancement could add a parallel machine-readable format for session restoration.

Configurable:

;; Disable if desired
(setq agent-shell-auto-save-transcript nil)

;; Change directory
(setq agent-shell-transcript-directory ".my-transcripts")

;; Customize filename generation
(setq agent-shell-transcript-filename-function
      (lambda () (format "chat-%s.txt" (format-time-string "%Y%m%d"))))

Relationship to shell-maker

This is separate from shell-maker's manual save functionality:

  • shell-maker: Manual save on-demand or prompted save-on-close
  • This feature: Automatic background archival to project directory

Users can use both, either, or neither depending on their needs.

Example transcript format

Agent Shell Transcript
Started: 2025-10-24 18:00:00
Working Directory: /Users/elle/code/agent-shell

============================================================

[2025-10-24 18:00:05] USER:
list files

[2025-10-24 18:00:06] AGENT:
I'll list the files in the current directory.

[2025-10-24 18:00:07] TOOL CALL [completed]:
  Tool: bash - Execute bash command
  Title: List files
  Command: ls -la
  Output:
total 256
drwxr-xr-x  15 elle  staff   480 Oct 24 18:00 .
...

Closes #63 - Auto-save transcripts without prompting

@ElleNajt ElleNajt force-pushed the en/transcriptsSaving branch from 273d9bd to 65508bc Compare October 24, 2025 22:22
@ElleNajt
Copy link
Contributor Author

ElleNajt commented Oct 25, 2025

Another benefit of doing something like this is that the buffers start to get laggy around 1M, and I'd like to have something like

(add-hook 'agent-shell-mode-hook
          (lambda ()
            (setq-local comint-buffer-maximum-size 50000)
            (add-hook 'comint-output-filter-functions 'comint-truncate-buffer nil t)))

In my personal config to keep the buffers manageable, and be able to look up the history if desired.

Perhaps I should open the that as a separate issue though.

@xenodium
Copy link
Owner

xenodium commented Oct 25, 2025

Thanks for the PR. Sorry, not had a chance to review. May need a little time...

Another benefit of doing something like this is that the buffers start to get laggy around 1M, and I'd like to have something like

1M characters? Something else? Could you please file a bug about this with more details? Bonus points if you investigate your laggy case. I spent some time recently chasing optimizations after a friend mentioned laggy buffers for codex agent. These helped, but I'm sure we can optimize elsewhere.

Also, when reproducing the laggy scenario, make sure you update to the latest acp.el and logging is turned off (including saving any traffic), via M-x agent-shell-toggle-logging. Older acp.el versions saved traffic regardless.

Btw, you prolly already know this (and not a solution), but the "clear" command wipes the content of the buffer but doesn't wipe agent history.

Also, the markdown-overlay implementation is super expensive, specially for code blocks. If you comment out all of the (markdown-overlays-put), does your buffer still get laggy at 1M?

@ElleNajt
Copy link
Contributor Author

ElleNajt commented Oct 26, 2025

1M characters, yes.

Btw, you prolly already know this (and not a solution), but the "clear" command wipes the content of the buffer but doesn't wipe agent history.

Ah, I didn't know this. I thought it was like /clear in claude, which does clear the agents context window. tbh, probably clear should mean to clear the context window ? I don't see a method in ACP for this though.

Could you please file a bug about this with more details?
Yes!

btw, looked more at ACP, and it does support restoring sessions: https://agentclientprotocol.com/protocol/session-setup#loading-sessions

xenodium added a commit that referenced this pull request Oct 26, 2025
@xenodium
Copy link
Owner

Ah, I didn't know this. I thought it was like /clear in claude, which does clear the agents context window. tbh, probably clear should mean to clear the context window ? I don't see a method in ACP for this though.

We're getting the "clear" command from "shell-maker" which merely clears shell content. I'm in two minds about also making it clear the agent. The convention seems to be that / is needed to operate on agent, though I can see how what we have today is confusing.

btw, looked more at ACP, and it does support restoring sessions: https://agentclientprotocol.com/protocol/session-setup#loading-sessions

While it's in the protocol, not all agents seem to support it. I've added a display of agent capabilities to surface these details more prominently

Screenshot 2025-10-26 at 15 14 11

Copy link
Owner

@xenodium xenodium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Here are some initial comments to get things going...

agent-shell.el Outdated
:type '(repeat string)
:group 'agent-shell)

(defcustom agent-shell-auto-save-transcript t
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before opening the feature up for customizations, I'd like to give it some time to settle. This gives us time to use it, get a feel for it, and tweak without necessarily breaking users (if we decide to change settings around). Also gives us an opportunity to figure out how to reconcile this feature with the transcript feature in shell-maker (we need to turn that off, for example).

I'd say let's drop agent-shell-auto-save-transcript (we default to autosave) and agent-shell-transcript-directory for now. Let's rename agent-shell-transcript-filename-function to agent-shell--transcript-file-path-function (also private defvar).

For now if anyone would like to disable things, set agent-shell--transcript-file-path-function to nil.

This private var/function can take care of not just creating the file name but the entire path to write to.

Copy link
Owner

@xenodium xenodium Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now if anyone would like to disable things, set agent-shell--transcript-file-path-function to nil.

On second thought, can we make this nil by default and create an internal function we can set it to for the time being? This gives us the opportunity to override ourselves and use it for a bit of time before we roll it out to others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me!

@xenodium
Copy link
Owner

Example transcript format

Not for this PR, but we should consider iterating on log format later on. For example, we can maybe consider saving as .md. An upside is that opening in Emacs itself automatically gives us the ability to collapse and expand bits.

ElleNajt added a commit to ElleNajt/agent-shell that referenced this pull request Oct 28, 2025
- Remove customization variables (agent-shell-auto-save-transcript,
  agent-shell-transcript-directory, agent-shell-transcript-filename-function)
- Create private agent-shell--transcript-file-path-function (nil by default)
- Add agent-shell--default-transcript-file-path internal function
- Change directory path from .agents/transcripts to .agent-shell/transcripts
- Add agent name to transcript header
- Refactor agent-shell--append-transcript to use :file-path keyword arg
- Create agent-shell--make-transcript-tool-call-entry helper function
- Group all transcript functions under ;;; Transcript section

Transcripts are now disabled by default for testing before rollout.
Set agent-shell--transcript-file-path-function to enable.

(with-eval-after-load 'agent-shell
  (setq agent-shell--transcript-file-path-function
        #'agent-shell--default-transcript-file-path))

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ElleNajt
Copy link
Contributor Author

Thanks for the feedback. Made the changes. Also, since it was a quick change, swapped from .txt to .md. Agreed that it makes sense to iterate on the log format.

Copy link
Owner

@xenodium xenodium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the changes. LGTM, though looks like it needs to update to the latest to resove conflicts.

Added some minor comments. Mind addressing those when you resolve the conflicts?

ElleNajt added a commit to ElleNajt/agent-shell that referenced this pull request Oct 28, 2025
Changes:
- Use when-let* to flatten nested conditionals in init-transcript
- Convert escaped newlines to actual multi-line strings for readability
- Remove emojis from headers (User/Agent instead of 👤/🤖)
- Remove redundant with-current-buffer wrappers (ACP callbacks run in buffer)
- Inline variables in tool call logging (more concise)
- Remove internal testing note from docstring
- Simplify docstrings where appropriate

All transcript code remains in the ;;; Transcript section for organization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
ElleNajt and others added 6 commits October 28, 2025 16:58
Implements automatic transcript saving that captures complete conversation
history including user prompts, agent responses, and tool executions.

Features:
- Enabled by default, saves to .agents/transcripts/{timestamp}.txt
- Captures all three conversation elements:
  * User prompts with timestamps
  * Agent responses (streamed chunks)
  * Tool calls (when completed/failed) with output
- Configurable directory and filename generation

Configuration:
- agent-shell-auto-save-transcript (t by default, set to nil to disable)
- agent-shell-transcript-directory (".agents/transcripts")
- agent-shell-transcript-filename-function (timestamp generator)

This is separate from shell-maker's manual save functionality - this
auto-saves in the background for archival/debugging purposes.

Closes xenodium#63 - Auto-save transcripts without prompting
- Remove customization variables (agent-shell-auto-save-transcript,
  agent-shell-transcript-directory, agent-shell-transcript-filename-function)
- Create private agent-shell--transcript-file-path-function (nil by default)
- Add agent-shell--default-transcript-file-path internal function
- Change directory path from .agents/transcripts to .agent-shell/transcripts
- Add agent name to transcript header
- Refactor agent-shell--append-transcript to use :file-path keyword arg
- Create agent-shell--make-transcript-tool-call-entry helper function
- Group all transcript functions under ;;; Transcript section

Transcripts are now disabled by default for testing before rollout.
Set agent-shell--transcript-file-path-function to enable.

(with-eval-after-load 'agent-shell
  (setq agent-shell--transcript-file-path-function
        #'agent-shell--default-transcript-file-path))

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Bug: After the first agent response, subsequent responses were missing
the [timestamp] AGENT: header in transcripts.

Root cause: :last-entry-type was not reset when a new user prompt was
sent, causing the agent_message_chunk handler to skip writing the header
for subsequent responses.

Fix: Reset :last-entry-type to nil at the start of agent-shell--send-command
to ensure each new conversation turn starts with a clean state.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Change file extension from .txt to .md
- Use markdown header (#) for transcript title
- Use markdown metadata (bold text) for agent, timestamp, and directory
- Use ## headers with emoji for user (👤) and agent (🤖) messages
- Use <details>/<summary> collapsible sections for tool calls
- Format tool call output in code blocks with backticks
- Add horizontal rule (---) after header

Benefits:
- Better readability when viewed in editors or GitHub
- Collapsible tool call sections reduce clutter
- Syntax highlighting for code outputs
- Native markdown rendering in most tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Use when-let* to flatten nested conditionals in init-transcript
- Convert escaped newlines to actual multi-line strings for readability
- Remove emojis from headers (User/Agent instead of 👤/🤖)
- Remove redundant with-current-buffer wrappers (ACP callbacks run in buffer)
- Inline variables in tool call logging (more concise)
- Remove internal testing note from docstring
- Simplify docstrings where appropriate

All transcript code remains in the ;;; Transcript section for organization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ElleNajt ElleNajt force-pushed the en/transcriptsSaving branch 2 times, most recently from fdd7855 to 3ec6843 Compare October 28, 2025 21:03
@xenodium
Copy link
Owner

Hi @ElleNajt I got notification of some commits addressing comments. Thank you! Are you finished with the changes? If so, I'll look into merging.

@ElleNajt
Copy link
Contributor Author

Hi -- yes, finished with the changes! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configuration to save transcripts automatically to a given location

2 participants