Skip to content

Conversation

@csheaff
Copy link

@csheaff csheaff commented Jan 18, 2026

Fixes #122

I've tested this with Claude Code and Copilot CLI. Unfortunately I realized in the process that I need persistent sessions with remote, as I often times lose connection. So SSH isn't ideal. But perhaps this PR will be useful for others with stable connections.

- Add agent-shell--tramp-command-runner to run agents on remote hosts via SSH
- Add agent-shell--resolve-tramp-path to convert paths between TRAMP and remote-local format
- Add agent-shell-enable-tramp-support and agent-shell-disable-tramp-support commands
- Fix temporary-file-directory returning remote path when default-directory is TRAMP path (icon caching bug)

Closes xenodium#122
For remote TRAMP sessions, save transcripts to ~/.agent-shell/transcripts/<host>/<path>/
instead of the remote filesystem. This avoids slow TRAMP file operations on every append.
- Add agent-shell--local-temp-directory helper for cross-platform temp paths
- Fix fallback icon caching to use local temp directory
- Use ~/tmp instead of /tmp for Windows compatibility
- Add ERT tests for TRAMP functions
- Add README.org documentation for TRAMP support
- Error explicitly on multi-hop TRAMP paths (prevents silent wrong-host execution)
- Use locate-user-emacs-file for cache instead of ~/tmp
- Add declare-function for tramp-file-name-hop
- Add negative ERT tests for multi-hop and unsupported methods
- All 23 tests pass
@xenodium
Copy link
Owner

Thank you for kicking this off!

I need to start breaking the agent-shell.el sections into sub packages. Mind if we move the TRAMP functionality to a new file, say agent-shell-tramp.el?

ps. I'm not using TRAMP myself, so may be good to ping the feature request at #122 and ask for feedback or folks to try it out.

Move TRAMP-specific functions to a separate file per maintainer request:
- agent-shell--tramp-command-runner
- agent-shell--resolve-tramp-path
- agent-shell-enable-tramp-support
- agent-shell-disable-tramp-support
- agent-shell--tramp-transcript-dir

Keep agent-shell--local-temp-directory in main file as it's needed
for icon caching even without TRAMP support.

Add autoloads for enable/disable commands.
@csheaff csheaff mentioned this pull request Jan 20, 2026
@fritzgrabo
Copy link
Contributor

fritzgrabo commented Jan 20, 2026

This is awesome -- love how support for containers and now TRAMP make agent-shell such a flexible tool for use with agents.

@csheaff re. the unstable connection issues you mention in the issue, maybe have a look at detached.el, and more importantly, the dtach tool it uses under the hood. It certainly adds another layer of indirection, but would help the session survive a reconnect.

Re. the PR, I was wondering if we could make TRAMP transparent, in the sense that it prefixes the command to run and resolves paths to/from remote machines automatically? After all, you should be able to defer from the current cwd and file path whether it's using TRAMP or not, so could bake that into the default logic, without the need to use agent-shell-container-command-runner or agent-shell-path-resolver-function at all.

UPDATE: just realized that not everybody would want to run the agent on the remote machine. which is likely why you went with the custom functions to manually toggle the feature -- got it 💡. The PR's issue mentions how eglot runs the server on the remote machine transparently, and if I read the code right, that happens automatically for remote working directories (at least I didn't find anything in eglot.el that would prefix the command to run with ssh ...). Should the same behavior should be the default in agent-shell then, and opting out of it should be toggled by a flag?

What do you think?

@csheaff
Copy link
Author

csheaff commented Jan 20, 2026

Hey @fritzgrabo , thanks for the feedback. In addition to removing the disable/enable functionality, I've attempted to use make-process as Eglot does. However agent-shell stalls for some reason and I need to move on to other work for rest of the week. @xenodium This requires some updates to acp.el i think:

  • adding :file-handler t to the make-process call in acp.el (line 130)
  • addressing the fact that TRAMP's file handler isn't compatible with the stderr handling in acp.el ( eglot.el line ~1794: uses (get-buffer-create ...) for stderr, not a pipe process)

I will attempt to fix next weekend if i can find some time.

@junyi-hou
Copy link

I tried it a little bit and here's what I found:

  • the ssh HOST -- claude-code-acp trick does not work if claude-code-acp is install in a customized place because this does not source the profile/rc file on the remote, changing the prefix to ssh HOST -- zsh -lc (or bash lc) fix this. i.e.
(defun agent-shell--tramp-command-runner (buffer)
  "Return command prefix for running commands on TRAMP remote host.
BUFFER is the agent-shell buffer.
Returns nil for non-TRAMP buffers, allowing local execution."
  (require 'tramp)
  (with-current-buffer buffer
    (let ((cwd (agent-shell-cwd)))
      (when (tramp-tramp-file-p cwd)
        (let* ((vec (tramp-dissect-file-name cwd))
               (method (tramp-file-name-method vec))
               (user (tramp-file-name-user vec))
               (host (tramp-file-name-host vec))
               (port (tramp-file-name-port vec)))
          (unless (member method '("ssh" "scp" nil))
            (error "TRAMP method '%s' not supported; only SSH is supported" method))
          (when (tramp-file-name-hop vec)
            (error "Multi-hop TRAMP paths not supported"))
          (append
           (list "ssh")
           (when port (list "-p" port))
           (list (if user (format "%s@%s" user host) host))
           (list "--" "zsh" "-lc")))))))
  • the environment variable set in agent-shell-anthropic-claude-environment doesn't seem to get pass onto the remote process. I was trying to add (when agent-shell-anthropic-claude-environment agent-shell-anthropic-claude-environment) to the list but this doesn't work with complex env variable (like ANTHROPIC_CUSTOM_HEADERS=OpenAI-Organization: xxx)

@junyi-hou
Copy link

environment variables can be passed in the following way:

(defun agent-shell-tramp-pass-env-var (var)
  "VAR should be output from `agent-shell-make-environment-variables`"
  (mapcar (lambda (env)
            (if-let* ((env-list (string-split env "="))
                      (value (cadr env-list))
                      (_ (string-match-p " " value)))
                (string-join `(,(car env-list) ,(format "'%s'" value)) "=")
              env))
          var))

to add quotes to the env variables

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.

Add tramp support

4 participants