Malleable Computing, Emacs, and You

kickingvegas4 pts0 comments

nfdn: Malleable Computing, Emacs, and You

notes from /dev/null

by Charles Choi 최민수

Malleable Computing, Emacs, and You

22 Jul 2026 Charles Choi

It all started with a routine task. I use GitHub issues for all of my public-facing projects but my preference is keeping track of things in Org Agenda. To reconcile the two, I would manually copy over the GitHub issue to an Org file, typically the title and description, like an animal.

Despite this separation, the duplicated issue allowed me to treat it as a scratchpad for anything I could express in Org. In this way, I used the duplicated issue in Org as both a dedicated area to take notes and a “staging” area to compose follow-up comments that I’d want to share in the public facing issue.

I manually copied for far longer than I care to admit. Repeat a task enough times in Emacs and the inevitable thought arises: “I should automate this.”

This post recounts how I automated this task and in doing so, highlight the malleable computing capabilities of Emacs. It should also be considered a follow-up to my earlier post “In Emacs, Everything Looks Like a Service”.

Requirements

An essential question to ask in any automation exercise is “What do I want done?”

I wanted to be able to:

Easily copy a GitHub issue (title, description, some metadata) as an Org task that can be tracked in an Agenda view.

Work primarily from Emacs to minimize the context switching between it and a web browser.

Express my thoughts in Org syntax.

Create a new GitHub issue.

Avoid dealing with GitHub authentication.

From Emacs, open a GitHub issue in a web browser.

Another essential question to ask is “What do I not want to do?”

Install or write a full-featured GitHub client.<br>Worry too much about synchronization logic between local (Emacs) and server (GitHub) state.

Spend a lot of time on this (ideally have something working in a day, no more than a week).

Specification

With the above requirements in place, the next question is “how do I build this?”

For this particular exercise, I decided to leverage my existing install of the GitHub command line utility gh. The benefits for this are:

GitHub authentication is delegated to gh; no need to mess with it directly from Emacs.

Emacs can treat gh as a REST service to GitHub as shown in the diagram below

To flesh out the rest of our tool, we can leverage using different Elisp packages and programs:

For the user interface, the Transient and Variable Pitch Table (vtable) packages are used for menus and display respectively.

For Org to Markdown translation, ox-gfm will be used.

For Markdown to Org translation, Pandoc will be used.

Elisp native JSON support will be used for deserializing the JSON responses from gh.

Implementation

The implementation of the above is published as the package fj with its source available for examination in the file fj.el. Of note is the function fj-request-issues which does the work of retrieving GitHub issues via gh as shown below.

10<br>11<br>12<br>13<br>14<br>15<br>16<br>(defun fj-request-issues (repo)<br>"Request issues for REPO."<br>(let* ((fields fj-browser-fields)<br>(cmd-list (list "gh"<br>"--repo"<br>(format "'%s'" repo)<br>"issue"<br>"list"<br>"--limit"<br>(number-to-string fj-request-issue-count)<br>"--json"<br>(string-join fields ","))))

(json-parse-string (shell-command-to-string<br>(string-join cmd-list " "))<br>:null-object nil)))

Consider the high degree of abstraction provided by fj-request-issues:

The list cmd-list forms the request (in this case, the arguments to invoke gh with).

shell-command-to-string dispatches the request to gh.

The returned JSON response is handled by json-parse-string to deserialize the JSON into an Elisp hash table.

All of the above is accomplished in less than 20 lines of code.

The returned hash table result is subsequently processed to populate a vtable as shown below. From the vtable, the user can navigate the list of issues with an ancillary window updated to show the details of a selected issue.

Multiple commands and functions working with said hash-table were made to satisfy the requirements above. They are accessible via the Transient menu shown below:

Malleable Computing Observations

As Elisp is a dynamic programming language, the above function (or some variant of it) can be coded and evaluated within a running Emacs session. In Emacs it is routine practice to prototype code behavior without the need to restart it. Contrast this with tools that are built with a static language and have no extensibility, where the edit-compile-debug development cycle must be applied to exercise behavior, provided the source code is available.

Emacs provides numerous ways to edit and evaluate Elisp code, among them:

A scratch buffer

An Elisp file

An Org source block

IELM REPL

Eshell

eval-expression (M-:)

Because there is no isolation between loaded Elisp code, all of it can be orchestrated together in an improvised fashion. Any program accessible to Emacs via shell further adds to this mix.

Provided high...

emacs github issue issues elisp json

Related Articles