Latest Posts (20 found)
xenodium 3 weeks ago

ytr: YouTube radio for Emacs

I've been a happy ready-player user for some time now. I consider the Emacs package fairly feature-complete, for my needs anyway. Well almost. While I've successfully migrated most of my music-listening to offline playback, there are the odd times when I enjoy streaming YouTube audio. I've pondered extending ready-player for this use case, but its current approach is fairly file-driven. For starters, it uses dired as a core abstraction . Before venturing on a major refactoring, without even knowing if an Emacs streaming flow would stick, I decided to build a new package. Coincidentally, this enables me to experiment with the package UX without being restricted by 's needs. And so that's what I did in my new YouTube radio package ytr . really is fairly experimental. I'm currently driving its development purely on current needs. Let's see where it goes. It borrows lots from , but its UX presents itself more as a widget. I'm kinda liking the experience. There isn't much to it: you add a channel URL, and its content metadata is automatically pulled and presented as a child frame. I've also sprinkled in some eye candy (animations), reminiscing about the Winamp days. Beware, these sweets require running on Emacs GUI. ytr is powered by mpv and yt-dlp , the real streaming workhorses doing the heavy lifting. is available on GitHub if you're keen to check it out. Keep in mind this is a brand new package and a first iteration, so it may need some improvements. If you give it a try, I'd love to hear how you got on. I've only tested on macOS so far. Liking ? Would like to see it evolve? Consider sponsoring the effort.

0 views
xenodium 1 months ago

agent-shell 0.55 updates

