Shared posts

02 Jul 21:20

6/30/25: Trump 'Beautiful' Bill, Dems Smear Zohran, Gaza Aid Site Massacres, Karen Read Trial & MORE

Tom Roche

Ryan Grim (this time mostly solo, definitely no other BP regulars) delivers another consistently EXCELLENT show, with 4 groups of segments (in order of presentation):

1. interview with David Dayen (possibly with assistance from Dave Smith on these--am recording this 2 days later) on the Trump OBBB ("one big beautiful bill") esp current Senate debate (just before it passed Senate 50-50). possibly |segments| > 1
2. (possibly |segments| > 1, definitely Dave Smith copilot) Zionist CorpDems (esp Albany shiksa Kirsten Gillibrand, who later apologized) freakout over Mamdani {beating Cuomo, failing to bend the knee to Zionism}
3. (definitely |segments| > 1) Dave Smith copilots 1st discussion of Zionist deepstate and USCFM crimes, then interview with (surprisingly craven) Amir Tibon (@ Haaretz) mostly re IDF crimes in Gaza, some on settler crimes in West Bank Palestine
4. (ends episode, definitely |segments| > 1) possibly overlong (but entertaining and illuminating re the Education of a Kinda Normie Rightwing Guy Who Really Bought the Copaganda) interview/rant (by RG--IIRC Dave Smith drops out) with Aidan Kearney (aka Dr Turtleboy) on how MA (Boston area, mostly Canton and environs) cops and "justice system" tried to
****1. railroad Karen Read (girlfriend of dead cop) for (what appears to be instead) a cop-on-cop murder
****2. suppress journalism and activists (esp Turtleboy) for unraveling/exposing The Man's attempted coverup

Ryan discusses Republican quits Senate while trashing Trump bill, Dems smear Zohran as antisemite, death to IDF chants in the UK, Trump attacks Israeli courts over Bibi charges, Gaza aid site massacres, explosive new details on Karen Read trial.

 

David Dayen: https://x.com/ddayen

Dave Smith: https://x.com/ComicDaveSmith

Amir Tibon: https://x.com/amirtibon

Aidan Kearney: https://x.com/DoctorTurtleboy

 

To become a Breaking Points Premium Member and watch/listen to the show AD FREE, uncut and 1 hour early visit: www.breakingpoints.com

Merch Store: https://shop.breakingpoints.com/

See omnystudio.com/listener for privacy information.

01 Jul 20:52

Democracy Now! 2025-06-17 Tuesday

Tom Roche

excellent 1st and 3rd/final post-headlines segments (BTW, never skip the headlines), but 2nd seg (interview with once-great-now-has-been Keith Ellison) is /very/ skippable

Democracy Now! 2025-06-17 Tuesday

  • Headlines for June 17, 2025
  • Preemptive Strike or Act of War? Israel Attacked Iran Amid Sinking Global Support for Assault on Gaza
  • "We Loved Her": MN AG Keith Ellison Mourns His Friend Melissa Hortman, Slams Republican Rhetoric
  • Cuban Deputy Foreign Minister on U.S. Embargo, Trump's Deportations, Israel's War on Iran & Gaza

Download this show

01 Jul 20:48

Democracy Now! 2025-07-01 Tuesday

Tom Roche

consistently good, best DN! in ~week

Democracy Now! 2025-07-01 Tuesday

  • Headlines for July 01, 2025
  • "Worst Thing I've Ever Seen": U.S. Surgeon Describes Mass Starvation, Injury and Death in Gaza
  • "Trying to Find Food Is a Death Sentence": Palestinian Writer Muhammad Shehada on Gaza Aid Massacres
  • "Ethnic Cleansing": U.N. High Commissioner for Human Rights, Volker Türk, on Israel's War in Gaza
  • "Damaging and Deadly" Heat Domes Nearly Tripled, from Europe to the U.S.: Climatologist Michael Mann

Download this show

01 Jul 17:01

7/1/25: DEPORT ELON? Trump GOES NUCLEAR Over ‘Big Beautiful Bill’

Tom Roche

