I used the TCP approach suggested by @wvxvw in the comments. I'm starting a TCP server inside emacs, which, when receiving a package, will eval it as elisp code. I found a piece of code for the TCP server somewhere in the internet (I can't seem to find it again, if anybody knows please leave a comment and I'll add to the answer), and made a few changes for the code evaluation:
;;; echo-server.el --- -*- lexical-binding: t -*-
;; Copyright (C) 2016-2017 York Zhao <email@example.com>
;; Author: York Zhao <firstname.lastname@example.org>
;; Created: June 1, 2016
;; Version: 0.1
;; Keywords: TCP, Server, Network, Socket
;; This file is NOT part of GNU Emacs.
;; This program is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free Software
;; Foundation; either version 3 of the License, or (at your option) any later
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; You should have received a copy of the GNU General Public License along with
;; this program. If not, see <http://www.gnu.org/licenses/>.
;; Running "M-x tcp-server-start" will prompt user to enter a port number to
;; listen to.
(defvar tcp-server-clients '()
"Alist where KEY is a client process and VALUE is the string")
(defvar tcp-server-servers '()
"Alist where KEY is the port number the server is listening at")
(defvar tcp-server-display-buffer-on-update nil
"If non-nil, force the process buffer to be visible whenever
new text arrives")
(defun tcp-server-make-process-name (port)
"Return server name of the process listening on PORT"
(format "tcp-server:%d" port))
(defun tcp-server-get-process (port)
"Return the server process that is listening on PORT"
(get-process (tcp-server-make-process-name port)))
(defun tcp-server-process-buffer (port)
"Return buffer of the server process that is listening on PORT"
(process-contact (tcp-server-get-process port) :buffer))
(defun tcp-server-delete-clients (server-proc)
(let ((server-proc-name (process-contact server-proc :name)))
(cl-loop for client in tcp-server-clients
if (string= server-proc-name (process-contact client :name))
(message "Deleted client process %s" client))
(cl-delete-if (lambda (client)
(string= (process-contact server-proc :name)
(process-contact client :name)))
(cl-defun tcp-server-start (port &optional (display-buffer-on-update nil)
"Start a TCP server listening at PORT"
(list (read-number "Enter the port number to listen to: " 9999)))
(let* ((proc-name (tcp-server-make-process-name port))
(buffer-name (format "*%s*" proc-name)))
(unless (process-status proc-name)
(make-network-process :name proc-name :buffer buffer-name
:family 'ipv4 :service port
:filter 'tcp-server-filter :server 't)
(setq tcp-server-display-buffer-on-update display-buffer-on-update))
(setq tcp-server-clients '()))
;; (display-buffer buffer-name)
(defun tcp-server-stop (port)
"Stop an emacs TCP server at PORT"
(list (read-number "Enter the port number the server is listening to: "
(let ((server-proc (tcp-server-get-process port)))
(defun tcp-server-append-to-proc-buffer (proc string)
(let ((buffer (process-contact proc :buffer))
(and buffer (get-buffer buffer)
(let ((moving (= (point) (point-max))))
(if moving (goto-char (point-max))))))))
(defun tcp-server-filter (proc string)
(defun tcp-eval (string)
(eval (car (read-from-string (format "(progn %s)" string)))))
(defun tcp-server-sentinel (proc msg)
((string-match "open from .*\n" msg)
(push proc tcp-server-clients)
(tcp-server-log proc "client connected\n")
((string= msg "connection broken by remote peer\n")
(setq tcp-server-clients (cl-delete proc tcp-server-clients))
(tcp-server-log proc "client has quit\n")
((eq (process-status proc) 'closed)
(defun tcp-server-log (client string)
"If a server buffer exists, write STRING to it for logging purposes."
(format "%s %s: %s"
;;; tcp-server.el ends here
Then you can call the
tcp-server-start command, informing the port you want it to run, and your server should be ready. Here's a python client example:
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect(('127.0.0.1', 9999)) # ip and port running emacs
if __name__ == '__main__':
conn = connect()
# now you send your desired elisps commands like this:
conn.send(b'(insert "foo bar")')
Keep in mind that this code doesn't have any type of firewall, so you should be vulnerable to external attacks.