It's been a little while since my last agent-shell update , so let's go through the latest highlights as of v0.55. agent-shell is a native Emacs mode to interact with AI agents powered by ACP ( Agent Client Protocol ). If you noticed slower project activity in April, this is why . I'm getting better at the new 24-hour job , so I've resumed working on agent-shell . I'm still chipping away at the backlog that built up while I was away, but if there's anything in particular you'd like me to look at, feel free to ping. With Anthropic's SDK subscription support changing , Google's Gemini CLI deprecation , and Antigravity's unclear support for the Agent Client Protocol (ACP) , vendor-neutral tools matter more than ever. Luckily, is built on ACP , which sidesteps the problem. When a vendor changes course, you can swap providers and keep using your preferred tool. No need to reshape that hard-earned muscle memory. On that note, the list of agents supported by continues to grow. Here's a list of the latest agents now supported by . Speaking of vendor-neutral tools being more important than ever, there are a couple of ways to help keep going. Some cost money, others just a click. All are appreciated ;) has been attracting quite a few users. It's nice to hear folks are using on a daily basis. They are often relieved exists as an alternative to AI-tools commonly mandated at work. Those tools have well-funded engineering teams behind them, while is just me, an indie dev ;) Time spent on is time away from work that pays the bills, so if it's useful to you, please consider sponsoring the project. Every individual sponsorship genuinely helps keep the project going. And if your employer benefits from your use, they're typically in a position to contribute at a scale individuals can't, so nudge them to chip in too. Hey, I'm looking at you, folks at Google , GitHub , GitLab , NVIDIA , Oracle , Red Hat , Yelp, Venmo, ARM , Spotify , Augment Code , Hinge, Mercury, Nubank, Veeva… Some of you are using . Nudge your employer ;) Anthropic offers 6 months of free Claude Max 20x for qualifying open-source projects with at least 5,000+ GitHub stars. Starring agent-shell costs nothing and can save me some money. We're only a 5th of the way there ;) so if you don't mind a couple of clicks, the project can really use another GitHub star . Speaking of GitHub stars, is now my most popular Emacs package, recently overtaking chatgpt-shell . agent-shell now ships with a brand new, more performant inline markdown renderer. This is the biggest internal change in some time. Enabled by default via (moving away from the overlay-based renderer in shell-maker). Table content is now accessible. Point can land on any cell, which wasn't possible with the previous overlay implementation. In addition, tables are now also navigable: and move between cells. Source-block syntax highlighting is now on by default. The per-snippet copy button is now keyboard-accessible too (previously mouse-click only, due to the overlay implementation). Blockquotes now render in both shell and viewport. More importantly, you can select text in either a viewport page (or the shell itself), press (for reply) and the selection becomes a blockquote in a fresh prompt. Session restoration got a meaningful overhaul ( #605 by @nhojb ), now exposed via , with four levels: Feature availability is agent-specific, requiring either or request support. degrades as needed, ultimately falling back to creating a new session. Note that anything but verbosity is fairly new, so please report bugs or rough edges . Relatedly, now defaults to , and has been retired. You can now fork the current session, starting a new shell that shares the conversation history so far and diverges from there. Invoke via . You can now restart the current shell anew (drop history) via or reload (keep history) via . The new and commands create agents anchored at either or a temp directory. Both are also reachable via . acp.el #20 by @martenlienen landed support for ACP connections over TRAMP, now making it possible to drive remote agents from . Pair it with agent-shell-tramp for the user-facing integration. Viewport interaction continues to be my primary way to interact with agents. It is focused (see only the latest interaction), fast (single-key bindings: = yes, = continue, = more…), and offers a richer editing experience (dedicated prompt-crafting buffer). The viewport is just a viewport to shell content. You can have your cake and eat it too, by jumping to the related shell buffer if needed. From a viewport, you can press to reply to the latest agent response. In the past, you could only reply to idle agents. You can now press to reply to busy agents too, automatically queuing requests on submission. A new (basic) lets you edit list-style content inside the viewport. Some commands prompt you to pick one of your active shell buffers (e.g. ). The picker now shows extra context for each buffer to help you choose. The same mechanism is now used by the new command. More on the underlying API later. Folding got smarter ( #608 by @codeluggage ): Together they replace the previous , which is now an internal primitive. You can now press from a viewport to quickly send a "continue" request, joining the rest of the single-key reply shortcuts: Tool call status is now rendered as a compact icon-based label by default ( ). ships several alternatives, picked via . To get the previous word-based label back: You can now set a default model and session mode for Codex via and ( #405 by @robjgray ). Both must match an ID from Codex's "Available models" / "Available modes" listings. Headers had a few rendering hiccups on Emacs 31. These are now fixed ( #588 and #590 by @nhojb , #463 by @ftlio ). Warnings from deprecated usage were also cleared. is now a supported clipboard handler for pasting images on Wayland ( #461 by @martenlienen ). Similarly, pasting clipboard images now works on Windows via PowerShell ( #572 by @repelliuss ). The graphical header got minor tweaks here and there. For example, thought level is now displayed in the header. It can be changed via as well as menus ( #601 by @martenlienen ). agent-shell now supports ACP session config options ( #553 by @greggroth and #613 by @catern ). Bind (or call ) to pick from the options the agent advertises. Broadcasted as and available externally via . You can now skip interrupt confirmations by unsetting ( #424 by @emil-e ). You can now resume an existing session by its ID via ( #332 ). Primarily useful for external integrations. You can now use to tag or transform outgoing requests. now broadcasts events ( #509 by @arthurgleckler ). returns the underlying shell buffer for the current context. jumps to the latest prompt/response pair, while returns the interaction at point as data. returns , , or status for any shell buffer. The agent-supplied session title is now exposed via the event (delivered via ) ( #559 by @smagnuso ). Can be handy for buffer names, bookmarks, or recent listings. The family of third-party packages keeps growing. Recent additions: Thank you to all contributors for these improvements! Beyond what's showcased, I've poured much love and effort into polishing the experience. Interested in the nitty-gritty? Have a look through my regular commits . If agent-shell is useful to you, please consider sponsoring the project. I'm now back to working on daily. LLM tokens aren't free, and neither is the time dedicated to building this stuff (especially as an indie dev). I also have bills to pay ;) Unless I can make this work sustainable, I will have to shift my focus to work on something else that is. ✨ Sponsor agent-shell ✨ CodeBuddy ( new by @illidan127 ) Factory Droid GitHub Copilot CLI Hermes ( new by @yitang ) Kimi Code ( new by @nicolaisingh ) Mistral Vibe (default): title only, so restore is fast and quiet (needs support). : render the last prompt turn (needs support). : render the first and last prompt turns (needs support). : replay the whole conversation (needs support). toggles the fragment at or near point (DWIM). cycles globally between all-expanded and all-collapsed. : replies "continue" (new) : replies "yes" : replies "more" : replies "again" … : replies with the corresponding numbered choice : opens the reply compose buffer : same as , with the agent response quoted agent-shell-knockknock : Notifications for via knockknock.el . agent-shell-notifications : Desktop notifications for events. agent-shell-hud : Real-time status overlay via a floating dashboard. agent-shell-pet : Codex-like pets that broadcast agent-shell session states. agent-shell-tramp : Tramp integration for . agent-circus : Run AI coding agents in sandboxed Docker containers. #308 : Fix heartbeat nil value crash in timer and busy indicator ( @ElleNajt ) #340 : Add documentation about the OAuth Anthropic authentication ( @chemtov ) #397 : Add detailed context usage indicator mode ( @emil-e ) #398 : Expose outgoing-request-decorator as a defcustom ( @emil-e ) #405 : Codex defaults for session mode and model ( @robjgray ) #408 : Use diff-command for diffing ( @timfel ) #413 : Track and manage diff buffers for each permission request ( @emil-e ) #418 : Add defvar for agent-shell-mode-hook + test ( @emil-e ) #420 : Replace all references to "Claude Code Agent" with "Claude Agent" ( @jinnovation ) #421 : Add agent-shell-clear ( @Makesesama ) #424 : Add agent-shell-confirm-interrupt option ( @emil-e ) #425 : README: Update all references to Claude Code ( @jinnovation ) #429 : Viewport attachment fixes ( @nhojb ) #438 : Fix for structured input from toolCall.rawInput.plan ( @timfel ) #442 : Add related project to README.org ( @rpoisel ) #445 : Use project-name instead of default-directory in header ( @bcc32 ) #446 : Droid: use native acp client and support default model and mode ( @kohnish ) #450 : Fix restart using wrong default-directory ( @zackattackz ) #453 : Ensure that viewport compiles ( @martenlienen ) #457 : Prefer cache directory over tmp for caching ( @martenlienen ) #460 : Unhandled method returns an error, unblocking client ( @0x6362 ) #461 : Add wl-paste as a Wayland image handler ( @martenlienen ) #463 : Fix header text invisible when font-get :size returns 0 ( @ftlio ) #469 : Do not create a file if no image in Wayland clipboard ( @martenlienen ) #473 : Caching project files completions for improved performance ( @Gleek ) #477 : Handle non-text content in user_message_chunk during session load ( @Gleek ) #483 : Add CodeBuddy agent support ( @illidan127 ) #489 : Snapshot session strategy in any case ( @timfel ) #492 : Update claude-agent-acp repository ( @Gleek ) #498 : Normalize missing MCP transport collection fields for ACP compatibility ( @CsBigDataHub ) #503 : Add agent-shell-macext to related projects ( @cxa ) #509 : Add ( @arthurgleckler ) #513 : Quote reply to the complete response with ( @martenlienen ) #515 : Make detection of binary files more robust ( @martenlienen ) #523 : Add agent-shell-org-transcript to Related projects ( @lllShamanlll ) #528 : Add support for Kimi Code CLI using ACP ( @nicolaisingh ) #529 : Sort the session list based on recency ( @smagnuso ) #530 : Add simple blinking circle as busy indicator ( @rudolf-adamkovic ) #532 : Fix removing queued messages ( @Gleek ) #536 : Add programmatic query API: agent-shell-query and agent-shell-shell-buffer ( @eddof13 ) #539 : Add ob-agent-shell to related projects in readme ( @eddof13 ) #545 : Keep buffer name on agent-shell-reload and -restart ( @timfel ) #550 : Add agent-recall to related projects ( @Marx-A00 ) #551 : Avoid gitignore update for external data dirs ( @Silex ) #552 : Use helper function from shell-maker rather than eob ( @smagnuso ) #553 : Add ACP session config options support ( @greggroth ) #554 : Fix error when cancelling session selection prompt ( @Gleek ) #555 : Add some niceties useful for ( @vermiculus ) #559 : Expose topic in agent-shell ( @smagnuso ) #561 : Update Pi coding agent logo to look more official ( @jeff-phil ) #565 : Enable @ and / completion when reading queued prompts ( @Gleek ) #571 : Fix unkillable buffer after major-mode change ( @Scott-Guest ) #572 : Add clipboard image support for Windows ( @repelliuss ) #574 : Add agent-shell-pet link to README ( @lgmoneda ) #582 : Add a few additional forward declarations ( @tychoish ) #583 : Add Hermes Agent support ( @yitang ) #588 : Fix header foreground color (emacs 31) ( @nhojb ) #589 : Only trim response region when region is active ( @martenlienen ) #590 : Fix context-limit header color (emacs-31) ( @nhojb ) #595 : Fix completion regression in viewport buffers ( @Gleek ) #600 : Do not emit permission-request for auto-handled permissions ( @Gleek ) #601 : Expose thought level (reasoning effort) in header, mode line and keymaps ( @martenlienen ) #602 : Update README with Opencode and Ollama setup instructions ( @dvictori ) #605 : Add defcustom ( @nhojb ) #608 : Toggle folding for everything & comfortably fold at point ( @codeluggage ) #609 : Prevent accidental auto-scrolling in viewport buffers on tool calls ( @martenlienen ) #611 : Fix ( @TamsynUlthara ) #613 : Improve completion for set-session-config-option ( @catern ) #618 : Fix header not showing session mode name ( @deftsp ) #621 : Reindent Elisp files ( @bcc32 ) #623 : Add agent-shell-hud to related packages ( @nohzafk ) #625 : Fix source-block face background not rendering when theme loads after package ( @phairoh ) #627 : Hermes: add default-session-mode-id to match other agents ( @yitang ) #629 : Write to instead of ( @phairoh ) #632 : Render tool call parameters for non-standard tools like MCP calls ( @martenlienen ) #633 : Add GitHub Actions workflow for ERT tests ( @phairoh ) #634 : Update art generated by ( @TamsynUlthara ) #639 : Preserve window position when restarting ( @Gleek ) #202 : Header icon is double the expected size #278 : Heartbeat causes high CPU usage with many agent buffers #366 : directory at risk when switching git branches #400 : errors with "Text is read-only" #401 : Garbled characters output when using non-English languages #412 : Diff buffer management is messy #414 : timing makes subscribing to events difficult #417 : Unhandled notifications with kiro #426 : Starting conversation before agent has initialized leaves "dangling" text #431 : Heartbeat timer keeps running after failed/abandoned authentication in OpenAI #435 : clipboard handler silently saves text as PNG in terminal mode #441 : Background agent notifications treated as stale after response #443 : : Invalid image type on calling agent-shell #455 : agent-shell enters frozen/hanging state when receiving unknown notifications #462 : Header text invisible when returns 0 #465 : Session load crashes on non-text user message chunks (e.g. images) #466 : / now focus the originating shell #468 : breaks pasting text #481 : History input rolls back in editing mode while pressing up/down arrows #485 : Shells created in other workspaces no longer display #493 : Tables rendered in agent-shell break cursor (point) navigation #533 : Can't install agent-shell from MELPA #548 : Copied highlighted text from agent output includes trailing backtick #563 : "Cannot modify map in-place" when starting agents #577 : does not work in an function #587 : Long region preview's "Expand…" button is sent literally to the agent #617 : OpenCode: consent prompt shows empty input when arrives before populates

0 views
xenodium 3 months ago

…and then there were three (expect delays)

The other day, my partner and I went into the hospital as two and came out as three. This week, I became a father. From the second I cuddled this little fella, I felt like I'd known him my entire life. I love him so much. Since going indie dev full-time, I've enjoyed a great degree of flexibility to work on personal projects. This has enabled me to share more via blog posts and YouTube videos , but also dedicate more time to projects like agent-shell . It is now my most popular Emacs package, receiving lots of attention from users (bug reports, pull requests, discussion, etc). If you've been in touch recently and haven't heard from me, now you know why. Fatherhood is new to me. I'll need a little time to adjust while finding my footing. While my hope is to continue working on my indie projects, sustainability is now… errm, a tad more important. If you get value out of my work, please consider sponsoring . Better yet, if you use my tools at work, consider getting your employer to sponsor me instead. I also run a blogging service and offer a handful of iOS/macOS apps . If you're keen to journal or take quick notes on iOS, Journelly is my take on it. Bonus points for Emacs users, as it saves entries to an org file. Now, please excuse me while I start crafting my son's first init.el … ps. This post was stitched up from a handful of seconds here and there, in between all the sleep-deprived but loving activities currently rocking my world.

0 views
xenodium 4 months ago

agent-shell 0.47 updates

We got quite a few agent-shell additions since the last post , so let's go through the highlights as of . Agent shell is a native Emacs mode to interact with LLM agents powered by ACP ( Agent Client Protocol ). has been attracting quite a few users. Many of you are working in tech where employers are happily paying for IDE subscriptions and LLM tokens to improve productivity. If you are using for work, consider getting your employer to give back by sponsoring the project. I also know many of you work at AI companies offering paid agents like Claude Code, Copilot, Gemini, Codex, etc. all supported by . Please nudge your employers to help fund projects like , which are making their services available to more users. Let's get this one out of the way, as it needs actioning. Both the npm package and the CLI agent have been renamed from to (to align with Anthropic's branding guidelines ). If you're using Claude Code, you'll need to update: If you had customized , update it to point to . This was a biggie. How sessions are loaded is now configurable via . When set to , starting a new shell delivers a fully bootstrapped session before presenting you with the shell prompt. This means the ACP handshake, authentication, and session creation all happen upfront. You can enable this flow with: What's the benefit? Bootstrapped sessions enable changing models and session modes (Planning, Don't ask, Skip permissions, etc…) before submitting your first prompt. For the time being, the existing (deferred) behaviour is still offered via . Just set as follows: Probably the most requested feature and also facilitated by the bootstrapping changes. also unlocks session resume. Set it to and every time either or are invoked, you'll be offered to resume previous sessions or start a new one. Alternatively, you can set to to always resume the most recent session in current project. Under the hood, there are two ways to pick up from previous session: session/resume (lightweight, no message replay) and session/load (full history replay). By default, prefers resuming (controlled by ). Please favor resuming for the time being as loading has more edge cases to sort out still. Note: Both resuming and loading sessions are agent-dependent. Some agents may not yet support either, especially as the features aren't yet considered stable in Agent Client Protocol (see session/list spec). This feature was a collaboration between @farra , @travisjeffery , and myself. You can now use ( #285 by @dangom ) to send images straight from your clipboard into . Clipboard images are saved to in your project root and inserted into the shell buffer as context. Note: You'll need either or installed on your system for the feature to automatically kick in. In addition, we now have : if the clipboard has an image, it pastes it as context. Otherwise, it yanks text as usual. In other words, copy an image anywhere to your system's clipboard and paste/yank into the buffer as usual (typically via ). Status labels and tool call titles rendering got some improvements. Status reporting is generally more compact, redundant text is dropped from tool call titles, and tool status/kind shortening has been consolidated. now renders images inline. When agents output images (charts, diagrams, screenshots, etc.), they display directly in the shell buffer. You may need to nudge the agent to output image paths in the expected format so can pick up. Markdown images: Any of the following in a line of their own are supported also: Recognized image formats depend on what your Emacs was built with (typically png, jpeg, gif, svg, webp, tiff, etc. via ). While on the topic of image rendering, this works particularly well when coupled with charting agent skills . I shared some of these over at emacs-skills , demoed in episode 13 of the Bending Emacs series. Table rendering Tables are now rendered using overlays ( #17 by @ewilderj ). Tracking usage now possible ( #270 by @Lenbok ): If keen to run multiple agents on the same repo without stepping on each other's work, facilitates this via git worktrees ( #255 by @nhojb ). You can now send context to a specific shell using , , . and . These prompt you to pick a target shell. Both and are now prefix-aware. forces a new shell, while prompts you to pick a target shell. Compose buffers now support file (via @) and command (via /) completions. It is now also possible to browse previous pages via and come back to your prompt draft. There's also prompt history navigation/insertion when composing prompts via (previous), (next), and (search). Bringing context into viewport compose buffers is now more robust. For example, carrying context into a new viewport compose buffer is now supported ( #383 by @liaowang11 ). While viewport interaction was introduced in the previous post , it is now my preferred way of interacting with agent-shell. You can enable via . In any case, viewport buffers got a handful of quality-of-life improvements. Single key replies without needing to open a compose/reply buffer: lets you configure which DWIM context sources are considered by , , and compose buffers. You can control the order sources are checked and add custom functions. Defaults to , , , and . I'm always on the lookout for some DWIM goodness. If you add your own context function, I'd love to hear about it. While on the topic of context sources, in addition to picking up flymake errors at point, flycheck errors are now automatically recognized ( #219 by @Lenbok ). Diff buffers got some love too, now with syntax highlighting ( #198 by @Azkae ). There's also a new for customizing diff keybindings, which avoid inheriting unsupported features from the parent mode. You can also press to open the modified file from a diff buffer. Additionally, you can now press from an buffer to reject all changes (same binding as the shell itself). You can now programmatically subscribe to events like initialization steps, tool call updates, file writes, permission responses, permission requests, and turn completions. This opens the door for building integrations on top of . Permission dialogs got a few improvements. Amongst them, automatic navigation to the next pending dialog and also making executed commands more prominent for some agents. You can now programmatically respond to permission requests via . A built-in handler is provided to auto-approve everything (use with caution): OAuth token now supported for Claude Code ( #339 by @chemtov ). Markdown transcripts generation needed love. Thank you @Idorobots and @systemfreund for the improvements ( #374 , #325 , and #326 ). With , session IDs are now displayed in header as well as session lists ( #363 by @Cy6erBr4in ). now enables customizing how determines the working directory sent to agents. now lets you customize where keeps per-project files ( #378 by @zackattackz ). now accept lambda functions too ( #237 by @matthewbauer ). Useful for setups like using dynamic MCP details. now makes buffer naming configurable. Choose between the default title case ( ), kebab-case ( ), or provide your own function ( #256 by @nhojb ). lets you temporarily disable modes (like auto-formatting entire file) when agents write files ( #224 by @ultronozm ). File autocompletion is now more performant for larger repositories ( #262 by @perfectayush ). When running shells inside a container, a indicator now shows up in the modeline ( #250 by @ElleNajt ). Graphical header rendering is more robust now ( #275 by @nhojb ). The busy/working indicator now offers multiple visual styles, customizable via ( #280 by @Lenbok ). Thank you to all contributors for these improvements! Beyond what's showcased, I've poured much love and effort into polishing the experience. Interested in the nitty-gritty? Have a look through my regular commits . If agent-shell is useful to you, please consider sponsoring the project. These days, I've been working on daily. LLM tokens aren't free, and neither is the time dedicated to building this stuff. While I now have more time to work on as an indie dev, I also have bills to pay ;) Unless I can make this work sustainable, I will have to shift my focus to work on something else that is. Auggie ( #179 by @Pacane ). Factory Droid ( #178 by @ag91 ). GitHub Copilot. Kiro CLI ( #351 by @zmjones ). Mistral Vibe. Pi ( #232 by @conornash ) A color-coded context usage indicator in the header (green -> yellow -> red as context fills up), enabled by default via . to check token counts, context window usage, and cost in the minibuffer.r- An optional end-of-turn usage summary can be enabled via . sends "yes" (handy for quickly answering agent questions). sends digits (handy for quickly choosing options). sends "more" (handy for requesting more of the same kind of data). sends "again" (handy for requesting to carry out instructions again). agent-shell-to-go : Interact with sessions from your mobile or any other device via Slack (by @ElleNajt ). meta-agent-shell : Multi-agent coordination system for with inter-agent communication, task tracking, and project-level dispatching (by @ElleNajt ). agent-shell-workspace : Dedicated tab-bar workspace for managing multiple sessions (by @gveres ). #159 : Improve Mistral Vibe documentation ( @KaiHa ) #162 : Fix agent-shell-help-menu binding ( @jinnovation ) #164 : Fix nil-check semantics in ( @jinnovation ) #166 : Use project-name for buffer names ( @catern ) #169 : Resolve paths in devcontainers ( @fritzgrabo ) #173 : Fix binding issue ( @byronclark ) #178 : Add Factory Droid capability ( @ag91 ) #179 : Add Auggie support ( @Pacane ) #185 : Update OpenCode logo ( @bps ) #186 : Use context in viewport mode ( @byronclark ) #193 : Handle session update type ( @Lenbok ) #196 : Fix agent names when config icons are off ( @budevg ) #197 : Function-based container command runner ( @rpoisel ) #198 : Syntax highlighting in diffs ( @Azkae ) #199 : Fix reply in viewport mode ( @byronclark ) #200 : Prevent context from own agent-shell buffer ( @juboba ) #204 : Terminal-mode status labels ( @whhone ) #206 : Add Evil section to README ( @juboba ) #208 : Theme-aware status label color ( @whhone ) #209 : Add missing require ( @timvisher ) #212 : Simplify language detection ( @necaris ) #213 : Improve file and command completion ( @necaris ) #214 : Fix auto-insert variable declaration ( @ultronozm ) #219 : Flycheck error context support ( @Lenbok ) #224 : Inhibit minor modes during file writes ( @ultronozm ) #226 : Deduplicate file link ( @bixuanzju ) #232 : Add Pi coding agent ( @conornash ) #235 : Fix empty list normalizer ( @ROCKTAKEY ) #237 : Lambda MCP servers ( @matthewbauer ) #240 : Fix viewport shell buffer association ( @Rutherther ) #245 : Fix state maintenance ( @vermiculus ) #246 : Respect viewport visits for buffer ordering ( @Rutherther ) #249 : Fix tool call title duplication ( @ElleNajt ) #250 : Container modeline indicator ( @ElleNajt ) #252 : Document to send ( @HIRANO-Satoshi ) #255 : Git worktree shell ( @nhojb ) #256 : Buffer name format customization ( @nhojb ) #257 : Fix kebab-case project name ( @nhojb ) #262 : File autocompletion speedup ( @perfectayush ) #266 : Guard permission title rendering ( @budevg ) #269 : Add missing paren ( @Rutherther ) #270 : Session usage tracking ( @Lenbok ) #272 : Update Copilot ASCII art ( @ewilderj ) #275 : Graphical header improvements ( @nhojb ) #279 : Add to transient ( @matthewbauer ) #280 : Busy throbber options ( @Lenbok ) #285 : Clipboard image pasting ( @dangom ) #289 : Session list/load/resume ( @farra , @travisjeffery ) #291 : Normalize tool call commands ( @ultronozm ) #292 : Strip text properties from copied text ( @ultronozm ) #293 : Restore usage indicator color ( @Lenbok ) #295 : Handle tools without a command ( @byronclark ) #296 : Handle nil tool-call command ( @genegoykhman ) #299 : claude-code-acp -> claude-agent-acp rename ( @byronclark ) #312 : Function-valued model ID ( @lgfang ) #316 : Fix diff syntax highlighting ( @Azkae ) #318 : Tool call parameters in transcripts ( @systemfreund ) #319 : Fix terminal Emacs font crash ( @eddof13 ) #325 : Log agent thoughts in transcript ( @Idorobots ) #326 : Fix nested backtick fences in transcript ( @systemfreund ) #328 : Switch modes in agent-shell-diff ( @wmedrano ) #329 : Fix tests ( @timvisher-dd ) #313 : Bring "Start a new session" to the top ( @catern ) #335 : Fix plan from request_permission ( @Azkae ) #339 : OAuth token support for Anthropic ( @chemtov ) #350 : Prepare devcontainer package extraction ( @fritzgrabo ) #351 : Add Kiro CLI ACP support ( @zmjones ) #353 : Fix xclip blocking on X11 ( @chemtov ) #363 : Configurable session selection columns ( @Cy6erBr4in ) #370 : Fix permission UI on out-of-order status updates ( @xar7 ) #374 : Indent markdown headers in transcript ( @systemfreund ) #376 : Fix file skip check ( @zackattackz ) #378 : Configurable dot-subdir location ( @zackattackz ) #382 : Permission-request and turn-complete subscription events ( @emil-e ) #383 : Viewport context on first open ( @liaowang11 ) #385 : Fix leading space in terminal prompt ( @bcc32 ) #388 : Apply dir-local variables in shell buffer ( @fritzgrabo ) #168 : timeout to prevent freeze on large diffs #170 : Suppress effects of during agent writes #175 : ACP configuration JSON-RPC inserted into shell #180 : Terminal-friendly keybindings #189 : Changing the model with Claude causes hang #191 : session updates no longer dump raw JSON #220 : Python comments no longer interpreted as Markdown headers #265 : with argv array commands #297 : Unexpected tool-call command type error #300 : no longer fails silently without a region #303 : Context insertion for new deferred sessions #319 : Fix "Wrong type argument: font, unspecified" in terminal Emacs (fix by @eddof13 ) #335 : Plan not displaying from (fix by @Azkae ) #345 : Out of turn notifications inserted into shell #353 : xclip handler blocking on X11 when clipboard has no image (fix by @chemtov ) #361 : regression #370 : Permission UI not reacting on status failed/completed (fix by @xar7 ) #376 : File skip check using full path instead of filename only (fix by @zackattackz ) #385 : Leading space in prompt in terminal frames (fix by @bcc32 )

0 views
xenodium 4 months ago

Bending Emacs - Episode 13: agent-shell charting

Time for a new Bending Emacs episode. This one is a follow-up to Episode 12 , where we explored Claude Skills as emacs-skills . Bending Emacs Episode 13: agent-shell + Claude Skills + Charts This time around, we look at inline image rendering in agent-shell and how it opens the door to charting. I added a handful of new charting skills to emacs-skills : /gnuplot , /mermaid , /d2 , and /plantuml . The agent extracts or fetches data from context, generates the charting code, saves it as a PNG, and agent-shell renders it inline. Cherry on top: the generated charts match your Emacs theme colors by querying them via . Hope you enjoyed the video! Liked the video? Please let me know. Got feedback? Leave me some comments . Please like my video , share with others, and subscribe to my channel . As an indie dev, I now have a lot more flexibility to build Emacs tools and share knowledge, but it comes at the cost of not focusing on other activities that help pay the bills. If you benefit or enjoy my work please consider sponsoring .

0 views
xenodium 4 months ago

Ready Player cover download improvements

At times, even purchased music excludes album covers in track metadata. For those instances, ready-player-mode offers , which does as it says on the tin. The interactive command offers a couple of fetching providers (iTunes vs Internet Archive / MusicBrainz) to grab the album cover. The thing is, I often found myself trying one or the other provider, sometimes without luck. Today, I finally decided to add a third provider ( Deezer ) to the list. Even then, what's the point of manually trying each provider out when I can automatically try them all and return the result from the first successful one? And so that's what I did. In addition to offering all providers, now offers "Any", to download from the first successful provider. Now, why keep the option to request from a specific provider? Well, sometimes one provider has better artwork than another. If I don't like what "Any" returns, I can always request from a specific provider. While on the subject, I also tidied the preview experience up and now display the thumbnail in the minibuffer. In any case, best to show rather than tell. Enjoying your unrestricted music via Emacs and ? ✨ sponsor ✨ the project.

0 views
xenodium 4 months ago

Bending Emacs - Episode 11: winpulse

I recently built a little package to flash Emacs windows as you switch through them, so I might as well showcase it in a new Bending Emacs episode, so here it goes: Bending Emacs Episode 11: winpulse In addition to showcasing winpulse , we showed some of the built-in window-managing commands like: It's worth noting the last four commands are can be optimized by repeat-mode . Check out Karthink's It Bears Repeating: Emacs 28 & Repeat Mode post. Hope you enjoyed the video! Liked the video? Please let me know. Got feedback? Leave me some comments . Please go like my video , share with others, and subscribe to my channel . If there's enough interest, I'll continue making more videos! Enjoying this content or my projects ? I am an indie dev. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;) split-window-right split-window-below delete-window enlarge-window enlarge-window-horizontally shrink-window-horizontally other-window

0 views
xenodium 5 months ago

Introducing winpulse

Hard to say officially, but I've been primarily using Emacs for roughly a couple of decades. Maybe my eyesight isn't what it used to be, or maybe I've just been wanting a stronger visual signal as I navigate through Emacs windows. Either way, today's the day I finally did something about it… I asked around to see if a package already existed for this purpose. Folks shared a handful of great options: I wanted my windows to temporarily flash when switching between them. Of these options, pulsar came closest, though highlighting the current line only. This is Emacs, so I should be able to get the behavior I want by throwing some elisp at the problem. With that, I give you winpulse , a package to temporarily highlight focused Emacs windows. This package is fresh out of the oven and likely has some edge cases I haven't yet considered. If you're still keen to check it out, it's available on GitHub . Enjoying this package or my content? I'm an indie dev. Consider sponsoring to help make it sustainable. pulsar: Emacs package to pulse the current line after running select functions. dimmer.el: Interactively highlight the active buffer by dimming the others. window-dim.el: A window dimmer package for Emacs.

0 views
xenodium 5 months ago

Introducing Kitty Cards

Back in 2023, I toyed with the relevant iOS dev tools needed to create a custom Tesco Clubcard pkpass , and even showed how to scan a QR code from our beloved Emacs (of course). Neither my friend Vaarnan nor I are strangers to the iOS ecosystem, yet we both agreed the above approach wasn't very practical (for neither devs nor the average iOS user). So we figured we should have a crack at it. While there are some ready-made solutions out there, they often require downloading additional iOS apps or working through clunky web interfaces. We just wanted a simpler way to create our own Apple Wallet cards, and so Kitty Cards ( kitty.cards ) was born: no app download or sign-in required. Hopefully not much to explain. From kitty.cards , customize a card, press the button, and Bobs your uncle . Hope you enjoy Kitty Cards !

0 views
xenodium 6 months ago

Bending Emacs - Episode 9: World times

A new year, a new Bending Emacs episode, so here it goes: Bending Emacs Episode 9: Time around the world Emacs comes with a built-in world clock: To customize displayed timezones, use: Each entry requires a valid timezone string (as per entries in your system's ) and a display label. I wanted a slightly different experience than the built-in command ( more details here ), so I built the time-zones package. is available on MELPA , so you can install with: Toggle help with the key add cities with the key. Shifting time is possible via the / keys, in addition to a other features available via the help menu. Hope you enjoyed the video! Liked the video? Please let me know. Got feedback? Leave me some comments . Please go like my video , share with others, and subscribe to my channel . If there's enough interest, I'll continue making more videos! Enjoying this content or my projects ? I am an indie dev. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;)

0 views
xenodium 6 months ago

My 2025 review as an indie dev

In 2024, I took the leap to go indie full-time. By 2025, that shift enabled me to focus exclusively on building tools I care about, from a blogging platform, iOS apps, and macOS utilities, to Emacs packages. It also gave me the space to write regularly, covering topics like Emacs tips, development tutorials for macOS and iOS, a few cooking detours, and even launching a new YouTube channel . The rest of this post walks through some of the highlights from 2025. If you’ve found my work useful, consider sponsoring . Now let’s jump in. For well over a decade, my blogging setup consisted of a handful of Elisp functions cobbled together over the years. While they did the job just fine, I couldn't shake the feeling that I could do better, and maybe even offer a blogging platform without the yucky bits of the modern web. At the beginning of the year, I launched LMNO.lol . Today, my xenodium.com blog proudly runs on LMNO.lol . LMNO.lol blogs render pretty much anywhere (Emacs and terminals included, of course). 2026 is a great year to start a blog ! Custom domains totally welcome. Sure, there are plenty of journaling and note-taking apps out there. For one reason or another, none of them stuck for me (including my own apps). That is, until I learned a thing or two from social media. With that in mind, Journelly was born : like tweeting, but for your eyes only . With the right user experience, I felt compelled to write things down all the time. Saving to Markdown and Org markup was the mighty sweet cherry on the cake. As a Japanese language learning noob, what better way to procrastinate than by building yet another Kana-practicing iOS app? Turns out, it kinda did the job. Here's mochi invaders , a fun way to practice your Kana 2025 brought us the likes of Claude Code, Gemini CLI, Goose, Codex, and many more AI/LLM CLI agents. While CLI utilities have their appeal, I wanted a native Emacs integration, so I simply ignored agents for quite some time. I was initially tempted to write my own Emacs agent, but ultimately decided against it. My hope was that agent providers would somehow converge to offer editor integration, so I could focus on building an Emacs integration while leveraging the solid work from many teams producing agents. With LLM APIs historically fragmented, my hope for agent convergence seemed fairly far-fetched. To my surprise, ACP ( Agent Client Protocol ) was announced by Zed and Google folks . This was the cue I had been waiting for, so I set out to build acp.el , a UX agnostic elisp library, followed by an actual client: agent-shell . I'm fairly happy with how 's been shaping up. This is my most popular package from 2025, receiving lots of user feedback . If you're curious about the feature-set, I've written about 's progress from early on: While agent-shell is the new kid on the block, chatgpt-shell received DeepSeek, Open Router, Kagi, and Perplexity support , in addition to a handful of other improvements and bugfixes. While most of what I share usually ends up as a blog post, this year I decided to try something new. I started the Bending Emacs YouTube channel and posted 8 episodes: Enjoying the content? Leave me a comment or subscribe to my channel . While I enthusiastically joined the Emacs Carnival , I didn't quite manage monthly posts. Having said that, when I did participate, I went all in, documenting my org experience over the last decade . Ok well… I also joined in with my elevator pitch ;) While migrating workflows to Emacs makes them extra portable across platforms, I've also accumulated a bunch of tweaks enhancing your Emacs experience on macOS . While we're talking macOS, I typically like my desktop free from distractions, which includes hiding the status bar. Having said that, I don't want to lose track of time, and for that, I built EverTime , an ever-present floating clock (available via Homebrew). Emacs ships with a perfectly functional world clock, available via , but I wanted a little more, so I built time-zones . Also covered in: For better or worse, I rely on WhatsApp Messenger. Migrating to a different client or protocol just isn't viable for me, so I did the next best thing and built wasabi , an Emacs client ;) While not a trivial task, wuzapi and whatsmeow offered a huge leg up. I wanted tighter Emacs integration, so I upstreamed a handful of patches to add JSON-RPC support, plus easier macOS installation via Homebrew . Details covered in a couple of posts: While both macOS and iOS offer APIs for generating URL previews, they also let you fetch rich page metadata. I built rinku , a tiny command-line utility, and showed how to wire it all up via eshell for a nifty shell experience. With similar magic, you can also get a neat experience. I always liked the idea of generating some sort of art or graphics from a code base, so I built one , a utility to transform images into character art using text from your codebase. Also covered in a short blog post . Emacs is just about the perfect porcelain for command-line utilities. With little ceremony, you can integrate almost any CLI tool. Magit remains the gold standard for CLI integration. While trimming videos doesn't typically spring to mind as an Emacs use case, I was pleasantly surprised by the possibilities . While I've built my fair share of Emacs packages , I'm still fairly new at submitting Emacs features upstream. This year, I landed my send-to (aka sharing on macOS) patch . While the proposal did spark quite the discussion , I'm glad I stuck with it. Both Eli and Stefan were amazingly helpful. This year, I also wanted to experiment with dictating into my Emacs text buffers, but unfortunately dictation had regressed in Emacs 30 . Bummer. But hey, it gave me a new opportunity to submit another patch upstream . Ready Player , my Emacs media-playing package received further improvements like starring media (via Emacs bookmarks), enabling further customizations, and other bug fixes. Also showcased a tour of its features . Hope you enjoyed my 2025 contributions. Sponsor the work. agent-shell 0.25 updates agent-shell 0.17 improvements + MELPA agent-shell 0.5 improvements Introducing Emacs agent-shell (powered by ACP) Introducing acp.el So you want ACP (Agent Client Protocol) for Emacs? Bending Emacs - Episode 1: Applying CLI utils Bending Emacs - Episode 2: From vanilla to your flavor Bending Emacs - Episode 3: Git clone (the lazy way) Bending Emacs - Episode 4: Batch renaming files Bending Emacs - Episode 5: Ready Player Mode Bending Emacs - Episode 6: Overlays Bending Emacs - Episode 7: Eshell built-in commands Bending Emacs - Episode 8: completing-read time-zones now on MELPA. Do I have your support? Emacs time-zones WhatsApp from you know where Want a WhatsApp Emacs client? Commits: 1,095 Issues created: 37 PRs reviewed: 106 Average commits per day: ~3 EverTime - An ever present clock for macOS acp.el - An ACP implementation in Emacs lisp agent-shell - A native Emacs buffer to interact with LLM agents powered by ACP diverted - Identify temporary Emacs diversions and return to original location emacs-materialized-theme - An Emacs theme derived from Material homebrew-evertime - EverTime formula for the Homebrew package manager homebrew-one - Homebrew recipe for one homebrew-rinku - Homebrew recipe for rinku one - Transform images into character art using text from your codebase rinku - Generate link previews from the command line (macOS) time-zones - View time at any city across the world in Emacs video-trimmer - A video-trimming utility for Emacs wasabi - A WhatsApp Emacs client powered by wuzapi and whatsmeow Journelly 1.3 released: Hello Markdown! agent-shell 0.25 updates Bending Emacs - Episode 8: completing-read At one with your code Bending Emacs - Episode 7: Eshell built-in commands Rinku: CLI link previews Bending Emacs - Episode 6: Overlays WhatsApp from you know where Want a WhatsApp Emacs client? Will you fund it? Bending Emacs - Episode 5: Ready Player Mode agent-shell 0.17 improvements + MELPA time-zones now on MELPA. Do I have your support? Bending Emacs - Episode 4: Batch renaming files Emacs time-zones Bending Emacs - Episode 3: Git clone (the lazy way) agent-shell 0.5 improvements Bending Emacs - Episode 2: From vanilla to your flavor Bending Emacs - Episode 1: Applying CLI utils Introducing Emacs agent-shell (powered by ACP) Introducing acp.el So you want ACP (Agent Client Protocol) for Emacs? Diverted mode Who moved my text? Dired buffers with media overlays Brisket recipe A tiny upgrade to the LLM model picker Emacs elevator pitch Emacs as your video-trimming tool macOS dictation returns to Emacs (fix merged) Writing experience: My decade with Org Interactive ordering of dired items Patching your Homebrew's Emacs Plus (macOS) Emacs send-to (aka macOS sharing) merged upstream Mochi Invaders now on the App Store Markdown is coming to Journelly EverTime available via Homebrew Journelly 1.2 released Ranking Officer now on the App Store Awesome Emacs on macOS Journelly 1.1 released LLM text chat is everywhere. Who's optimizing its UX? A richer Journelly org capture template Journelly: like tweeting but for your eyes only (in plain text) Journelly vs Emacs: Why Not Both? The Mac Observer showcases Journelly Journelly open for beta DeepSeek, Open Router, Kagi, and Perplexity join the chat Keychron K3 Pro: F1-F12 as default macOS keys E-ink bookmarks Sourdough bookmarks Cardamom Buns recipe A tour of Ready Player Mode A platform that moulds to your needs Blogging minus the yucky bits of the modern web

0 views
xenodium 6 months ago

Journelly 1.3 released: Hello Markdown!

Journelly 1.3 available on the App Store Journelly feels like tweeting but for your eyes only. A fresh take on frictionless note-taking or journaling for iOS, powered by plain text (Markdown + Org). Check out journelly.com for details. Journelly v1.3 brings Markdown support (the most requested feature) along with Simplified Chinese localization and other new enhancements. By far the most requested feature. Thank you to everyone who reached out, shared interest, and helped beta test early builds. Whether you're a fan of Markdown or an Org-mode enthusiast, Journelly lets you store entries in your preferred format. You can now choose your favorite markup on first launch or via the app menu. While on topic, I also run lmno.lol , a Markdown-powered blogging service. Simple and focused, without the frustrating parts of the modern web. Custom domains welcome. My xenodium.com blog runs off lmno.lol . Simplified Chinese (简体中文) is now available, joining Journelly's list of supported languages: A home screen widget is now available, offering quick access to three key actions right from the home screen. Prefer clear buttons over swipe gestures? You can now enable Discoverable Mode under “Menu > View.” This new mode makes features more visible and easier to navigate, perfect for folks favoring more explicit interaction over gestures or subtle hints. For Org users: Journelly now renders both quote and code blocks. The entry list received a little refresh to make better use of screen space. Bottom-aligned controls also make for easier one-handed use. Since launch , Journelly has remained a single-payment app. No subscriptions . I get it, subscriptions are no fun. That said, sustainable development is tough without regular downloads . I'm hoping the new Markdown support helps Journelly reach a wider audience. Help Journelly grow: Hope you enjoy the v1.3 update. Thank you for using Journelly and supporting indie development 💛💙❤️ Save cooking recipes, movies, music, restaurants, coffee shops… Jot down your thoughts. Save your favorite quotes. Use it as a journal, memo book, or notes. Write your shopping lists. Document your travels. Simplified Chinese (简体中文) Leave a review on the App Store . Share Journelly with your friends.

0 views
xenodium 6 months ago

agent-shell 0.25 updates

It's been a little while since the last agent-shell blog post detailing changes , so we're naturally due another one detailing the latest features. A native Emacs shell to interact with any LLM agent powered by ACP ( Agent Client Protocol ). Let's go through the latest changes… The biggest change is the new experimental viewport/compose mode. While agent-shell's comint shell experience has its benefits, some folks may opt for a more familiar buffer experience, that is less shell-like. There are perhaps 3 defining characteristics in the new viewport/compose feature: A dedicated compose buffer : You get a full, multiline buffer dedicated to crafting prompts. I personally find this mode of operation more natural (no need to watch out for accidental submissions via RET), but also opens up the possibility to enable your favourite minor modes that may not play nice with . You can launch compose buffers via , edit your prompt, and when you're ready, submit with the familiar binding. Viewport : I've experimented with shell viewports before and also added a similar experience to chatgpt-shell . This compose/viewport UX quickly became my primary way of interacting with non-agent LLMs. This is a read-only buffer typically displaying the latest agent interaction. Use to navigate through current interaction items. Use to switch through pages/interactions. Auto-modal : Compose and viewport modes complement each other and offer automatic transition between read-only and editable (compose) buffers. From a viewport, you can always press to reply to the latest interaction. When replying, you automatically go into edit/compose mode. When submitting via , you automatically transition into viewport (read-only) mode. While you can use at any time to compose multi-line prompts and send from the shell, to get the hybrid experience, you need to enable with . From then on, will favor the experience. You can always jump between viewport and shell with . buffers now offer the ability to queue additional prompts if the agent is busy. Use and to queue and remove requests. You can now change models via ( ), when supported by the agent. For Anthropic users, we now have and to set default agent model and modes. You can view available values by expanding shell handshake items. If keen on using defaults for a different agent, please file a feature request . By default, launching via prompts users to select one of the supported agents. You can now skip this by setting your preferred agent ( thank you Jonathan ). While shell-maker automatically prompts users to save content when killing buffers, its integration was a little clunky with agents. Elle Najt's -specific implementation is now enable by default, saving Markdown transcripts to . When launching new shells, you should see a message like: You can always open the current transcript via . To disable the new transcript generation use: Jonathan Jin introduced , enabling folks to add MCP servers to their agents. For example: You can now search across shell nodes, including collapsed ones. When using isearch ( swiper too), matching nodes are now automatically expanded. When invoking , active region, flymake errors, dired and image buffers are now automatically considered and brought over to buffers to be included while crafting prompts. There's one more. From a viewport buffer, selecting a region and pressing "r" (for reply) brings the selection over to the compose buffer as blockquoted text. We've migrated Cursor agent support to use Mike Moore's ACP Adapter . Install with: Thank you to all contributors for these improvements! Beyond what's showcased, much love and effort's been poured into polishing the experience. Interested in the nitty-gritty? Have a look through the 122 commits since the last blog post. If agent-shell or acp.el are useful to you, please consider sponsoring development. LLM tokens aren't free, and neither is the time dedicated to building this stuff ;-) Paul Nelson built agent-shell-attention.el offering a mode line attention indicator. Julian Hirn built agent-review introducing a streamlined workflow. #106 : Use replace-buffer-contents instead of erase-buffer/insert #127 : No longer possible to select the Anthropic model used by Claude Code #142 : [bug] Crash during message streaming: markdown overlay receives nil positions #143 : gemini 0.17.1 requires authMethod to authenticate (fix by Andrea ) #144 : Make collapsible indicator keymap customizable #145 : Unable to enter Plan Mode until after first message is sent #150 : Warning (undo): Buffer 'Codex Agent @ …' undo info was 25664948 bytes long #154 : Gemini CLI doesn't need authorization if already logged in #125 : Fix error when viewing proposed diffs ( Nat Page ) #129 : Support setting a preferred agent config ( Jonathan Jin ) #138 : Enable specifying MCP server configurations via custom variable ( Jonathan Jin ) #139 : Document MCP server config functionality ( Jonathan Jin ) #140 : README: Add MELPA badge + expand install instructions ( Jonathan Jin ) #141 : Add keybindings to cycle/set session mode ( Jonathan Jin ) #149 : Use fixed-pitch for ascii art logos ( Mark A. Hershberger ) #155 : Give the new custom flag to gemini for skipping the authorization ( ccQpein )

0 views
xenodium 7 months ago

Bending Emacs - Episode 8: completing-read

Nearly a couple of weeks since the last Bending Emacs episode, so here's a new episode: Bending Emacs Episode 8: completing-read In this video, we take a look at the humble but mighty completing-read function. We can use it to craft our purpose-built tools, whether in pure elisp or to interact with command-line utilities. Of interest, I also highlighted the great elisp-demos package, which extends your help buffers with sample snippets. Here are some of the snippets we played with: Pick a queen: Our own hashing function with an algo picker: A first look at integrating completing read with a CLI util: Also got creative with BluetoothConnector on macOS and . Some of my completing-read uses: Emacs: quickly killing processes . Emacs: insert and render SF symbols . macOS open with . macOS set default app . macOS share (the unhinged way). ready-player search. Hope you enjoyed the video! Liked the video? Please let me know. Got feedback? Leave me some comments . Please go like my video , share with others, and subscribe to my channel . If there's enough interest, I'll continue making more videos! Enjoying this content or my projects ? I am an indie dev. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;) Emacs: quickly killing processes . Emacs: insert and render SF symbols . macOS open with . macOS set default app . macOS share (the unhinged way). ready-player search. Hope you enjoyed the video!

10 views
xenodium 7 months ago

At one with your code

While in the mood to goof around with Emacs, CLI, and image rendering , I've revised an idea to generate some sort of art from your codebase (or any text really). That is, given an image, generate a textual representation, potentially using source code as input. With that, here's one : a utility to transform images into character art using text from your codebase. Rather than tell you more about it, best to see it in action. Just a bit of fun. That's all there is to it. While I've only run it on macOS, 's written in Go, so should be fairly portable. I'd love to know if you get it running on Linux. The code's on GitHub . If you're on macOS, I've added a Homebrew on GitHub , so you should just be able to install with: Having fun with ? Enjoying this blog or my projects ? I am an 👉 indie dev 👈. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;)

0 views
xenodium 7 months ago

Bending Emacs - Episode 7: Eshell built-in commands

With my recent rinku post and Bending Emacs episode 6 both fresh in mind, I figured I may as well make another Bending Emacs episode, so here we are: Bending Emacs Episode 7: Eshell built-in commands Check out the rinku post for a rundown of things covered in the video. Liked the video? Please let me know. Got feedback? Leave me some comments . Please go like my video , share with others, and subscribe to my channel . If there's enough interest, I'll continue making more videos! Enjoying this content or my projects ? I am an indie dev. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;)

0 views
xenodium 7 months ago

Rinku: CLI link previews

In my last Bending Emacs episode, I talked about overlays and used them to render link previews in an Emacs buffer. While the overlays merely render an image, the actual link preview image is generated by rinku , a tiny command line utility I built recently. leverages macOS APIs to do the actual heavy lifting, rendering/capturing a view off screen, and saving to disk. Similarly, it can fetch preview metadata, also saving the related thumbnail to disk. In both cases, outputs to JSON. By default, fetches metadata for you. In this instance, the image looks a little something like this: On the other hand, the flag generates a preview, very much like the ones you see in native macOS and iOS apps. Similarly, the preview renders as follows: While overlays is one way to integrate anywhere in Emacs, I had been meaning to look into what I can do for eshell in particular. Eshell is just another buffer , and while overlays could do the job, I wanted a shell-like experience. After all, I already knew we can echo images into an eshell buffer . Before getting to on , there's a related hack I'd been meaning to get to for some time… While we're all likely familiar with the cat command, I remember being a little surprised to find that offers an alternative elisp implementation. Surprised too? Go check it! Where am I going with this? Well, if eshell's command is an elisp implementation, we know its internals are up for grabs , so we can technically extend it to display images too. is just another function, so we can advice it to add image superpowers. I was pleasantly surprised at how little code was needed. It basically scans for image arguments to handle within advice and otherwise delegates to 's original implementation. And with that, we can see our freshly powered-up command in action: By now, you may wonder why the detour when the post was really about ? You see, this is Emacs, and everything compounds! We can now leverage our revamped command to give similar superpowers to , by merely adding an function. As we now know, outputs things to JSON, so we can use to parse the process output and subsequently feed the image path to . can also output link titles, so we can show that too whenever possible. With that, we can see the lot in action: While non-Emacs users are often puzzled by how frequently we bring user flows and integrations on to our beloved editor, once you learn a little elisp, you start realising how relatively easily things can integrate with one another and pretty much everything is up for grabs . Reckon and these tips will be useful to you? Enjoying this blog or my projects ? I am an 👉 indie dev 👈. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;)

0 views
xenodium 7 months ago

Bending Emacs - Episode 6: Overlays

The Bending Emacs series continues with a new a new episode. Bending Emacs Episode 6: Overlays Today we had a quick intro to overlays. Here's the snippet I used for adding snippets: Similarly, this is what we used for removing the overlay. Of the experiments, you can find: Hope you enjoyed the video! Liked the video? Please let me know. Got feedback? Leave me some comments . Please go like my video , share with others, and subscribe to my channel . If there's enough interest, I'll continue making more videos! Enjoying this content or my projects ? I am an indie dev. Help make it sustainable by ✨ sponsoring ✨ Need a blog? I can help with that . Maybe buy my iOS apps too ;) Redaction snippet at the related blog post . Dired media metadata at Ready Player's ready-player-dired.el . Link previews: While I don't have elisp to share for link previews just yet, I did release a tiny thumbnail utility named rinku ;)

0 views
xenodium 7 months ago

WhatsApp from you know where

While there are plenty of messaging alternatives out there, for better or worse, WhatsApp remains a necessity for some of us. With that in mind, I looked for ways to bring WhatsApp messaging to the comfort of my beloved text editor. As mentioned in my initial findings , WhatsApp on Emacs is totally doable with the help of wuzapi and whatsmeow , which offer a huge leg up. Today, I introduce a super early version of Wasabi , a native Emacs interface for WhatsApp messaging. I wanted installation/setup to be as simple as possible. Ideally, you install a single Emacs package and off you go. While leveraging XMPP is rather appealing in reusing existing Emacs messaging packages, I felt setting up a WhatsApp gateway or related infrastructure to be somewhat at odds with 's simple installation goal. Having said that, wuzapi / whatsmeow offer a great middle ground. You install a single binary dependency, along with , and you're ready to go. This isn't too different from the git + magit combo. As of now, 's installation/setup boils down to two steps if you're on macOS: While you may try Homebrew on Linux, you're likely to prefer your native package manager. If that fails, building wuzapi from source is also an option. While runs as a RESTful API service + webhooks , I wanted to simplify the Emacs integration by using json-rpc over standard I/O, enabling us to leverage incoming notifications in place of . I floated the idea of adding json-rpc to wuzapi to 's author Nicolas, and to my delight, he was keen on it. He's now merged my initial proof of concept , and I followed up with a handful of additional patches (all merged now): With the latest Wasabi Emacs package and wuzapi binary, you now get the initial WhatsApp experience I've been working towards. At present, you can send/receive messages to/from 1:1 or group chats. You can also download/view images as well as videos. Viewing reactions is also supported. Needless to say, you may find some initial rough edges in addition to missing features. Having said that, I'd love to hear your feedback and experience. As mentioned is currently available on GitHub . I've now put in quite a bit of effort prototyping things, upstreaming changes to , and building the first iteration of wasabi . I gotta say, it feels great to be able to quickly message and catch up with different chats from the comfort of Emacs. Having said that, it's taken a lot of work to get here and will require plenty more to get to a polished and featureful experience. Since going full-time indie dev, I have the flexibility to work on projects of choice, but that's only to an extent. If I cannot make the project sustainable, I'll eventually move to work on something else that is. If you're keen on Wasabi 's offering, please consider sponsoring the effort , and please reach out to voice your interest ( Mastodon / Twitter / Reddit / Bluesky ). Reckon a WhatsApp Emacs client would help you stay focused at work (less time on your phone)? Ask your employer to sponsor it too ;-) Add JSON-RPC 2.0 stdio mode (via -mode=stdio) for communication Expose more HTTP endpoints as JSON-RPCs . Enable setting a custom data directory via -datadir=/path/to/data . Add Homebrew recipe/installation .