EXCELLENT, but just a KB radar (~15 min)--she cites ~"massive technical issues" at start, implies no full show for T 1 Jul (despite Trump's OBBB just passing Senate, which this radar was recorded just before)

Krystal breaks down Trump going to war with Elon over his 'big beautiful bill' opposition. 

To become a Breaking Points Premium Member and watch/listen to the show AD FREE, uncut and 1 hour early visit: www.breakingpoints.com

Merch Store: https://shop.breakingpoints.com/

See omnystudio.com/listener for privacy information.

01 Jul 00:57

NATO Forever

by The Späti Boys
Tom Roche

Rob @ 'Podcasting is Praxis' joins Nick (alone of the Späti gang) deliver VERY EXCELLENT rants on various NATO (and EU and US--not sure why Canada gets a pass) evils, including

* Rutte et al shamelessly NAFO Trump (i.e., kneel-and-deliver North Atlantic FellatiO)
* uttering continuous streams of incredible (as in, not credible) Russophobic threats while completely cowed/craven before the PRC
* absurd military-spending-increase promises express neoliberal desire to replace democratic welfare states with authoritarian warfare states via military Keynesianism
* Ursula von der Leyen uses authoritarian provision (Article 122 of the TFEU) to allow European Commission impose ReArm Europe plan overriding Parliamentary review
* Macron's risible neo-Gaullism
* EU (esp Germany) is pro-veterans especially Nazis (Red Army and Warsaw Pact veterans need not apply)
* the continuing evils caused by post-1990 NATO expansion, esp Ukraine, esp
* ... (they don't say exactly, but come /very/ close to saying, so I will) so-called Russia-Ukraine War is NATO's proxy war on Russia
* EU member governments' increasing anti-{Palestine, Russia} authoritarian repression excused as defending liberalism

01 Jul 00:20

116: Exit Music (For A Fanbase), with Anthony Fantano

Tom Roche

BH drop another VERY EXCELLENT ep, excepting only {pre- and post-content ads, bit of (admittedly amusing) Portuguese bashing at content start}

(NOTE: This is an UNLOCKED Patreon exclusive episode. You should really join the Patreon.)


Matt and Daniel are joined by music critic and creator of The Needle Drop, Anthony Fantano to get the knives out for Thom Yorke's muddled stance on Gaza and Israel, to declare Gen-X as jaded as Mila Kunis in a video for a third-tier Aerosmith song, and to definitively adjudicate the Kendrick-Drake beef by Roberts Rules of Order.


Please donate to Islamic Relief USA: https://irusa.org


LIVE COMEDY SHOW DATES


Friday August 1st - Francesca and Matt will be at Laughs Comedy Club in Seattle. Tickets here: https://bit.ly/4kFt1xE


Saturday August 2nd - The Bitchuation Room LIVE in Seattle. Tickets here: https://bit.ly/4khBhnK


HOUSTON AUGUST 28 - Francesca and Matt will be at The Punchline in Houston. Tickets: https://www.ticketmaster.com/event/3A0062C3F8154B3F


Visit Anthony's channel The Needle Drop: https://www.youtube.com/@theneedledrop


Find Anthony online at https://x.com/theneedledrop or https://www.instagram.com/afantano


Subscribe to the Patreon https://www.patreon.com/badhasbara


What’s The Spin playlist: https://spoti.fi/4kjO9tL


Subscribe/listen to Bad Hasbara wherever you get your podcasts.




Support this podcast at — https://redcircle.com/bad-hasbara/donations

Privacy & Opt-Out: https://redcircle.com/privacy
30 Jun 18:49

Marcin Borkowski: Interacting with an external process via stdin and stdout

by Marcin Borkowski
For a project I’ve been recently working on, I needed Emacs to interact with an external process, sending things to it via its stdin and receiving responses via its stdout. I never did anything like that before, so I started with checking my options.
30 Jun 18:44

Charles Choi: Take Two: Eshell

by Charles Choi
Tom Roche

VERY EXCELLENT if a bit muddled: combines

1. intro: why Choi previously preferred to use `M-x shell` over `M-x eshell`
2. body: why Choi now prefers /eshell/
3. not-quite-conclusion: /eshell/ tips, tricks, and traps

so could definitely profit from splitting into multiple articles. exemplary pullquote (slightly edited):

> Eshell is better thought of as a “prompt” interface for Emacs which in turn serves as the interface to all the command line utilities made available to it. In this light, a whole swath of common shell workflows get replaced by Emacs.

following table unfortunately sabotaged by TOL stripping /internal/ spaces! loathesome, esp since TOL also strips internal tabs, so tabifying !workaround

> Workflow Shell Eshell
> ----------------------------- ------------------------------- ----------------------------------------
> File management Orchestrate cd, ls, cp, rm, mv Run dired {optional path}
> View a file Run `less` Run view-file
> SCM with git Run git command(s) Run magit {optional path}
> View man page Run man Run Emacs man
> Run Makefile Run make Run `make`, output to a compile buffer
> Remote login Run ssh Run Eshell Tramp
> Edit a file Run $EDITOR Run find-file
> Manage processes Run htop Run proced
> Search for pattern in a file Run grep Run Eshell `grep`, output to compile buffer
> Locate a file Run locate Run Eshell `locate`, output to locate buffer

> Suffice to say, Eshell reinforces and rewards keeping Emacs users only in Emacs.

This is a contribution to the Emacs Carnival 2025-06: Take Two collection of posts on Christian Tietze’s blog.

My first take with Eshell many years back did not leave a good impression. My early expectations was that it should act like any other shell, only to be unpleasantly surprised by it. It took a long time for me to warm up to Eshell. Upon reflection, it was because I wasn’t ready for it.

Now Eshell is an inseparable part of my Emacs experience. Paradoxically though, I find little occasion to use Eshell in the same way I’ve used shells in the past. Much of what I used to use the shell for, I do today with Emacs modes instead.

It was not always this way. Like so many users who started Unix computing in the 80’s, I started with the command line (for myself ksh and later bash), studiously internalizing command line tools and their arcane syntaxes to support file management, running programs, and systems administration. Overwhelmingly though, it was file management and running programs that I did through the command line.

For file management these days, Dired is my interface of choice. It is simply the more elegant tool for the job.

Case in point: renaming a bunch of files in a directory to arbitrary names. With a shell, my standard approach would have been to run some variant of ls -1 > foo.sh, edit foo.sh to insert mv on each line to a renamed target file, chmod u+x foo.sh to be executable, run foo.sh, delete foo.sh and call it a day.

With Dired, the above steps are replaced as such: make the buffer writable (via Wdired). Change the target filenames to a desired result, then commit the changes. This is even easier if there is a pattern you can use a regexp for. Unsurprisingly, all the basic file management operations that you would want are supported by Dired. Add Casual Dired to help make these operations discoverable and you’ll soon consider how quaint using mv, cp, rm, and ls are.

Running a simple command on a file? Again, you can do that with Dired. Move the point to the Dired line containing the file. Type “!” and enter a command in the prompt. You can optionally reference the filename in the command with the “?” character if you want to redirect its output to a file (e.g. cmd ? > outfile).

Taking file management and running simple commands out of what you would use a shell for, what’s left over? Source code management (SCM)?

Like for many others, git is my goto tool for SCM. Much has been said about the terrible user experience of the git command line and for years I suffered with its design decisions. Thankfully for Emacs users, there is Magit and VC mode which both provide a saner experience for it.

Running a Makefile? Use Emacs compile, which provides command completion for the targets defined in the Makefile and error/warning navigation if needed. (Try out Casual Make for editing Makefiles in Emacs.)

Do you need to run a command with arcane arguments repeatedly? Again, Makefile + compile to the rescue where it can be used as a task runner for that command.

Need robust terminal emulation? Eshell will fail you here and you are likely better off using a dedicated terminal emulator app, separate from Emacs. That said, I’ve found the built-in term to be good enough for many curses-style utilities.

Mining data files with piped commands? Eshell is a power tool here: used wrongly and you could figuratively cut off a limb. But used cleverly, Eshell offers great value. More on this later.

So with all these use cases described, why even use Eshell?

Using Eshell becomes a win only if you know Elisp. With that, you can think of Eshell as an Elisp REPL that can secondarily act as a shell.

Let’s not mince words. For many users this is a high bar, as it takes into account a lot of prerequisite knowledge. That said, learning basic Elisp is trivial for readers already conversant with programming and manageable for those that aren’t. Personally, I was very late (decades!) in taking the time to learn Elisp because I didn’t see the reward in it and so, prioritized accordingly. That hesitancy turned out to be unfounded. Elisp is easy to learn and the reward (or punishment) for knowing it is having the ability to really use the full capabilities of Emacs. (Know Python? Here’s a cheatsheat for Elisp that I wrote, hop in, the water’s fine…)

Once gained, bringing Elisp knowledge to using Eshell gives you a command line super power: the ability to improvise shell commands with Elisp functions.

Consider the following Eshell example where we wish to apply a command on a set of png files in a directory. Let’s start with a simple example that simply echoes filenames with suffix .png.

$ for i in *.png { echo $i }

In Eshell, you can replace echo $i with an Elisp expression.

$ for i in *.png { (format "%s" i) }

You can also mix shell commands and Elisp via dollar ($) expansion. Note that $ expansion in Eshell is different from other shells. A deeper reading is on it is recommended to avoid confusion with what works in conventional shells.

$ for i in *.png { echo $(format "%s" i) }

If you have ImageMagick, installed, you can use the convert utility to change this to a jpeg file, using the Elisp file name components functions to do the work of getting a desired target name.

$ for i in *.png { convert $i $(file-name-with-extension i "jpg") }

Contrast this with the equivalent expression in Bash which I consider to have much more forgettable syntax.

$ for i in *.png; do convert $i ${i/.png/.jpg}; done

Another significance with mixing shell commands and Elisp together is the ability to incorporate Emacs buffers into an improvised workflow. Shell commands are typically designed to work with data organized as files. In contrast, Elisp (rather, Emacs) treats files as a persisted, secondary form of data. Instead, Buffers are the primary data type in Emacs.

Recall the Dired naming example above? Consider the added steps due to using a temporary file foo.sh compared to using a writeable Dired buffer.

Eshell shifts you into thinking differently about working with a prompt, where instead of thinking of output being only a file or (stdout, stderr), the output could also be an Emacs buffer.

With that change in thinking, Eshell is better thought of as a “prompt” interface for Emacs which in turn serves as the interface to all the command line utilities made available to it. In this light, a whole swath of common shell workflows get replaced by Emacs.

Workflow Shell Eshell
File management Orchestrate cd, ls, cp, rm, mv Run dired {optional path}
View a file Run more or less Run view-file
SCM with git Run git command(s) Run magit {optional path}
View man page Run man Run Emacs man
Run Makefile Run make Run make & to send output to a compile buffer
Remote login Run ssh Run Eshell Tramp
Edit a file Run $EDITOR Run find-file
Manage processes Run htop Run proced
Search for pattern in a file Run grep Run Eshell grep to send output to a compile buffer
Locate a file Run locate Run Eshell locate to send output to locate buffer

Suffice to say, Eshell reinforces and rewards keeping Emacs users only in Emacs.

Another common shell workflow is using grep with pipes (|) for data mining files. For example:

$ grep {pat1} {file} | grep -v {pat2} | grep {pat3} >outfile

Using this pattern indiscriminately in Eshell is a recipe for unpleasant surprise if the file to be mined is large. This is because Eshell will ingest said file into Emacs as part of the pipeline processing. This will be slow. To avoid this, you can prefix each | with an * as follows:

$ grep {pat1} {file} *| grep -v {pat2} *| grep {pat3} >outfile

Why store a result in a file (outfile) that you have to open to see it and may not care to keep around? Here Eshell gives you the ability to redirect to a buffer.

$ grep {pat1} {file} *| grep -v {pat2} *| grep {pat3} >#<buffer "*my grep results*">

Note that Eshell supports creating/overwriting (>) and appending (>>) for redirection. Use > with care when working with an existing buffer.

What about piping shell command output to an Elisp function? At the time of this writing, you really can’t though according to this Reddit thread, this may change in the future.

If you are used to workflows that bleed out megabytes of data to stdout, you really shouldn’t use Eshell. But with some cleverness, Eshell can help you get insights to your data faster by leveraging all the tools Emacs can offer for this (occur, highlighting, grep, etc.).

Closing Thoughts

IMHO, Eshell is best thought primarily as a prompt for Elisp/Emacs functionality with the secondary benefit of running command line utilities with a “shell-like” experience. It should not be thought of as a “drop-in” replacement for an actual terminal shell. If full terminal emulation is desired, my guidance is to run a dedicated terminal emulator outside of Emacs.

To get the full benefit of using Eshell, you really need to be conversant with Elisp. That said, Eshell is actually a great way to start learning Elisp as it provides you a prompt interface (REPL) in much the same way that other languages like Python, JavaScript, Ruby, Java, Swift, etc do.1 Especially if you are comfortable with programming, take a day to learn Elisp. You won’t regret it.

Bringing Eshell into my Emacs journey has been amazing and I’m happy to have given it a second take.

Thanks to all the contributors of Eshell.

Footnotes

1 To clarify, these languages adopted the idea of a REPL from Lisp development which Elisp is descended from.

30 Jun 18:27

Civ 1919: Treaty of Versailles 8 – Greece negotiates too well

Tom Roche

Justin and (mostly) Dave excellent as usual--just waaay too short this time, but they've set this up as just a preview for a series on the 1919-1922 Anatolian wars aka Turkish War of Independence

The story of Greece’s negotiator Eleutherios Venizelos, and how his success at negotiating sowed the seeds of future disasters.
30 Jun 18:24

Civ 1919: Treaty of Versailles 7 – Japan and China

Tom Roche

Justin and (mostly) Dave excellent as usual

Japan takes a stand on the principle of racial equality, but it’s a non-starter with the white powers. The Japanese insist, and ultimately yield so they can take a piece of China.
30 Jun 18:22

Civ 1919: Treaty of Versailles 6: Italy leaves

Tom Roche

Justin and (mostly) Dave excellent as usual

Italy joined the allies late and wanted a lot of Yugoslavia. The dress rehearsal for Mussolini, Gabriele d’Annunzio, gathers Argonauts and makes a big move. Another seed of the next war planted at the conference in Paris 1919.
30 Jun 18:22

Civ 1919: Treaty of Versailles 5 – Eastern Europe

Tom Roche

Justin and (mostly) Dave excellent as usual

Poland, Czechoslovakia, Austria, and Hungary’s fates are decided at the conference in Paris in 1919.
29 Jun 18:43

Jakub Nowak: Goodbye LanguageTool, Hello Harper

by Jakub Nowak
Tom Roche

for 'spellchecking in Emacs (and particularly in org-mode)'

I found out about Harper the other day. Ever since I heard about it, I've been itching to set it up in my config and get rid of the horrible LanguageTool setup I had going. Now that I've got it working, I've gotta say I'm quite impressed. My previous LanguageTool setup was not smooth at all, and definitely not as fast as Harper is. I'm not sure how anyone else is doing spellchecking in Emacs (and particularly in org-mode) at the moment, but I recommend anyone using Emacs for most of their writing to give it a shot.

I won't embarrass myself with a comparison of my LanguageTool config. Just know that it was slow and terrible. Copied from the Harper docs, this is what my config looks like:

(when (and (not (equal system-type 'windows-nt)) (locate-file "harper-ls" exec-path))
  (with-eval-after-load 'eglot
    (add-to-list 'eglot-server-programs
               '(org-mode . ("harper-ls" "--stdio"))))

  (setq-default eglot-workspace-configuration
              '(:harper-ls (:dialect "Australian")))

  (add-hook 'org-mode-hook 'eglot-ensure))

Some caveats: it doesn't look like Harper has support for org-mode specifically yet, but it seems to generally work OK despite that. I have however noticed that it doesn't lint property tags, so for example your #+title: won't be spellchecked. Another minorly annoying little niggle is that straight seems to misbehave with eglot, or eldoc more specifically, printing eldoc error: (invalid-function incf) in the minibuffer instead of an actual error message. I was using lsp-mode before this - although I'm beginning to like the eglot interface more and more as I write this, so I think I may swap over to it where possible - so I never realised this issue. Per that GitHub issue link, (use-package eldoc :straight (:type built-in)) seems to be the solution.

The only thing that's missing, and to be fair LanguageTool doesn't implement this either (in fact to my knowledge nothing implements this, I don't even think there's a Word plugin), is text style metrics analysis. Every so often I get the impulse to try to untangle what the source code for that website is doing, and then write a simple elisp wrapper for it, but I always get sidetracked before I start. Maybe now is the time.

Addendum

I've discovered another few quirks in setting this up (mostly to do with eglot and company), so I figured I'd go back to update this post and catalogue what I've had to do for future reference.

eglot overwrites company-backends by default. This can be disabled with (setq eglot-stay-out-of '(company)). Figuring this out also convinced me to finally fix company-ispell, which I could not get working last time I tried. To get it working with both Ispell and flyspell it seems to need to following code-block:

(if (file-exists-p "/usr/bin/hunspell")
    (progn
      (eval-after-load "ispell"
        '(progn
         (setq ispell-program-name "hunspell"
               ispell-dictionary   "en_AU"
               ispell-alternate-dictionary (file-truename (concat user-emacs-directory "en_AU.dict"))
               ispell-local-dictionary-alist '(("en_AU" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_AU,en_AU-med") nil utf-8)))
         (defun ispell-get-coding-system () 'utf-8)))
      (eval-after-load "flyspell"
        '(progn
         (setq ispell-program-name "hunspell"
               ispell-dictionary   "en_AU"
               ispell-alternate-dictionary (file-truename (concat user-emacs-directory "en_AU.dict"))
               ispell-local-dictionary-alist '(("en_AU" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_AU,en_AU-med") nil utf-8)))
         (defun ispell-get-coding-system () 'utf-8)))))

I'm using Hunspell here - if you don't also eval-after-load for flyspell, then ispell-program-name gets overwritten (in my case, to enchant-2, which wasn't working). The alternate dictionary needs to be created, Hunspell doesn't ship a plaintext dictionary. You can make it by going to /usr/share/hunspell/ and running unmunch en_AU.dic en_AU.aff >> /~//.emacs.d/en_AU.dict. You'll notice that I'm using file-truename to turn that user Emacs directory into an absolute path - for some reason, it wasn't working with just the relative path.

29 Jun 16:41

Peter Tillemans: Consolidating Secrets in Pass

by Peter Tillemans

Background

Like a lot of people I've had a long history managing passwords and secrets over the years. From a little black book, over an Excel sheet, using a GPG encoded secrets file (works really well with Emacs gpg support), 1password (till they racked up their prices), lastpass (till they got bought by the Evil LogMeIn Corp), KeepassXC and lately pass.

I was perfectly happy with KeepassXC for a very long time, except for the command line integration. So I kept ending up with passwords in .envrc files in folders and excluded in the global .gitignore to avoid too many red cheeks. While this does keep secrets out of harms way mostly, it kept nagging that I had them in plain text in those files. In theory there is keepassxc-cli to query the passwords from the command line, but let's say the experience does not spark joy. It has no easy way to cache the password between calls and it is optimized for interactive use. (AFAICT, just the giant size of the command to type gives me dread).

Some day I stumbled over pass and found that after setup I could just pass snamellit/website to get the password on stdout. I wrote about the setup and emacs integration in a previous post. Since it leverage gpg, password caching is handled by the gpg-agent and my .envrc files quickly were purged of blasphemous secrets, replace by pure bliss:

export MY_SECRET=$(pass my/secret)
export OTHER_SECRET=$(pass other/secret)

similarly in emacs I can consistently get my passwords and related info with:

(org-gcal-client-id (auth-source-pass-get 'secret "snamellit/org-gcal-client"))
(org-gcal-client-secret (auth-source-pass-get "id"
"snamellit/org-gcal-client"))

When needed the gpg-agent will launch the appropriate pin-entry program whether in terminal or in the GUI and the caching will not force me to login several times when entering the folder.

So I ended up with my interactive use covered by KeepassXC and automated use by pass.

However, after some time I ended up with hundreds of secrets in KeepassXC, hundreds in pass, it is not always clear whether use is interactive or automated so confusion and duplication starts and things become harder to manage. In addition KeepassXC was using historically Dropbox to make it available on all my devices, recently migrated to Nextcloud, which has issues with dealing with conflicts which occasionally bite me in the behind. On the other hand pass secrets are stored encrypted in git where conflict punch you in the face. I prefer the latter. And started contemplating whether to move everything to pass.

Thanks to the encouragement of SummerEmacs, one of the more enthusiastic SystemCrafters, ensuring the great experience in browsers and iOS mobile devices I had no more excuses to keep postponing it.

Preparation

I started out with keeping my pass passwords as part of my dotfiles. This was convenient when they were few. However this is weird so this will attract weirdness when configuring all integrations I'll need.

Also pass supports a git command to manage the password-store with git which is not really useful when it is part of something else. So the first order of the day is to move all secrets to a separate repository and update the dotfiles to check for presence and clone the repo if missing (and do a gently pull when it is). A quick visit to each of the machines in my machine park to apply this change. Everything still seems to be working.

Migration of the KeepassXC data

I used the pass-import tool which adds in import command to pass which supports a crazy amount of password managers, including keepassxc. For keepassxc it need the pykeepass. If you're running on Arch, everything is a yay -S away. However on Ubuntu and its derivatives it is the usual slog we start to get accustomed to. It's all in the pass-import README , note that on Ubunty the pykeepass library is available with apt install python3-pykeepass.

Once it is installed I tried a dry run (with the -d flag) to see if basic functionality is working

pass import -a -d keepassxc ~/Nextcloud/Apps/Keepassxc/Passwords.kdbx
Password for /home/pti/Nextcloud/Apps/Keepassxc/Passwords.kdbx:
  w  Data would be imported from keepassxc to pass
  .   Passwords imported from: /home/pti/Nextcloud/Apps/Keepassxc/Passwords.kdbx
  .   Passwords exported to: /home/pti/.password-store
  .   Number of password imported: 2035
  .   All data imported
  w  Weak password detected: eDGQqipE might be weak.  Score 2 (100000001 guesses).  This estimate is based on the sequence eDGQqipE(bruteforce)
  w  Weak password detected: eDGQqipE might be weak.  Score 2 (100000001 guesses).  This estimate is based on the sequence eDGQqipE(bruteforce)
  w  Weak password detected: eDGQqipE might be weak.  Score 2 (100000001 guesses).  This estimate is based on the sequence eDGQqipE(bruteforce)
...  large list of names of secrets

This asks for the password of the Keepass file and some remarks it has.

This all looks reasonable. So we can try the import. Since the password-store is a git repo no real damage can be done to it (as it is safely pushed somewhere else where the import tool cannot touch it) and any damage done can be reverted....

Now is a good time to check if the mooring lines of your laptop are properly secured as encrypting all the secrets will spin up the propellors if the number is large enough.

I run it again without the -d flag and after several minutes the noise dies down and I am left with a lot of additional folders in my ~/.password-store which match the grouping in KeepassXC. The files contain the secrets and the expected metadata. This looks good so I add/commit the things to complete the level.

Integration with iOS for my iPhone

Let's start with the most scary one : the iPhone.

Upon recommendation I had installed passforios which needs to be configured.

Configuring the host, repo and username to use for the git repository is straightforward enough.

I always use ssh to access my repos so we need to add an ssh keypair for this purpose. There is no support to generate key-pairs in passforios for reasons, so I have to do it externally and upload the key. A quick ssh-keygen , uploading the public key to the forge, allowing access to the repo and if I can get the private key on my phone we can access the repo.

passforios has a nice feature to load ascii armored keys via a QR code. A bit digging surfaced the asc-key-to-qr-code-gif tool which was made for this specific purpose. The ssh key is already in the appropriate format so this can be directly converted

./asc-to-gif.sh ~/.ssh/id-passforios ssh-pub.gif
display ssh-pub.gif

Then go to the repository settings, press the circled i on the SSH Key button, select the ASCII-Armor Key and click to scan the QR code. Point the camera to the QR code on the screen and it should appear in the key field in the app.

We have to repeat this 2 more times to get the private and public key for the password-store into the app. First exporting the keys

gpg --export -a 1234ABCD >gpg.pub
gpg --export-secret-key -a 1234ABCD >gpg.key

converting to a gif, displaying them and scanning them in *Settings -> PGP Key -> ASCII-Armor Key in the respective fields.

If, after synching, you go now to the Passwords you should be greeted with a listing of all folders and keys and the secrets should be visible if made visible by tapping the eye icon.

I needed to enable passforios as a source for autofill : Settings -> Passwords -> Autofill Passwords and slide the toggle for Pass. I also disabled the toggle for Strongbox which I was using for integration with the Keepass database.

Now I see the option to select the secrets from the passforios app. It does not narrow down to the right key, but that is a problem for future me.

Ok, the hard part is done. Or at least the most risky part, ... in my eyes... whatever. Moving on...

Integration with FireFox

Checking at the bottom of the pass website we find that passff is the good stuff for integration with FireFox. From previous adventures with KeepassXC and NativeMessaging I assumed there had to be a host part to be installed too.

Indeed we are directed to the passff-host github repo to get an install-script which generates the native messaging json for the different browsers and a small executable python script which contains remarkable clean and no-dependency code. Similarly the install script is straightforward. I do not understand why it support half a dozen browser, mostly chrome based as for the life of me I cannot find an extension which uses this host program. So either I need bigger glasses or there is some knowledge beyond my grasp.

Running the installer, installing the extension, restarting firefox for good luck and the extension appears and offers passwords on the sites I try.

Out of curiosity I check the configuration in ~.mozilla/native-messaging :

pti@tuxedo ~> ls .mozilla/native-messaging-hosts/
org.keepassxc.keepassxc_browser.json  passff.json  passff.py*
pti@tuxedo ~> cat .mozilla/native-messaging-hosts/passff.json
{
  "name": "passff",
  "description": "Host for communicating with zx2c4 pass",
  "path": "/home/pti/.mozilla/native-messaging-hosts/passff.py",
  "type": "stdio",
  "allowed_extensions": [ "passff@invicem.pro" ]
}
pti@tuxedo ~> cat .mozilla/native-messaging-hosts/passff.py
#!/usr/bin/python3
"""
    Host application of the browser extension PassFF
    that wraps around the zx2c4 pass script.
"""

import json
...

Nothing out of the ordinary, the passff.py python is the same as in the repo. My old keepassxc extension support is still there.

Firefox is installed natively on this machine, not with a flatpak which I assume will come with its own challenges.

Chromium Support

Time to tackle the Chrome family. Chrome is required to put food on the table so we have to get that going eventually. But Chrome is distributed as a flatpak (or a snap but I am NOT going to deal with that), and I can install Chromium natively, and apparently native installs are MUCH better supported than the versions in wrappers so let's start with that one first.

From the pass website we find that browserpass is the way to go for the chrome family. The browser extension installs from the usual places without drama and starts promptly complaining it cannot find the native host to talk to.

The native host in question is from the browsaerpass-native sister repo . As usual for all distro's there are packages ready to install but because Ubuntu-derivative I can compile from source. Downloading the source for version 3.1.0 from the releases page. Again this repo refers to all browsers including firefox although I cannot for the life of me find a Firefox Extension supporting this host app.

Then building and installing timelapse :

tar -xzvf ~/Downloads/browserpass-native-3.1.0.tar.gz
cd browserpass-native-3.1.0
ls
less README.md
PREFIX=/usr/local make configure
sudo make PREFIX=/usr/local install
which browserpass

which shows the executable lives at /usr/local/bin/browserpass and this totally went fine the first time (NOT!!!!).

The Makefile has support to install the magic json to enable native messaging for the different browsers.

PREFIX=/usr/local make hosts-chromium-user
PREFIX=/usr/local make hosts-chrome-user

The second invocation is a hail-mary because I already know the Chrome flatpak does not look in the same places and will require some additional finnagling

For now focus on Chromium and check if the configuration looks reasonable:

pti@tuxedo ~> cd .config/chromium/NativeMessagingHosts/
pti@tuxedo ~/.c/c/NativeMessagingHosts> ls
com.github.browserpass.native.json@
pti@tuxedo ~/.c/c/NativeMessagingHosts> cat com.github.browserpass.native.json
{
    "name": "com.github.browserpass.native",
    "description": "Browserpass native component for the Chromium extension",
    "path": "/usr/local/bin/browserpass",
    "type": "stdio",
    "allowed_origins": [
        "chrome-extension://naepdomgkenhinolocfifgehidddafch/",
        "chrome-extension://pjmbgaakjkbhpopmakjoedenlfdmcdgm/",
        "chrome-extension://klfoddkbhleoaabpmiigbmpbjfljimgb/"
    ]
}

Cool, the executable is looked at where it is installed (this is not obvious, don't ask how I know). The rest looks also like how these things should look. Let's try...

The extension settings page is no longer complaining the native host is missing and there are password entries visible. Checking with some website shows the password is injected. yay!.

Level complete, ready for the final boss.

Enabling Chrome Support, now with more Flatpak!

Ok, we have a working chromium support so repo access, host app, native host configuration et al are proven working. We can only focus on jumping over the Flatpak Firewall...

As a good cargo cultist I do a literature study and find that I should

  • find the config location of the flatpak app

  • use flatpak-spawn to spawn the native messaging host app

  • enable D-Bus Session socket access for chrome

  • Package up the calling of the host app in a single script to configure in the json.

    Not necessarily in that order....

For the permission to access D-Bus Session start up flatseal from flathub, navigate to com.google.Chrome and enable the D-Bus Session socket. This should be possible with some additional cursing in the manifest file of Chrome. I cannot find decent reference documentation in a reasonable time, so flatseal it is.

The configuration of the flatpak app is easy too, painful experience seared in my brain that flatpaks look in ~/.var/app/ folder so for Chrome this will be ~/.var/app/com.google.Chrome . From the hail-mary install for chrome done above I know that it just creates a symbolic link to /usr/local/lib/browserpass/hosts/chromium/com.github.browserpass.native so we can start from there. We will have to edit that so copy it. We also need a wrapper to call the native host app

cd ~/.var/app/com.google.Chrome/config/google-chrome/NativeMessagingHosts
cp /usr/local/lib/browserpass/hosts/chromium/com.github.browserpass.native
ec browserpass.sh

Add the content of the wrapper

#!/bin/sh
cd ~
/usr/bin/flatpak-spawn --host /usr/local/bin/browserpass 2>/tmp/browserpass-error.log

I added the optional redirect of stderr to an error logfile because from experience I know nothing ever goes wrong if you enable error reporting beforehand.

chmod +x browserpass.sh
pwd
pwd | wl-copy
ec com.github.browserpass.native.json

Installing the browserpass extension in Chrome after restarting it (I am not superstitious, just careful) and I can bask in the glory of seeing proposals for passwords when trying to log in. Most of the proposals are pretty garbage, but that is a problem for future me.

Conclusion

I have access to my password-store secrets on my phone, my browsers on laptop and desktop, and most importantly Emacs. Narrowing of the proposed secrets is, euhmmm, sub-optimal, but since it is sub-optimal in the same way on all platforms I assume that some TLC in the password-store and cleaning of the migrated secrets will fix that in time.

In the process I gained much more confidence in configuring flatpak apps. I can decommission the keepassxc system including dealing with the sync conflicts (which was admittedly super easy with the merge database feature in KeepassXC). I no longer have to deal with giving the KeepassXC window a place on the desktop and autostarting it.

I am a bit puzzled about the host-apps referring to supporting browsers for which no extensions are available. This probably might warrant some additional investigation.

Big step forward

27 Jun 01:22

Macau, the Portuguese city in southern China

Tom Roche

excellent

Macau is best known now for its casinos, but it was the first European city in Asia, remained a Portuguese colony for 500 years, and contains many colourful and significant stories within its walls. 

26 Jun 18:37

The real reasons for the US-Israeli war on Iran, explained

Tom Roche

another VERY EXCELLENT Ben Norton explainer, bit longer than usual (<67 min) but thorough and well-documented. Unfortunately no transcript at [the episode's GER page](https://geopoliticaleconomy.com/2025/06/17/real-reasons-us-israel-war-iran/) (archived [here](http://web.archive.org/web/20250624003527/https://geopoliticaleconomy.com/2025/06/17/real-reasons-us-israel-war-iran/)). The audio (starting ~4:38) explains 5 main goals of the Zionist empire (US, Israel, NATO, et al) for the war started {13 Jun 2025 local time, 12 Jun US time}; the above GER page gives a slightly-longer list of goals, which I slightly edit below to fit into the 5 of the audio:

1. Maintain imperial hegemony in southwest Asia (aka Mideast, Middle East, SWA).
2. Completely undercut (longterm) the SWA Axis of Resistance through regime-change in Iran: either
----- replace the Islamic Republic regime with another (e.g., reimpose the Pahlavi dictatorship)
----- permanently weaken IR state power
----- break the IR regime, leave a "failed state" à la Lebanon, Libya, Iraq, Syria
3. Maintain Israel's nuclear monopoly in the region, prevent Iran from developing nuclear weapons.
4. Stop GCC dedollarization: maintain fossil fuel pricing in USD (aka the "petrodollar system")
5. Stop global multipolarization:
----- most importantly: break Iran-PRC-Russia partnerships from becoming a "real" alliance
----- break Eurasian economic and security partnerships, e.g., BRICS, SCO

The United States and Israel are waging war on Iran, but why? What are their real goals? Ben Norton explains the imperial strategy to impose US hegemony on West Asia (aka the Middle East), destroy the Axis of Resistance, colonize Palestine, destabilize the revolutionary Iranian government, preserve the petrodollar system, prevent de-dollarization, divide BRICS, and break up the Iran-Russia-China partnership. VIDEO: https://www.youtube.com/watch?v=OwH780cEcEQ How Israel's war on Iran was made in USA: https://geopoliticaleconomy.com/2025/06/14/israel-war-iran-us-trump-support/ US pressures Saudi Arabia to sell oil in dollars, not Chinese yuan: https://geopoliticaleconomy.com/2023/08/10/us-saudi-arabia-sell-oil-dollars-chinese-yuan/ Topics 0:00 US support for Israeli attacks 4:38 Goals of US-Israeli war on Iran 10:13 Israel: outpost of US empire 14:35 US imperial strategy 16:28 Geopolitics of West Asia (Middle East) 17:50 Oil and gas 21:11 Geostrategic chokepoints 24:53 Axis of Resistance 28:33 Syria: Fall of Assad government 31:44 US plan to overthrow 7 countries 33:54 Iranian Revolution 35:53 Anti-colonial movements 39:14 Dedollarization 41:49 Petrodollar and OPEC oil embargo 47:05 Super Imperialism 49:36 Petrodollar challenge 52:43 BRICS 55:55 Shanghai Cooperation Organization 58:53 Iran-Russia-China partnership 1:04:05 US divide-and-conquer strategy 1:06:03 Outro
26 Jun 16:14

Iran-Israel War: Trump Tries to Control Monster He Created? | LIVE w/ Trita Parsi

Tom Roche

EXCELLENT, just too short (though untruncated)

The U.S. has officially joined Israel’s war on Iran, bombing Iranian nuclear sites and obliterating what was left of the nuclear talks. With Trump hinting at regime change, the world is now watching to see how Iran will respond.

Is this the end of diplomacy? Does Iran now view nuclear weapons as the only way to deter U.S. and Israeli aggression? Can Iran survive?

Rania Khalek is joined by Trita parsi, Executive Vice President of the Quincy Institute, for a special live episode of Dispatches to break down what the strikes mean, the geopolitical fallout, and whether the path ahead now leads to wider war.

📅 LIVE on June 24

🕑 2pm ET / 11am PT / 9pm Palestine

🔔 Set a reminder and subscribe to Breakthrough News to get notified when we go live.

Support independent media, become a Breakthrough News member today:  Patreon.com/BreakthroughNews


26 Jun 16:10

"Israel Has Walked Off a Cliff" - John Mearsheimer, Alexander Mercouris & Glenn Diesen

by The Duran
Tom Roche

Mearsheimer EXCELLENT as usual

"Israel Has Walked Off a Cliff" - John Mearsheimer, Alexander Mercouris & Glenn Diesen

26 Jun 02:16

Backstory to Assange's secret deal for freedom

Tom Roche

VERY EXCELLENT (if too brief: <19 min content) interview with author Andrew Fowler on the Julian Assange (/JA/) story c2010-2025, including

+ Manning Wikileaks, esp Collateral Murder
+ US-Sweden-UK plot against JA for his "crime" of exposing the crimes of their empire, but ...
- unfortunately doesn't mention what mostly got JA done, which was exposing the US Corporate Democrats' fixing the 2016 US presidential election (esp the Democrats primary)
+ /much/ too briefly mentions the sexcrime libel with which JA was smeared for a decade, but fortunately mentions the [report](https://spcommreports.ohchr.org/TMResultsBase/DownLoadPublicCommunicationFile?gId=24838) (archived [here](http://web.archive.org/web/20250618221957/https://spcommreports.ohchr.org/TMResultsBase/DownLoadPublicCommunicationFile?gId=24838)) by [Nils_Melzer](https://en.wikipedia.org/wiki/Nils_Melzer#Assessment_of_Julian_Assange%27s_confinement) that utterly crushes the Swedish sex smear
+++++ in Melzer report (above): skip starting bureaucratese to bottom of p2, read at least to end of p12
+ the 2024 deal to free JA (Rudd and Albanese vs Biden and the US deepstate)
+ Assange's legacy esp for global journalism

A year ago this week Julian Assange was released from prison after a 14-year fight for freedom. Assange accepted a guilty plea of conspiring to obtain and disclose classified U.S. documents in exchange for being returned home to Australia. But how did this deal come about and what happened in the lead-up to his return home? Journalist Andrew Fowler shares the inner-dealings and joins the dots on the backstory of the negotiations to release Assange.

  • Guest: Andrew Fowler - journalist and author of The Most Dangerous Man in the World: Julian Assange and his secret White House deal for freedom
  • Producer: Sarah Allely
25 Jun 19:13

NYC fiscal crisis: canonizing Felix once again

by Doug Henwood
Tom Roche

Felix Rohatyn, Lazard Freres, Municipal Assistance Corporation--BURN IN HELL

I’ve got a review on The Nation‘s site of a new documentary on the NYC fiscal crisis, co-directed and -produced by Michael Rohatyn, son of the chief imposer of austerity 50 years ago, Felix Rohatyn. It was one of the opening battles of the class war from above, and the role of liberals like Felix in engineering it should never be forgotten.

25 Jun 02:19

E215 - Tracking Think Tanks w/ Ben Freeman and Nick Cleveland-Stout

Tom Roche

VERY EXCELLENT

Subscribe now to skip the ads and get more content.

Ben Freeman and Nick Cleveland-Stout from the Quincy Institute join the program to talk about their Think Tank Funding Tracker, a repository that tracks funding from foreign governments, the U.S. government, and Pentagon contractors to the top 50 think tanks in the United States over the past five years. The group discusses think tanks’ role in the “military-intellectual” complex, what specific foreign funders like the UAE and UK might be looking to influence, why certain governments like Ukraine and China gave little to no money, the lack of transparency among individuals working in sectors like journalism and government who also work with think tanks, the utilization (and under-utilization) of the Foreign Agents Registration Act, how to restructure the order so that expertise isn’t limited to these kinds of institutions, and how to make think tanks more democratically accountable in the meantime. 


Read the Quincy Institute's brief on their project, “Big Ideas and Big Money: Think Tank Funding in America.”

24 Jun 18:12

Irreal: Making TRAMP Faster

by Irreal

One of Emacs’ really nice features is TRAMP. It allows you to edit files on a remote system and otherwise interact with that system as if you were working on your local machine. The problem with it is that it can sometimes be slow, even unusably so.

Troy Hinckley over at Core Dumped has a very interesting post on making TRAMP faster. Oddly, almost everything he does is merely adjusting settings. He writes a bit of code to implement caching but even that is minimal.

Hinckley’s post is long and complicated because he explains what he’s doing and why it works. He’s spent a lot of time profiling and researching how TRAMP works. That’s nice because it means that he’s not just trying things to see if they work.

This is a short post because rather than simply listing the things that Hinckley did without explaining the reasons for them, I’m going to send you over to his post to get the full story. If you’ve tried using TRAMP but found it too slow for your particular workflow, take a look at Hinckley’s post. His changes are easy to implement so you can try them out without a lot of effort.

Happily, my use of TRAMP mostly involves the local network or remotes connected with a high speed network so I usually don’t experience these slowdowns. Even so, it’s probably worth implementing his changes.

24 Jun 16:46

Peter Povinec: Fault-tolerant Org Links

by Peter Povinec

I’m sure many Org users have experienced this: you reorganize your notes, maybe renaming a file or moving a section to a different Org file, and a few weeks later you open a link in another note only to be greeted by an unexpected prompt: “No match - create this as a new heading?”. Org tries to be helpful, even creating a new buffer for the non-existent file, assuming all along that you are creating a wiki and normally insert in your text links to targets that don't exist yet. But what if that is not your use-case? What if, instead of popping a new buffer and disrupting your flow, you want to be told that you got a broken link (knowing full well that the link target exists somewhere)? Then you can utter an expletive and carry on reading whatever you were reading, or try to find the intended target and fix the link.

Broken Org links are an unfortunate fact of life when your files and headings change over time. In my case, I kept stumbling on dead links in my org notes that have been curated for decades and survived multiple moves between cloud storage providers, note management systems (remember remember.el?), and other reorgs. I am not a big fan of spending a lot of time migrating my files and rewiring everything proactively. I wished for an Org setup that would detect a broken link and fix it right there and then, as I tried to follow it. In a sense, I wished for Org links to be fault-tolerant. At the same time, I didn't want a heavy solution, with its own consistency and maintenance burden, like globally unique Org Ids or a custom database.

I created a small set of tools to help detect and repair broken links in my Org files on the fly. My Org Link Repair code consists of three little helpers:

  • A checker hook /org-test-file-link that intercepts broken links before Org tries to apply its built-in 'nonexistent target' logic.
  • A transient menu /olr-transient to provide a quick interface for automated and manual broken link recovery tasks.
  • An interactive repair mode /olr-manual-mode that guides a user through fixing broken links one by one.

Together, these additions make it much easier to stay on top of link rot in my notes without altering how I normally create and use Org links. Let’s look at each part and how they work together in practice.

A side note on the UX: One of my design goals was to guide the user to perform the needed actions without relying on their familiarity with Org Link Repair flow. I expect this flow to be exercised rarely enough that even a user who has done it before is not expected to remember key bindings or the steps to repair their broken link. The code should try to make the process seamless and straightforward.

The helpers that I show are meant as a starting point and can be adapted or extended. I implemented detection of broken file links and a manual (user-assisted) repair strategy, because file links were the ones breaking for me and the manual strategy is the most general (the correct target file may be in an abandoned Google drive, an encrypted file bundle, or anywhere). Other link types could be tested and different repair strategies could be implemented, including a fully automated strategy, if the likely target file location is known, or can be easily searched for. Even web links could be handled similarly: detect broken links to web pages that have disappeared, and rewrite them to use a web archive (like the Wayback machine).

If you can’t prevent links from breaking, at least make them easy to find and fix.

Catching Broken Links

The first thing to do is to change the value of org-link-search-must-match-exact-headline from its default setting of query-to-create. That eliminates the wiki-centric query to create a new heading when following a broken link. But it doesn't prevent Org from popping a new buffer for a link pointing to a nonexistent file name. To suppress that, we need to do a bit more work.

Luckily Org developers provided the org-open-at-point-functions hook which makes it straightforward to intercept the link opening flow and detect a broken link due to non-existent file early. Here is my interceptor that checks for broken file links and bails out with a user error on non-existent files. It could be expanded to handle other link types and other broken link scenarios. Note that the error message tells the user what key binding to use to initiate the link repair.

(custom-set-variables '(org-link-search-must-match-exact-headline t))

(defun /org-test-file-link ()
  "Check if the file link target file exists before following it."
  (let ((ctx (org-element-context)))
    (when (and (eq (org-element-type ctx) 'link)
               (string= (org-element-property :type ctx) "file"))
      (let ((file (org-element-property :path ctx)))
        ;; If the file exists, return nil to let org-open-at-point continue
        (if (not (file-exists-p file))
            (user-error (concat "Target file not found; Use "
                                (substitute-command-keys "\\[/olr-transient]")
                                " to repair link to %s") file))))))

(add-hook 'org-open-at-point-functions #'/org-test-file-link)

A Transient Menu for Link Repair Tasks

I am using Emacs’ Transient library (the same engine behind Magit’s menus) to create a one-stop menu for all Org Link Repair activities. The command /olr-transient is a prefix command that, when invoked, pops up a transient menu with several relevant actions. This spares me from memorizing multiple separate commands or key bindings. I just hit one key sequence to get the menu, then select what I need. Here’s my initial definition of the transient menu:

(transient-define-prefix /olr-transient ()
  "Transient menu for Org Link Repair."
  [:description "Org Link Repair transient: fix your broken links\n\n"
   ["Test/Repair"
    ("l" "Lint all links in the buffer" /org-lint-links :transient nil)
    ("m" "Manually find the new target" /olr-manual-mode :transient nil)]
   ["Display/Navigate"
    ("n" "Next link" org-next-link :transient t)
    ("p" "Previous link" org-previous-link :transient t)
    ("d" "Display toggle" org-toggle-link-display :transient t)]
   ["Other"
    ("q" "Quit" transient-quit-one :transient nil)]])

(global-set-key (kbd "<f2> <return>") #'/olr-transient)

The manual repair strategy is the only one offered for now. The menu also offers linting the links in the current buffer (I have a customized version of the built-in org-lint for that), link navigation and display toggling commands.

Using a transient menu here feels like overkill for just a few commands, but I anticipate adding more link-related utilities over time. Even now, it’s nice to have a single “hub” for link management. I don’t use it every day, but when I suspect there might be broken links, I know where to go. It’s also convenient when a broken link does pop up unexpectedly. I can quickly bring up this menu and choose to repair it on the spot.

Manual Repair Strategy — Guided Link Fixing

This is the most general strategy which is why I implemented it first. The tradeoff is that it relies on the user knowing where the intended link target is and navigating to it. I found that I usually remember what happened to my abandoned Org files, even after years of not visiting them. I can usually recover them from an old archive, or one of my no-longer-used Dropbox accounts.

The strategy implements a global minor mode and a set of functions to initiate the repair flow and to complete it. When the user chooses to use this strategy, the code remembers the current location (the location of the broken link) and activates the /olr-manual-mode minor mode while the user is free to do whatever they need to locate the correct target org file and a headline. A mode line lighter provides a visual clue that the repair flow is in progress. Once the target has been located, the user would hit C-c C-c to complete the repair, which will interpret the current point as the intended link target. The code will replace the broken link at the starting location with the new link. The user is free to abandon the flow at any time with C-c C-k.

Here is my code:

;; 
;;; Org Link Repair - Manual (user-assisted) Strategy
;; 
(defvar /olr-manual-marker nil
  "Marker pointing at the original (broken) link.")

(defvar /olr-manual-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c C-c") #'/olr-manual-complete)
    (define-key map (kbd "C-c C-k") #'/olr-manual-abort)
    map)
  "Keymap for `/olr-manual-mode'.")

(easy-menu-define /olr-manual-mode-menu /olr-manual-mode-map
  "Menu for OLR Manual Mode"
  '("OrgLinkRepairManualMode"
    ["Complete" /olr-manual-complete t]
    ["Abort" /olr-manual-abort t]))

(define-minor-mode /olr-manual-mode
  "Global minor mode for Org Link Repair manual strategy.
When enabled, the marker pointing at the link at point is saved.  The user
is expected to navigate to where the link should be pointing at and call
`/olr-manual-complete' to repair the link, or `/olr-manual-abort' to cancel.
Attempting to enable this minor mode outside an Org-mode derivative, or
if the point is not at an Org link will fail with a user error."
  :lighter " LinkRepair"
  :global t

  (if (not /olr-manual-mode)
      (setq /olr-manual-marker nil)
    (unless (derived-mode-p 'org-mode)
      (user-error "Not in an Org buffer"))
    (unless (eq (org-element-type (org-element-context)) 'link)
      (user-error "Not at an Org link"))
    (setq /olr-manual-marker (point-marker))
    (message
     (substitute-command-keys
      "Manual link repair mode initiated.  Navigate to intended link target,
press \\[/olr-manual-complete] to complete, or \\[/olr-manual-abort] to abort."
      ))))

(defun /olr-manual-complete ()
   "Complete Org Link Repair by replacing the broken link at saved marker
with a new link targeted at point.
The user is expected to have navigated to the location of the new link target.
This function will call `org-store-link', then use `org-insert-all-links' to
replace the broken link, location of which was saved by `/olr-manual-mode'."
  (interactive)
  (org-store-link nil t)
  (unless (and /olr-manual-marker (marker-position /olr-manual-marker))
    (error "OrgLinkRepair: Lost marker to the original link location"))
  (switch-to-buffer (marker-buffer /olr-manual-marker))
  (goto-char (marker-position /olr-manual-marker))
  (/olr-manual-mode -1)
  (let* ((oldctx (org-element-context))
         (oldstart (org-element-property :begin oldctx))
         (oldend (org-element-property :end oldctx))
         oldlink newlink)
    ;; Delete the old link at point
    (when (and oldstart oldend)
      (setq oldlink (buffer-substring oldstart oldend))
      (delete-region oldstart oldend))
    ;; Insert the new link
    (org-insert-all-links 1 "" "")
    (let* ((newctx (org-element-context))
           (newstart (org-element-property :begin newctx))
           (newend (org-element-property :end newctx)))
      (goto-char newstart)
      (setq newlink (buffer-substring newstart newend)))
    ;; Notify the user: audibly+visibly (hopefully after auto-revert messages)
    (ding)
    (run-with-idle-timer
     0.2 nil
     (lambda () (message (concat "Modified buffer by replacing link %s with %s."
                            "\nSave the buffer to keep changes!")
                    oldlink newlink)))))

(defun /olr-manual-abort ()
  "Abort manual Org Link Repair."
  (interactive)
  (unless (and /olr-manual-marker (marker-position /olr-manual-marker))
    (error "OrgLinkRepair: Lost marker to the original link location"))
  (switch-to-buffer (marker-buffer /olr-manual-marker))
  (goto-char (marker-position /olr-manual-marker))
  (/olr-manual-mode -1)
  ;; Notify the user
  (message "Org Link Repair aborted."))

Limitations and Next Steps

Not a Complete Solution: This toolkit currently provides early interception for broken file links only. It could be extended to catch other link types if doing it early would be beneficial. For example opening web links may pop a browser window, which is annoying if we could know ahead of time that it will fail. The manual repair strategy will work for any link type, as long as it is supported by org-store-link. Again, not for web links opened in a browser.

Manual Effort: While the repair mode makes fixing easier, it’s still a manual process. I have to find the new targets or decide to remove links. There’s room for automation, e.g. suggesting likely new locations for a file (perhaps by searching for a filename in a known directory). At the moment, I actually prefer the manual control, but smarter suggestions could speed things up.

Workflow UX: I experimented with making a nicer user experience during the manual link repair workflow. I wanted to make it visually clear that the user is in the workflow and is expected to either complete it or abort it. The global minor mode lighter in the mode line doesn't seem to be enough. I tried sticking a header-line at the top, displaying a banner message and key bindings to complete/abort, but it was not reliable, and didn't look great either. I have some other ideas to try, but if you have a suggestion please let me know.

Despite these limitations, the gain in convenience has been huge for me. I can freely rename files or reorganize headings, knowing that if I forget to update a reference, Emacs will help me catch it later. And fixing it is straightforward. This is a relatively small addition to my Emacs config (just a few dozen lines of Elisp), but it solves an annoying real problem that used to steal time and momentum. And by the way, I do have LLM generated test cases for this code (see my previous blog post).

Enjoy the malleability of Emacs and the freedom it gives you!

Discuss this post on Reddit.

22 Jun 05:22

Radio War Nerd EP 531 — What's The Matter With Germany? feat. James Jackson

by mail@yashalevine.com (Gary Brecher)
Tom Roche

excellent--not as good as Corner Späti, but if you're not following CS, this is a decent introduction to German politics today

Co-hosts John Dolan & Mark Ames
21 Jun 19:41

117: Check Maté, with Aaron Maté

Tom Roche

EXCELLENT--no Matt Lieb (which decreases overall humor) but Brother Aaron (think Brother Mouzone but Jewish intellectual) brings the thinx

With Matt on assignment, Daniel is joined by Producer Adam and brother of the pod, journalist Aaron Maté to survey mysteriously shrouded Israeli weapons demonstrations, the purported expertise of the New York Times Editorial Board, and fittingly for an episode with 100% more Canadians than normal: a thorough investigation of things you can’t do on television (if hasbarists are watching).

Please support Doctors Without Borders: https://www.doctorswithoutborders.org/

To read Aaron's writing visit the Grayzone: https://thegrayzone.com/

See Francesca Fiorentini and Matt Lieb August 28 in Houston, TX: https://bit.ly/mattfranhtx

Subscribe to the Patreon https://www.patreon.com/badhasbara

What’s The Spin playlist: https://spoti.fi/4kjO9tL

Subscribe/listen to Bad Hasbara wherever you get your podcasts.

Spotify https://spoti.fi/3HgpxDm

Apple Podcasts https://apple.co/4kizajt



Support this podcast at — https://redcircle.com/bad-hasbara/donations

Privacy & Opt-Out: https://redcircle.com/privacy
20 Jun 22:40

Dead Ringers: Ep1. Greta, Trump and Eau de Farage

Tom Roche

SKIP! starts bad (not /just/ not funny, but /objectionably/ bad), and is rather consistently unfunny (which is IMHO rather unusual for 'Dead Ringers') thereafter

The Dead Ringers team are back to train their vocal firepower on the week’s news with an armoury of impressive impressions.

This week: Greta Thunberg floats her boat at Rachel Reeves, Trump and Elon couple up on Love Island, and Gary Lineker tries something new.

Cast: Jan Ravens, Jon Culshaw, Jess Robinson, Kieran Hodgson and Duncan Wisbey.

The episode was written by: Nev Fountain and Tom Jamieson, Laurence Howarth, Edward Tew, Tom Coles, Rob Darke, Sophie Dickson, Toussaint Douglas, Jon Holmes, Nicky Roberts, Jennifer Walker, Phoebe Butler, David Whitehead, Rachel E. Thorn, and Davina Bentley.

Created by Bill Dare Producer: Jon Holmes Executive Producer: Richard Morris Production Co-ordinator: Caroline Barlow

20 Jun 22:37

Live from the UK

Tom Roche

excellent, consistently amusing

Live from the UK brings you the best comedy talent from around the country, all from the comfort of your own headphones.

Stand up legend Angela Barnes talks to Glasgow about their swearing, Newcastle about their love of getting starkers on holiday, and Manchester about the rude origins of their city's name.

She brings you acts from all of these places and more, covering topics as far and wide as heatwaves, Gazza, hen dos and the George Foreman grill. How many shows can say that?

This week you can hear;

Mark Nelson at The Stand, Glasgow Louise Young at The Stand, Newcastle Hayley Ellis at the Frog and Bucket, Manchester and headliner Josh Pugh at the Glee Club, Birmingham

Additional Material by Eve Delaney

Recorded by Sean Kerwin and David Thomas Sound design by David Thomas Production Coordinator: Sarah Nicholls Executive Producer: Pete Strauss

Produced by Gwyn Rhys Davies. A BBC Studios Audio Production for Radio 4.

An EcoAudio Certified Production.

20 Jun 17:03

Irreal: Running All Code Blocks In An Org Subtree

by Irreal

If you’ve been around the Emacs technical community for a while, you know that Sacha Chua—despite being the mother of a young daughter—is an ever present and incredibly productive member of that community. One of the ways she manages that is by automating as much of her work as she can.

In a recent post she shows one such bit of automation. As almost every Org mode user knows, you can add executable code blocks to an Org file that can be executed to perform various actions, usually—but not always—altering the text of the Org file in some way. In the example that Chua gives, calendar entries are parsed and used to build crontab entries to perform certain actions in a timely manner. Chua gives the details here.

You can check out her code at the post but the aspect I want to focus on is her use of Property ID for an Org subtree. For her purposes, the ID can be used to execute every code block In the subtree. That means that she can mix various languages to build her crontab entry but execute them all with a single call to build the entry. That’s pretty neat.

The other, perhaps more useful, thing you can do with a Property ID is set an anchor point for the subtree if you export it to HTML. For example if you have a document with several subtrees—a blog post, say—that you want to publish to the Web you can have any or all of those subtrees directly addressable through a URL because the Property ID sets an anchor point for the subtree. That’s a really handy thing to know.

18 Jun 15:38

Thanos Apollo: Major update for Gnosis: 0.5.0 release

by Thanos Apollo
Tom Roche

[Gnosis](https://thanosapollo.org/projects/gnosis/) is [spaced repetition](https://en.wikipedia.org/wiki/Spaced_repetition) (think flashcard-quizing for learning) for Emacs

Gnosis just got a major update with this new release. With the long promised support of org-mode being added along with support for linking notes to org-gnosis nodes.

Org Mode Support

After hacking on org-gnosis and gaining a better understanding of how org-mode works, I decided to use org-mode for creating and exporting gnosis notes.

Notes, no matter their note type, will now be as follows:

Cloze type example.

* Thema                      :pharmacology:antimicrobials:penicillin:
:PROPERTIES:
:GNOSIS_ID: NEW
:GNOSIS_TYPE: cloze
:END:
** Keimenon 
What is the treatment for Actinomyces infection?

Penicillin

** Hypothesis 
- drug type

** Answer 
- Penicillin

** Parathema 
Sulfonamides → Nocardia
Actinomyces → [[id:680ca944-8ee9-4513-92d6-25696ee01f48][Penicillin]] 
(treatment is a SNAP)

Note that anki-like syntax is still supported for clozes.

MCQ example


* Thema                                                            :clinical:
:PROPERTIES:
:GNOSIS_ID: NEW
:GNOSIS_TYPE: mcq
:END:
** Keimenon 
A 60-year-old man comes to the physician with chills, nausea, and
diffuse muscle aches for 3 days. His niece had similar symptoms 2
weeks ago and H3N2 influenza strain was isolated from her respiratory
secretions. He received his influenza vaccination 2 months ago. His
temperature is 38.5°C. A rapid influenza test is
positive. Which of the following mechanisms best explains this
patient's infection despite vaccination?

** Hypothesis 
- Random point mutations within viral genome
- Complementing with functional viral proteins
- Exchange of viral genes between chromosomes
- Reassortment of viral RNA segments
- Acquisition of viral surface proteins

** Answer 
- Random point mutations within viral genome

** Parathema 
Random point mutations within the viral genome are responsible for
antigenic drift, which creates a new virus strain.

Each note is a thema consisting of the following components:

  • Keimenon; The main text or question.
  • Hypothesis; Assumptions/hints for the text to guide to the right answer
    • For example this is used as hints for cloze type or as choices in MCQs
  • Answer; The correct response or solution to the keimenon.
  • Parathema; expansion of keimenon, that can include links to e.g org-gnosis topics or even files, serving as a way to link org-gnosis topics to current thema.

Optionally, you can use also add tags for each note.

Notes/themas can have multiple hypotheses and answers (depending on their type), separated by gnosis-export-separator, which defaults to "\n-" (a new line followed by a dash).

Support for exporting decks

Support for exporting decks as org files via gnosis-export-deck has been added.

Support for org-gnosis notes

With this update org-gnosis is finally part of gnosis. The goal is not to just have a spaced repetition tool, but an all-in-one learning tool.

With this new update you can do reviews for specific org-gnosis topics.

  • Use M-x gnosis-review-topic to select a topic from your org-gnosis notes to review all linked themas.
  • You can link a thema to an org-gnosis topic by adding an org id link to either the parathema (recommended) or keimenon, using M-x org-gnosis-insert.

Future versions will further expand on this functionality.

Deprecated support for images

  • Image support will be rewritten in the next minor version
    • Support to display file links of images will be added.

Deprecated support for y-or-n notes

With this update your current y-or-n notes will be converted into MCQ type, with “Yes” & “No” choices.

18 Jun 00:46

943 - The Tehran Offensive feat. Séamus Malekafzali (6/16/25)

Tom Roche

VERY EXCELLENT analysis and humor

Seamus joins us to discuss last week’s “preemptive” Israeli strike on Iran, the damage done to Iranian command and infrastructure, Iran’s retaliation, America’s potential involvement. We also look at Trump’s big birthday Parade, one of the most pathetic & hilarious spectacles of American Military prowess any of us have ever seen.  Read Seamus on the attacks in the Intercept: https://theintercept.com/staff/seamus-malekafzali/Read Seamsu go long on the Axes of Resistance for Parapraxis: https://www.parapraxismagazine.com/articles/axes-of-resistanceSubscribe to Seamus’ Substack: https://www.seamus-malekafzali.com/ New merch for the summer up at https://chapotraphouse.store/