0 views
xenodium 8 months ago

Want a WhatsApp Emacs client? Will you fund it?

Like it or not, WhatsApp is a necessity for some of us. I wish it weren't the case, but here we are. Given the circumstances, I wish I could use WhatsApp a little more on my terms. And by that, I mean from an Emacs client, of course. Surely I'm not the only one who feels this way, right? Right?! Fortunately, I'm not alone . With that in mind, I've been hard at work prototyping, exploring what's feasible. Spoiler alert: it's totally possible, though will require a fair bit of work. Thankfully, two wonderful projects offer a huge leg up: wuzapi and whatsmeow . wuzapi offers a REST API on top of whatsmeow , a Go library leveraging WhatsApp's multi-device web API. Last week, I prototyped sending a WhatsApp message using 's API. I got there fairly quickly by onboarding myself on to using its web interface and wiring shell-maker to send an HTTP message request via . While these two were enough for a quick demo, they won't cut it for a polished Emacs experience. While I can make REST work, I would like a simpler integration under the hood. REST is fine for outgoing messages, but then I need to integrate webhooks for incoming events. No biggie, can be done, but now I have to deal with two local services opening a couple of ports. Can we simplify a little? Yes we can. You may have seen me talk about agent-shell , my Emacs package implementing Agent Client Protocol (ACP) … Why is this relevant, you may ask? Well, after building a native Emacs implementation, I learned a bit about json-rpc over standard I/O. The simplicity here is that we can bring bidirectional communication to an Emacs-owned process. No need for multiple channels handling incoming vs outgoing messages. So where's this all going? I've been prototyping some patches on top of wuzapi to expose over standard I/O (as an alternative to ). This prototype goes far beyond my initial experiment with sending messages, and yet the Emacs integration is considerably simpler, not to mention looking very promising. Here's a demo showing incoming WhatsApp messages, received via , all through a single Emacs-owned process. Look ma, no ports! These early prototypes are encouraging, but we've only scratched the surface. Before you can send and receive messages, you need to onboard users to the WhatsApp Emacs client. That is, you need to create a user, manage/connect to a session, authorize via a QR code, and more. You'll want this flow to be realiable and that's just onboarding. From there, you'll need to manage contacts, chats, multiple message types, incoming notifications… the list goes on. That's just the Emacs side. As mentioned, I've also been patching . My plan is to upstream these changes , rather than maintaining a fork. I've prototyped quite a few things now, including the onboarding experience with QR code scanning. At this point, I feel fairly optimistic about feasibility, which is all pretty exciting! But there's a bunch of work needed. Since going full-time indie dev, I have the time available (for now), but it's hard to justify this effort without aiming for some level of sustainability. If you're interested in making this a reality, please consider sponsoring the effort , and please reach out to voice your interest ( Mastodon / Twitter / Reddit / Bluesky ). Reckon a WhatsApp Emacs client would help you stay focused at work (less time on your phone)? Ask your employer to sponsor it too ;-)

0 views