<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rodolfo Olivieri</title>
    <description>The latest articles on DEV Community by Rodolfo Olivieri (@r0x0d).</description>
    <link>https://dev.to/r0x0d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F446966%2F30f4d8fc-c9f9-4f2b-9561-880926625d59.jpeg</url>
      <title>DEV Community: Rodolfo Olivieri</title>
      <link>https://dev.to/r0x0d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/r0x0d"/>
    <language>en</language>
    <item>
      <title>Let’s talk about: Goose!</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Fri, 19 Dec 2025 17:20:00 +0000</pubDate>
      <link>https://dev.to/r0x0d/lets-talk-about-goose-46p3</link>
      <guid>https://dev.to/r0x0d/lets-talk-about-goose-46p3</guid>
      <description>&lt;p&gt;In today’s post I would love talk with you all about an exciting open source project, &lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But before we deep dive on why Goose is so amazing, let me give you some backstory context first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s start from the beginning
&lt;/h2&gt;

&lt;p&gt;Back in September, I got a task at my job in Red Hat to research about new upstream AI clients. As many of you may imagine, there are dozens and dozens of choices in the wild for you to pick your favorite, however, the intention behind this was to join forces with such community and initiate an effort to bring to Fedora and later to RHEL this upstream client.&lt;/p&gt;

&lt;p&gt;This is not an easy task, as just “yeah, this feels good!”. You need some data, research, consideration and a bunch of other things to keep in mind. So, back in September, I started researching the different variations of upstream clients, with the intention to bring one of them to Fedora, and that’s when I landed my eyes on &lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some of my team mates were already using Goose for some sporadic tasks here and there, but neither of us actually had an opinion on it other than “It looks pretty good!”.&lt;/p&gt;

&lt;p&gt;I have also to add in this context, that, even though I’m working for RHEL Lightspeed, a team primarily dealing with AI toolings, I understand that the primary thought is that I’m a die hard AI user. Well, hate to say, but… &lt;strong&gt;not that much&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have been using more AI lately for some side projects and searching, but I’m not the kinda of person that lies all my coins on this technology. I think it’s useful, for sure, if you use it with caution and for specific actions, but, I will reserve myself to talk about it in another post in the future.&lt;/p&gt;

&lt;p&gt;Phew! Much context, right? Let’s jump to the good part now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What were we looking for in the research?
&lt;/h2&gt;

&lt;p&gt;Primarily, we were looking out for an LLM client that could match the following basic criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stdio redirection&lt;/li&gt;
&lt;li&gt;File attachments&lt;/li&gt;
&lt;li&gt;Interactive mode&lt;/li&gt;
&lt;li&gt;Simple question asking&lt;/li&gt;
&lt;li&gt;History management&lt;/li&gt;
&lt;li&gt;Shell bindings&lt;/li&gt;
&lt;li&gt;MCP support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know this does not look an extensive or surprise to any one, but we figured out that for a good LLM client, this was the most basic feature support we could even ask for. In our conception, any LLM client, to be considered “usable”, would indeed check each of those criteria above.&lt;/p&gt;

&lt;p&gt;Of course, all LLM clients out there have a miriad of features available, some of them going even way beyond than we can imagine, but one requirement was the most crucial for us. The &lt;strong&gt;community&lt;/strong&gt; around the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which clients were considered in the research?
&lt;/h2&gt;

&lt;p&gt;Well, we did a long list of analysis:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project Name&lt;/th&gt;
&lt;th&gt;SCM URL&lt;/th&gt;
&lt;th&gt;License&lt;/th&gt;
&lt;th&gt;UXD Considerations&lt;/th&gt;
&lt;th&gt;Other Details&lt;/th&gt;
&lt;th&gt;Pros/Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Goose&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/block/goose/blob/main/LICENSE" rel="noopener noreferrer"&gt;Apache&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;👍 Session-based (modal) interaction method by default, with direct interaction &lt;a href="https://block.github.io/goose/docs/guides/running-tasks" rel="noopener noreferrer"&gt;available&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;👍 Built-in &lt;a href="https://block.github.io/goose/docs/guides/goose-cli-commands/#themes" rel="noopener noreferrer"&gt;themes&lt;/a&gt;, but unclear on how custom theming works&lt;br&gt;&lt;br&gt;
😐 Desktop counterpart (does this provide the same, full functionality?), &lt;a href="https://block.github.io/goose/docs/guides/goose-cli-commands/#web" rel="noopener noreferrer"&gt;web interface&lt;/a&gt; as well&lt;br&gt;&lt;br&gt;
😐 Possible opportunity for rich onboarding — existing configuration menus are good | Goose feels like the most complete project on the list. It has all the tools, functionality and features that we may require. (Written in Rust) | 👍Multi-provider support&lt;br&gt;&lt;br&gt;
👍 Custom provider&lt;br&gt;&lt;br&gt;
👍 MCP client&lt;br&gt;&lt;br&gt;
👍Extensions support (Bultin and community)&lt;br&gt;&lt;br&gt;
👎Different tech stack than the team knows |&lt;br&gt;
| Gemini CLI | &lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/google-gemini/gemini-cli/blob/main/LICENSE" rel="noopener noreferrer"&gt;Apache&lt;/a&gt; |   | Since this does not offer multi-provider support, we would need to fork the proejct and continue on our own. While this is an option, we may lack the “contribute back to the community” aspect of our work, and we might lose new features due to being harder to rebase. | 👎No multi-provider support&lt;br&gt;&lt;br&gt;
👍 MCP client&lt;br&gt;&lt;br&gt;
👍 Bulti-in useful tool calling out of the box&lt;br&gt;&lt;br&gt;
👍 Focus on security |&lt;br&gt;
| LLM | &lt;a href="https://github.com/simonw/llm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/simonw/llm/blob/main/LICENSE" rel="noopener noreferrer"&gt;Apache&lt;/a&gt; |   | This is one of the most interesting projects we have in the list, but, it does not have mcp support (as of now). It would be a great fit if we didn’t had to have mcp as required feature.  &lt;/p&gt;

&lt;p&gt;Also, it feels to me that this integrates very well with other datasette projects, so it would be a case where we would need to ship this project, plus a couple of more. | 👍Multi-provider support&lt;br&gt;&lt;br&gt;
👎Not an MCP client |&lt;br&gt;
| QWEN Code | &lt;a href="https://github.com/QwenLM/qwen-code" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/QwenLM/qwen-code/blob/main/LICENSE" rel="noopener noreferrer"&gt;Apache&lt;/a&gt; |   | It falls under the same category as any other gemini-cli based clients. It has a lot of functionality, it looks good, but in the end, there is no real multi-provider, we would need to fork and continue work separated from the community, and all else | 👍Has MCP capabilities in the client&lt;br&gt;&lt;br&gt;
👍Multi-provider support |&lt;br&gt;
| Open Code | &lt;a href="https://github.com/sst/opencode" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/sst/opencode/blob/dev/LICENSE" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; |   | We would need to fork the project as it does not accept core functionality PRs.   &lt;/p&gt;

&lt;p&gt;Nanocoder has a pretty good statement about opencode that I think it’s worth to document here: &lt;a href="https://github.com/Nano-Collective/nanocoder?tab=readme-ov-file#how-is-this-different-to-opencode" rel="noopener noreferrer"&gt;https://github.com/Nano-Collective/nanocoder?tab=readme-ov-file#how-is-this-different-to-opencode&lt;/a&gt; | 👎Does not accept Core PR |&lt;br&gt;
| Crush | &lt;a href="https://github.com/charmbracelet/crush" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/charmbracelet/crush/blob/main/LICENSE.md" rel="noopener noreferrer"&gt;FSL-1.1-MIT&lt;/a&gt; |   | Some controversy about &lt;a href="https://biggo.com/news/202507310715_Charm_Crush_AI_Coding_Agent" rel="noopener noreferrer"&gt;git history rewrite&lt;/a&gt; | 👎Not so open-source license&lt;br&gt;&lt;br&gt;
👎Does not feel like an CLI app |&lt;br&gt;
| Codex | &lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/openai/codex/blob/main/LICENSE" rel="noopener noreferrer"&gt;Apache 2.0&lt;/a&gt; |   | Same problem as the gemini-cli ones. We would need to fork in order to use it. | 👍MCP client support&lt;br&gt;&lt;br&gt;
👍MCP server support (experimental)&lt;br&gt;&lt;br&gt;
👎Multi-provider is not supported |&lt;br&gt;
| Terminal AI | &lt;a href="https://github.com/dwmkerr/terminal-ai" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/dwmkerr/terminal-ai/blob/main/LICENSE" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; |   | The project feels very configurable and the look/feel is very intuitive. However, the “assistant” mode is experimental for now, and is subject to change. | 👍It is very intuitive&lt;br&gt;&lt;br&gt;
👎MCP support is experimental (assistant mode) |&lt;br&gt;
| Nanocoder | &lt;a href="https://github.com/Nano-Collective/nanocoder" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/Nano-Collective/nanocoder/blob/main/LICENSE.md" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; |   | If the current directory you’re running nanocoder does not have a &lt;code&gt;agents.config.json&lt;/code&gt;, nanocoder won’t work. This make the user to be stuck on the same directory, or move the configuration file everywhere with them. | 👍MCP client support&lt;br&gt;&lt;br&gt;
👍Multi-provider support&lt;br&gt;&lt;br&gt;
👍Very community-based&lt;br&gt;&lt;br&gt;
👎It works on a directory based setup |&lt;br&gt;
| copilot-cli | &lt;a href="https://github.com/github/copilot-cli" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/github/copilot-cli/blob/main/LICENSE.md" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; |   | Not really open source | 👎Source code is not available yet&lt;br&gt;&lt;br&gt;
👎License does not tell much |&lt;br&gt;
| aichat | &lt;a href="https://github.com/sigoden/aichat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/sigoden/aichat/blob/main/LICENSE-APACHE" rel="noopener noreferrer"&gt;Apache 2.0&lt;/a&gt; or &lt;a href="https://github.com/sigoden/aichat/blob/main/LICENSE-MIT" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; | 👍Direct interaction method by default, with session-based (modal) available&lt;br&gt;&lt;br&gt;
👍&lt;a href="https://github.com/sigoden/aichat/wiki/Custom-Theme" rel="noopener noreferrer"&gt;Theme support&lt;/a&gt;&lt;br&gt;&lt;br&gt;
😐Current onboarding is minimal | MCP Support is not “native”. One have to use &lt;a href="https://github.com/sigoden/llm-functions/tree/main/mcp/bridge" rel="noopener noreferrer"&gt;https://github.com/sigoden/llm-functions/tree/main/mcp/bridge&lt;/a&gt; to configure MCP | 👎MCP is supported as part of external project&lt;br&gt;&lt;br&gt;
👍Multi client support&lt;br&gt;&lt;br&gt;
👍Has an RAG ingestion tool |&lt;br&gt;
| Fabric | &lt;a href="https://github.com/danielmiessler/Fabric" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/danielmiessler/Fabric/blob/main/LICENSE" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; |   | Fabric is a very different tool from the rest of the tools in this table, but I would say that if we want to push this forward, we would need to customize the way it works to “behave” like a tool calling/question asking software.   &lt;/p&gt;

&lt;p&gt;Right now, fabric is pretty good in some general knowledge fields, like the “extract wisdom from text” and a couple of other defined ones.   &lt;/p&gt;

&lt;p&gt;It also has “limited” mcp support, and by “limited”, I mean, it only works with what they have built in the codebase. We can’t really plug other servers or tool calling to it without modifying the code to support. | 👍Very customizable&lt;br&gt;&lt;br&gt;
👍Multi provider support (including ollama)&lt;br&gt;&lt;br&gt;
👎Not really a tool for asking question, but could be extended for that&lt;br&gt;&lt;br&gt;
👎Limited mcp support. |&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A small disclaimer: The UXD team got pulled in to the research in the last minute, so, that’s why we only have so few considerations on this column. We would like to have more, but due to time constraints, I asked them to limit the analysis to Goose and AIChat.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this research was proposed and directed to be released on Fedora mindset, our goal is also to bring this LLM client to RHEL, following the cascade model of packaging, meaning that, we will start in Fedora and get our way down until RHEL Extensions&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    Fedora--&amp;gt;EPEL
    EPEL--&amp;gt;RHEL-EXTENSIONS[RHEL Extensions]
    EPEL--&amp;gt;RHEL-REPOS[RHEL AppStream?]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very important to keep in mind because we want to provide to our customers something that meets the following criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be customizable&lt;/li&gt;
&lt;li&gt;Has multi provider support (ollama, gemini, vertex, anthropic, etc…)&lt;/li&gt;
&lt;li&gt;Is open source&lt;/li&gt;
&lt;li&gt;Cert based authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when we thought about the above criteria, we decided to split the research in two parts, the &lt;strong&gt;forking model&lt;/strong&gt; and the &lt;strong&gt;non-forking model&lt;/strong&gt; , what is that you may think? Let’s see each of them below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A quick side note: We were also looking to be partners in this community, meaning that, whatever we decided that is the project we wanted to bring to Fedora and way down to RHEL, we would like to give back to the community and push patches, bugfixes and etc. We don’t just want to pick something, package, and call it a day. We want to be involved with them and make sure that we are causing an positive impact in this upstream project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Forking model
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;forking model&lt;/strong&gt; is what we understand we would need to literaly fork the upstream project, to patch the source code to add the above criteria you just read. While this was a valid option, we tried to avoid this at all cost, because now, we would have to support a full product that we are not familiar with the code, and managing all the rebases on top of our patches and etc. If it was just a configuration file here and there, this forking model would be probably viable, but we are talking about mulit provider support, cert based authentication and etc. You can imagine how painful it would be to go down that route. Although this was something we wanted to avoid at all costs, we still researched and looked into it, just to have an idea of what is out there.&lt;/p&gt;

&lt;p&gt;This is a very recurring model that most folks use against&lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;gemini-cli&lt;/a&gt;, while this approach works on most of the cases, we would fall behind on innovation and giving back to the community. For instance, if gemini-cli implements a new feature that will be needed by our customers, it would become very hard for us to rebase and pick their changes, since our fork and theirs would have diverged so much at some point.&lt;/p&gt;

&lt;p&gt;The following upstream projects fit in this category of forking model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;google-gemini/gemini-cli: An open-source AI agent that brings the power of Gemini directly into your terminal.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sst/opencode" rel="noopener noreferrer"&gt;sst/opencode: AI coding agent, built for the terminal.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/QwenLM/qwen-code" rel="noopener noreferrer"&gt;QwenLM/qwen-code: Qwen Code is a coding agent that lives in the digital world.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;openai/codex: Lightweight coding agent that runs in your terminal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the above are in the “state of art” LLM clients. They are all pretty good, but, if we want to have customization, we would need to fork it 🙁.&lt;/p&gt;

&lt;h4&gt;
  
  
  Comparative analysis
&lt;/h4&gt;

&lt;p&gt;Here is a comparative analysis of gemini-cli, qwen-code, opencode, and codex (OpenAI’s Codex CLI / agent offering).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Architecture&lt;/th&gt;
&lt;th&gt;Maturity&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;gemini-cli&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Google’s open-source AI agent in the terminal, exposing Gemini capabilities (code, search, tools, etc.).&lt;/td&gt;
&lt;td&gt;Node.js / TypeScript (CLI), MCP support, integration with tools, search grounding, toolchain&lt;/td&gt;
&lt;td&gt;High profile (Google-backed), ~8k forks, many stars&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/QwenLM/qwen-code" rel="noopener noreferrer"&gt;qwen-code&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A coding agent tailored for “Qwen-Coder” models; aims to provide code understanding, editing, and automation.&lt;/td&gt;
&lt;td&gt;Primarily command-line / agent wrapper around Qwen-style models, with compatibility with OpenAI‑style APIs&lt;/td&gt;
&lt;td&gt;Moderate; niche focus (Qwen models), less broad community than Google / OpenAI tools&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sst/opencode" rel="noopener noreferrer"&gt;opencode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Provider-agnostic AI coding agent built for the terminal, with modular architecture (client/server) and emphasis on TUI / terminal user experience.&lt;/td&gt;
&lt;td&gt;Node.js / TypeScript + Go for backends, client/server model, supports multiple LLM providers.&lt;/td&gt;
&lt;td&gt;Growing; ~1.8k forks, MIT license.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;codex&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;OpenAI’s AI coding agent / CLI — part of its push to embed an “agent” into developer workflows.&lt;/td&gt;
&lt;td&gt;Cloud-based agent model + local CLI / sandbox environment, integrated with ChatGPT, GitHub, IDEs.&lt;/td&gt;
&lt;td&gt;Very high (OpenAI’s flagship), many users, high expectations&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And here is a dimension comparision about the same tools.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Scope &amp;amp; ambition&lt;/th&gt;
&lt;th&gt;Provider / model dependence&lt;/th&gt;
&lt;th&gt;User interface / UX&lt;/th&gt;
&lt;th&gt;Context &amp;amp; memory / session state&lt;/th&gt;
&lt;th&gt;Sandboxing, safety / permissions&lt;/th&gt;
&lt;th&gt;Extensibility / plugin / tools integration&lt;/th&gt;
&lt;th&gt;Complexity / maintainability&lt;/th&gt;
&lt;th&gt;Community / adoption risks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;gemini-cli&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full-featured agent: code, search grounding, tool access, “reason &amp;amp; act” loop with local/remote tools.&lt;/td&gt;
&lt;td&gt;Primarily built around Gemini / Google ecosystem (supports MCP extensibility).&lt;/td&gt;
&lt;td&gt;CLI / terminal-first; tool commands, project context, session management.&lt;/td&gt;
&lt;td&gt;“Reason &amp;amp; act” loops, checkpointing, context files (e.g. &lt;code&gt;GEMINI.md&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Built-in tools (shell, file ops, web fetch); security sensitive due to local execution.&lt;/td&gt;
&lt;td&gt;Supports MCP (Model Context Protocol) for custom integrations / tool servers.&lt;/td&gt;
&lt;td&gt;High complexity due to rich agent features and tool integration.&lt;/td&gt;
&lt;td&gt;Strong visibility from Google backing; risk of dependency on Google models, quotas, and policies.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/QwenLM/qwen-code" rel="noopener noreferrer"&gt;qwen-code&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Focused on code editing and understanding, especially for Qwen-Coder models; narrow domain.&lt;/td&gt;
&lt;td&gt;Tightly coupled to Qwen (Qwen-Coder) models; compatible with OpenAI APIs.&lt;/td&gt;
&lt;td&gt;CLI / prompt-based, command-driven sessions.&lt;/td&gt;
&lt;td&gt;Maintains history and sessions; less emphasis on complex agent behavior.&lt;/td&gt;
&lt;td&gt;Minimal scope; fewer dangerous operations and simpler sandboxing.&lt;/td&gt;
&lt;td&gt;Limited extensibility; custom commands but less infrastructure for tool chaining.&lt;/td&gt;
&lt;td&gt;Lower complexity due to narrower scope.&lt;/td&gt;
&lt;td&gt;Dependency on Qwen models and smaller user base increases risk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sst/opencode" rel="noopener noreferrer"&gt;opencode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Balanced: broad agent features with modular, provider-agnostic design.&lt;/td&gt;
&lt;td&gt;Strongly provider-agnostic: supports OpenAI, Google, local models, etc.&lt;/td&gt;
&lt;td&gt;TUI / terminal-first with client/server architecture and flexible frontends.&lt;/td&gt;
&lt;td&gt;Modular architecture enabling persistent, server-side context across sessions.&lt;/td&gt;
&lt;td&gt;Sandboxing is critical due to provider independence and modularity.&lt;/td&gt;
&lt;td&gt;Designed for extensibility via client-server architecture and custom tool backends.&lt;/td&gt;
&lt;td&gt;Moderate complexity balancing flexibility and features.&lt;/td&gt;
&lt;td&gt;Risk of fragmentation across providers and difficulty maintaining parity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;codex&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Ambitious: embeds AI coding across terminal, IDEs, GitHub, and cloud workflows.&lt;/td&gt;
&lt;td&gt;OpenAI-centric; leverages OpenAI infrastructure and models (CLI runs locally with sandboxing).&lt;/td&gt;
&lt;td&gt;CLI plus deep integration with IDEs, GitHub, and ChatGPT web UI.&lt;/td&gt;
&lt;td&gt;Strong context handling with isolated sandboxes and project metadata (e.g. &lt;code&gt;AGENTS.md&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Strong sandboxing with approval models for file writes and shell commands.&lt;/td&gt;
&lt;td&gt;Deep integrations (GitHub, IDEs, agent pipelines) with task-level tool orchestration.&lt;/td&gt;
&lt;td&gt;Very high complexity from extensive integrations and safety mechanisms.&lt;/td&gt;
&lt;td&gt;Risk of lock-in, cost, API constraints, and agent-task reliability.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Non-forking model
&lt;/h3&gt;

&lt;p&gt;The following upstream projects fit in the category of non-forking model, i.e, we would be able to just contribute back to their community, pull the changes, adapt and stay in parity with upstream and downstream. Of course, not all projects listed here are super flexible, so we would need to do downstream patching to accomodate some of our needs, but it still fit the category of “let’s not fork and diverge from the upstream community” model.&lt;/p&gt;

&lt;p&gt;With that in mind, here are the considered non-forking projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;block/goose: an open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/charmbracelet/crush" rel="noopener noreferrer"&gt;charmbracelet/crush: The glamourous AI coding agent for your favourite terminal 💘&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sigoden/aichat" rel="noopener noreferrer"&gt;sigoden/aichat: All-in-one LLM CLI tool featuring Shell Assistant, Chat-REPL, RAG, AI Tools &amp;amp; Agents, with access to OpenAI, Claude, Gemini, Ollama, Groq, and more.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Comparative analysis
&lt;/h4&gt;

&lt;p&gt;Here is a comparative analysis of goose, crush, and aichat. I break down their key differences, strengths, and weaknesses (from the perspective of architecture, features, maturity, extensibility, etc.).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Description / goal&lt;/th&gt;
&lt;th&gt;Primary language / tech stack&lt;/th&gt;
&lt;th&gt;Maturity / popularity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;goose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;An “on-machine AI agent” that goes beyond code suggestions: installs, executes, tests, and debugs tasks; integrates with any LLM.&lt;/td&gt;
&lt;td&gt;Rust + TypeScript (with some Go and Python components)&lt;/td&gt;
&lt;td&gt;High: ~20k stars, ~1.8k forks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/charmbracelet/crush" rel="noopener noreferrer"&gt;crush&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A “glamorous AI coding agent for your favorite terminal” — CLI integrating LLM APIs, sessions, context, LSPs, and extensions.&lt;/td&gt;
&lt;td&gt;Go (100%)&lt;/td&gt;
&lt;td&gt;Strong: ~13.4k stars, active development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sigoden/aichat" rel="noopener noreferrer"&gt;aichat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;All-in-one LLM CLI: shell assistant, chat REPL, RAG, AI tools, and agents; multi-provider support.&lt;/td&gt;
&lt;td&gt;Mixed stack (likely Python plus shell scripts)&lt;/td&gt;
&lt;td&gt;Moderate: ~8.2k stars, fewer recent open issues&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And here is a dimension comparision about the same tools.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Scope / ambition&lt;/th&gt;
&lt;th&gt;Extensibility / plugin / model support&lt;/th&gt;
&lt;th&gt;User interface / UX&lt;/th&gt;
&lt;th&gt;Context handling / sessions&lt;/th&gt;
&lt;th&gt;Complexity vs simplicity&lt;/th&gt;
&lt;th&gt;Community / stability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;goose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Very ambitious: full agent capabilities (run code, orchestrate workflows, interact, test) beyond chat or suggestions.&lt;/td&gt;
&lt;td&gt;Multi-model, modular architecture; supports any LLM and “recipes” (developer-contributed agents).&lt;/td&gt;
&lt;td&gt;Desktop GUI plus CLI components; dedicated UI module.&lt;/td&gt;
&lt;td&gt;Strong agent-oriented context and orchestration support.&lt;/td&gt;
&lt;td&gt;Very high complexity with many moving parts due to agent orchestration.&lt;/td&gt;
&lt;td&gt;Large community, many contributors, frequent releases.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/charmbracelet/crush" rel="noopener noreferrer"&gt;crush&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Developer / terminal-first focus: sessions, LSP integration, tool access, context switching.&lt;/td&gt;
&lt;td&gt;Extensible via MCP servers (HTTP, stdio, SSE); model switching mid-session; LSP and plugin-like capabilities.&lt;/td&gt;
&lt;td&gt;Pure terminal / CLI experience targeting developers.&lt;/td&gt;
&lt;td&gt;Project-based sessions, context switching, LSP-enhanced context.&lt;/td&gt;
&lt;td&gt;More focused design with fewer moving parts; easier to reason about.&lt;/td&gt;
&lt;td&gt;Strong and mature user base with many commits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sigoden/aichat" rel="noopener noreferrer"&gt;aichat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Broad feature set: chat REPL, agents, RAG, and wide multi-provider support.&lt;/td&gt;
&lt;td&gt;Supports many backends (OpenAI, Claude, Gemini, Ollama, Groq, etc.).&lt;/td&gt;
&lt;td&gt;CLI / REPL-style interface, possibly with shell integration.&lt;/td&gt;
&lt;td&gt;Conversation history, tools, and some session management (less mature).&lt;/td&gt;
&lt;td&gt;Moderate complexity: many features, less deep orchestration than goose.&lt;/td&gt;
&lt;td&gt;Growing community, but smaller contributor base compared to others.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Cool! But, why Goose then?
&lt;/h2&gt;

&lt;p&gt;From all the reading above, you can see that a long list of LLM clients got considered to be our chosen one. We always try to go and pick the non-forking model, because that’s what give flexibility and stability for us, allowing customers and all users to play with such tools they way the like (running locally, changing providers, mcp, etc..).&lt;/p&gt;

&lt;p&gt;We tried all of the clients in the above lists, and we had a deep consideration for each of them, wether or not it would be a good fit for such downstream repositories, user experience and maintainence as well.&lt;/p&gt;

&lt;p&gt;Goose really made us be impressed with the power, simplicity and flexibility the tool has. It has a fast growing environment, with an &lt;strong&gt;amazing&lt;/strong&gt; community behind it, and we had a lot of folks trying it out internally at that point too, so we felt pretty confident that Goose would meet our expectations, and, would meet users expectations as well.&lt;/p&gt;

&lt;p&gt;Also, I just want to expand a bit more on the community side of Goose, the folks there just embraced my questions and were eager to help no matter what. From dumb questions (that I always ask, I know, sorry.), to more advance questions and etc. Folks there were happy to answer and guide us if necessary. That was one of the huge points that made us consider Goose as our favorite LLM client in our day to day work.&lt;/p&gt;

&lt;p&gt;That collaboration was not only virtual, some folks from my team went to a F2F for Goose and met some of the engineers there, I heard that their experience was the same as mine virtually 😄. Always amazing to work with such upstream groups.&lt;/p&gt;

&lt;p&gt;And to finalize, not sure if you all had the change to read this news, but, the Linux Foundation announced on December 9th, 2025 the formation of Agentic AI Foundation, and guess who is involved in that? That’s right, 🪿!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2y5nkc1ftkmeals8xg76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2y5nkc1ftkmeals8xg76.png" alt="Linux Foundation Announces the Formation of the Agentic AI Foundation (AAIF), Anchored by New Project Contributions Including Model Context Protocol (MCP), goose and AGENTS.md" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; linuxfoundation.org &lt;/p&gt;

&lt;h3&gt;
  
  
  Linux Foundation Announces the Formation of the Agentic AI Foundation (AAIF), Anchored by New Project Contributions Including Model Context Protocol (MCP), goose and AGENTS.md
&lt;/h3&gt;

&lt;p&gt;Linux Foundation Announces the Formation of the Agentic AI Foundation&lt;/p&gt;



&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;I would like to give a shout out to my entire team at Red Hat and for all the folks that helped in this research. The list is long and I would be unfair if I tried to list all of them here, but you know who you are, so please, accept my deep gratitude for the hard work and patience at answering my questions 💖.&lt;/p&gt;

&lt;p&gt;Also, a huge shout out to the Goose community for their amazing work and quickiness in replying to all questions and being eager to help who is new in there! 💖💖&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.redhat.com/en/blog/unleashing-innovation-rhel-extensions-repository" rel="noopener noreferrer"&gt;Red Hat Enterprise Linux Extensions&lt;/a&gt; ↩︎
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>research</category>
      <category>goose</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Packaging for Fedora: Python projects</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Thu, 18 Dec 2025 12:49:00 +0000</pubDate>
      <link>https://dev.to/r0x0d/packaging-for-fedora-python-projects-4md1</link>
      <guid>https://dev.to/r0x0d/packaging-for-fedora-python-projects-4md1</guid>
      <description>&lt;p&gt;In this post, I want to share with you what I know about packaging &lt;code&gt;Python&lt;/code&gt;projects for Fedora. I must start this text admitting that I don’t know a whole lot (&lt;em&gt;yet&lt;/em&gt;), but I figured that it would be very valuable, not for myself, but also for others, if I shared my learning process and the roadblocks I have been facing recently. More like documenting what is happening and how I solved such problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I get started?
&lt;/h2&gt;

&lt;p&gt;Packaging can be seem as a challenging task, no matter your level of experience, but, let’s try to understand how it works from the beginning.&lt;/p&gt;

&lt;p&gt;Before jumping straight to writing specfiles, patches and all the fun stuff, let’s first understand a couple of resources that can make your life easier in this process. Fedora has a great online documentation available to everyone that can guide you in this process, going from what you need to know about packaging in general, and down to the more specific topics in each language, for instance, take a look at the below docs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.fedoraproject.org/en-US/packaging-guidelines/" rel="noopener noreferrer"&gt;Fedora Packaging Guidelines&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Fedora Packaging Guidelines&lt;/code&gt; Has a complete set of information about packaging and what you should and should not do when packaging any software.&lt;/p&gt;

&lt;p&gt;That piece of documentation goes in detail about all the pieces of packaging, from licensing to architecture support, build scripts and much, much more! It’s always good to read or bookmark that URL for further reference when needed.&lt;/p&gt;

&lt;p&gt;Now, if you take a look at the below one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/" rel="noopener noreferrer"&gt;Python Packaging Guidelines&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Python Packaging Guidelines&lt;/code&gt;, much like the &lt;code&gt;Fedora Packaging Guidelines&lt;/code&gt;will give you a complete tour on the specifics about packaging &lt;code&gt;Python&lt;/code&gt;applications, whici, is what we are intetrested in here.&lt;/p&gt;

&lt;p&gt;In that one, you will learn about the structurue that is expected of your specfile, where to pull the source tarball, and many more information.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep in mind that, while it is always &lt;em&gt;recommended&lt;/em&gt; that you read those documentation above, you can always bookmark and check them before submiting anything for review. Depending on your style of work, it may be more interesting to read such docs on the fly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowing that such materials exists will be extremely helpful to us when we proceed to submit our newly built package for review in&lt;a href="https://bugzila.redhat.com" rel="noopener noreferrer"&gt;bugzilla&lt;/a&gt;, but don’t worry, we will cover this in another post, as there is quite a lot of information for us to go through. This post is more intended to be a hands-on, practical, python packaging and not really about package reviews or procedures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding your upstream community/project
&lt;/h3&gt;

&lt;p&gt;Finding a community that you like is one of the most crucial steps before you start hacking your packages. This step is important because if you find yourself trying to package something that is not even related to your day-to-day work or of your interest, you may find it boring when errors and workarounds appears. My advice to you, my fellow beginner packager, is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick something that you use on your workflow and that does not exist in Fedora currently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m not saying that packaging just for the fun of it is wrong, but, when you give a purpose to your work, then, it does not feel boring or a “hard requirement”. Our goal here is that you can learn how packaging is done, and also, have fun 😃!&lt;/p&gt;

&lt;p&gt;Once you know what you want to introduce to Fedora, either because you need it, or you have a higher purpose (like contributing with a given community), then you are all set to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a specfile?
&lt;/h2&gt;

&lt;p&gt;Working with specfiles can be challenging with many terms to identify and understand, but once you get the hang of it, the packaging part starts to be fun! I could go over here in details of each field, component and techniques for writing good specfiles, but, that would make this post be three times bigger than it already is. Instead, since this topic is huge and contain a lot of information, I will leave here the official documentation of the RPM Packaging Guide linked directly to the explanation of what is a specfiles, and instead of deep diving on it myself, let’s try to get to other topics that are not covered in the official docs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rpm-packaging-guide.github.io/#what-is-a-spec-file" rel="noopener noreferrer"&gt;RPM Packaging Guide&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pulling sources from pypi or GitHub/Gitlab/etc?
&lt;/h3&gt;

&lt;p&gt;When working with packaging, we need to identify from where we want to pull the sources for our builds. The Python Packaging Guidelines states that you _MAY_pull the sources from PyPi for better convenience, however, that scenario may be complicated some times.&lt;/p&gt;

&lt;p&gt;Let’s see below when to pull from PyPi or when to pull from another SCM.&lt;/p&gt;

&lt;h4&gt;
  
  
  When to pull from PyPI?
&lt;/h4&gt;

&lt;p&gt;Usually, I like to start my packaging process by pulling the sources from PyPi and taking a good look at what is being present in the source tarball. You are not required to do this, but I prefer starting my workflow like that.&lt;/p&gt;

&lt;p&gt;For instance, let’s take a look at this section of one of my specfile:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/r0x0d/python-sse-starlette/blob/c7a72897695d492b1c4cdda64b30049b3ddbde00/python-sse-starlette.spec#L1-L8" rel="noopener noreferrer"&gt;python-sse-starlette.spec (L1-L8)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: python-sse-starlette
Version: 3.0.3
Release: %autorelease
Summary: SSE plugin for Starlette

License: BSD-3-Clause
URL: https://github.com/sysid/sse-starlette
Source0: %{pypi_source sse_starlette}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see that I’m using this macro called &lt;code&gt;%pypi_source&lt;/code&gt;, right? This is a&lt;a href="https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/#_convenience_macros" rel="noopener noreferrer"&gt;Convenience Macro&lt;/a&gt;that we can use to generate the full PyPi URL. With that, you only need to pass the package name in PyPi and optionally, the version, as it pick the version from the &lt;code&gt;Version&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;The good part is that it is convenient to pull the sources from PyPi directly with this macro, but, sometimes the upstream maintainer may not include required files/folders that we need to use in downstream packaging. For instance, the upstream project may be using a new shiny tooling/builder that generate metadata differently what is currently expected (like poetry, uv, setuptools, etc…). This can cause problem during the package build as you may be missing the license information, tests folders (which is good to execute during the specfile builds) and more.&lt;/p&gt;

&lt;p&gt;When that happens, we may need to switch to pull sources from other SCM variants, like GitHub. From there, it’s more likely to get a full overview of the project setup, and then you can manually pick what you want from the tarball.&lt;/p&gt;

&lt;h4&gt;
  
  
  When to pull from GitHub/Gitlab/etc?
&lt;/h4&gt;

&lt;p&gt;As stated before, sometimes the PyPi sources may not contain all the required metadata, tests, or essential files for your package building, when such cases happen, we need to switch our plan and start pulling from the upstream SCM, for instance, take a look at this other package:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/done-packaging/python-openapi-pydantic/blob/main/python-openapi-pydantic.spec#L1-L8" rel="noopener noreferrer"&gt;python-openapi-pydantic.spec (L1-L8)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: python-openapi-pydantic
Version: 0.5.1
Release: %autorelease
Summary: Pydantic OpenAPI schema implementation

License: MIT
URL: https://github.com/mike-oakley/openapi-pydantic
Source: %{url}/archive/v%{version}/openapi-pydantic-%{version}.tar.gz

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This project was exceptional one, as the PyPI sources didn’t contain the tests folder for me to check under the &lt;code&gt;%check&lt;/code&gt; directive. For that, I had to change my approach to pull from GitHub (were the project is hosted), as in that one, I would have the same copy of the project, but with the tests folder that I needed.&lt;/p&gt;

&lt;p&gt;You can go with the upstream SCM directly if you wish, that’s not a big deal at all. This is more a question of preference and from where you want to pull your trusted tarball.&lt;/p&gt;

&lt;h3&gt;
  
  
  Patching in downstream
&lt;/h3&gt;

&lt;p&gt;Patching is one of the most needed useful techniques that we can bring to the packaging world! This help us modify the behavor of the project before the builds. Why this is necessary, you may think? Well, let’s think that your project depends on &lt;code&gt;libXX == 1.0.0&lt;/code&gt;, but Fedora only has &lt;code&gt;libXX == 0.9.0&lt;/code&gt;packaged in the repositories, what should you do now?&lt;/p&gt;

&lt;p&gt;Well, it’s always possible to ask for the maintainer of the &lt;code&gt;libXX&lt;/code&gt; package to update to the newest version, but, that may not be possible all the time. Instead, it’s when patching comes to the rescue!&lt;/p&gt;

&lt;p&gt;You could use different strategies and methods you like, for instance, &lt;code&gt;sed&lt;/code&gt; is a pretty good viable option for patching if you’re familiar with it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Patching toml files
&lt;/h4&gt;

&lt;p&gt;I like to use a tool called &lt;a href="https://git.sr.ht/~gotmax23/tomcli" rel="noopener noreferrer"&gt;tomcli&lt;/a&gt;, which is a bit confusing on the first try, I must admit, but it makes the patching much easier once you get the hang of it.&lt;/p&gt;

&lt;p&gt;Take a look at this example where I wanted to relax one of the dependencies for &lt;code&gt;python-sse-starlette&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/r0x0d/python-sse-starlette/blob/main/python-sse-starlette.spec#L37-L38" rel="noopener noreferrer"&gt;python-sse-starlette.spec (L37-L38)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Relax daphne dependency
tomcli set pyproject.toml arrays replace project.optional-dependencies.daphne "daphne&amp;gt;=([0-9]+\.[0-9]+\.[0-9]+)" "daphne&amp;gt;=4.1,&amp;lt;4.3"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another useful way of patching toml files with &lt;code&gt;tomcli&lt;/code&gt; is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Patch pyproject.toml to use setuptools instead of uv_build (not available in Fedora)
tomcli set pyproject.toml lists str "build-system.requires" "setuptools&amp;gt;=61" "wheel"
tomcli set pyproject.toml str "build-system.build-backend" "setuptools.build_meta"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disclaimer: Using cookiecutter-fp template
&lt;/h3&gt;

&lt;p&gt;Alternatively, you can get started using my cookiecutter packaging template. This template is written in a way to help bootstrap some of your manual work with copr/builds/logs by providing a set of crafted make targets for convenience. You can read more about it in my blog post below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://r0x0d.com/posts/packaging-for-fedora-general-purpose-cookiecutter-template" rel="noopener noreferrer"&gt;Packaging for Fedora: General purpose cookiecutter template&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to learn more? Joing the Matrix channel!
&lt;/h2&gt;

&lt;p&gt;Did you find this interesting? Please, feel free to join the Fedora Matrix channel to learn more and get started. The community is amazing and I’m pretty sure that you will find what you need there.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://matrix.to/#/#python:fedoraproject.org" rel="noopener noreferrer"&gt;Fedora Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://matrix.to/#/#ai-ml:fedoraproject.org" rel="noopener noreferrer"&gt;Fedora AI/ML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to get in touch with me, just send a message to &lt;code&gt;@r0x0d:fedora.im&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rpm-packaging-guide.github.io/" rel="noopener noreferrer"&gt;RPM Packaging Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fedora</category>
      <category>packaging</category>
      <category>python</category>
    </item>
    <item>
      <title>Packaging for Fedora: General purpose cookiecutter template</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Fri, 12 Dec 2025 17:38:00 +0000</pubDate>
      <link>https://dev.to/r0x0d/packaging-for-fedora-general-purpose-cookiecutter-template-4kgi</link>
      <guid>https://dev.to/r0x0d/packaging-for-fedora-general-purpose-cookiecutter-template-4kgi</guid>
      <description>&lt;p&gt;To make the effort on packaging easier, I developed a custom &lt;a href="https://github.com/cookiecutter/cookiecutter?tab=readme-ov-file" rel="noopener noreferrer"&gt;cookiecutter&lt;/a&gt; template to help bootstraping this work.&lt;/p&gt;

&lt;p&gt;The template currently comes with pre-defined settings for packaging &lt;code&gt;Rust&lt;/code&gt; and&lt;code&gt;Python&lt;/code&gt; applications, which is my main target as of now. The details on how to package such proejcts will be detailed in another blog post, not here. In here, we will try to focus on how this cookiecutter template works and how you can use it in your workflow (if you like it.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;In order to use this template, you will need to have &lt;code&gt;cookiecutter&lt;/code&gt; and&lt;code&gt;jinja2_time&lt;/code&gt; installed (preferably in a virtualenv), so let’s begin with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install cookiecutter jinja2_time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;jinja2_time&lt;/code&gt; is used here as a convenience to update the current year in the &lt;code&gt;LICENSE&lt;/code&gt; file once it is generated.&lt;/p&gt;

&lt;p&gt;Once both are installed, we can proceed with calling cookiecutter to generate our new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This will pull the template with ssh
cookiecutter git@github.com:r0x0d/cookiecutter-fp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be prompted to answer a few bootstraping questions for the template. Don’t worry, this won’t execute any hidden hooks on your system. This is mainly to track the correct names of the upstream project, GitHub/Gitlab/Codeberg URLs and etc. You should have something looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  [1/6] project_slug (rust-my-awesome): my-super-project
  [2/6] pkg_name (my-awesome): super-project
  [3/6] upstream_repo (https://github.com/my/awesome-repo): https://github.com/my-username/super-project
  [4/6] Select tool_2_rpm
    1 - rust2rpm
    2 - pyp2spec
    Choose from [1/2] (1): 2
  [5/6] year (2025):
  [6/6] copr_username (&amp;lt;your username&amp;gt;): my-username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break down what each prompt above means for you:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;project_slug&lt;/td&gt;
&lt;td&gt;Used to match the downstream package name (e.g; &lt;code&gt;python-flask&lt;/code&gt;, &lt;code&gt;rust-serde&lt;/code&gt;, etc…)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pkg_name&lt;/td&gt;
&lt;td&gt;The name of the package you are trying to get to fedora (e.g; &lt;code&gt;flask&lt;/code&gt;, &lt;code&gt;serde&lt;/code&gt;, etc…)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;upstream_repo&lt;/td&gt;
&lt;td&gt;URL to the upstream repository for the package (e.g; &lt;code&gt;Github&lt;/code&gt;, &lt;code&gt;Gitlab&lt;/code&gt;, etc…)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tool_2_rpm&lt;/td&gt;
&lt;td&gt;Choose from &lt;code&gt;rust2rpm&lt;/code&gt; or &lt;code&gt;pyp2spec&lt;/code&gt; (more details on that below)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;year&lt;/td&gt;
&lt;td&gt;The year used in the &lt;code&gt;LICENSE&lt;/code&gt; file for your mid-stream repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;copr_usernam&lt;/td&gt;
&lt;td&gt;The &lt;a href="https://copr.fedorainfracloud.org" rel="noopener noreferrer"&gt;COPR&lt;/a&gt; username to manage the builds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once all of the prompts are answered, you will se a new folder in the directory you are that matches the &lt;code&gt;project_slug&lt;/code&gt; name you entered before.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is not required to set the &lt;code&gt;project_slug&lt;/code&gt; to be the same downstream package name, but, this help in organization and knowing that you will have the same data when you go to the package review process, avoiding confusion and unnecessary drawback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What to do with a new project?
&lt;/h2&gt;

&lt;p&gt;Once you have created a new project with the above &lt;code&gt;cookiecutter&lt;/code&gt; command, you are now ready to start modifying, building and eventually, submit it to package review. This part is one of the most important in the process of packaging, as it is here where you will do your experimentation and get the builds right, so don’t be afraid of messing stuff up 😊.&lt;/p&gt;

&lt;p&gt;This template comes with a set of &lt;code&gt;make&lt;/code&gt; targets that will help you quickly experiment with the builds and iterate over the changes. We will talk about them in each of the sub-sections bellow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new copr repository
&lt;/h3&gt;

&lt;p&gt;First things first, we need to create a new copr repository for you to track your builds. In Fedora, you can use &lt;code&gt;mockbuilds&lt;/code&gt; that will execute locally, but they will, at some point, get your directories dirty. I’m not sure about you, but I don’t like having dangling files all around my computer that I won’t remember why they are there 6 months or 1 year later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up a copr account
&lt;/h4&gt;

&lt;p&gt;You will need to create a new &lt;a href="https://accounts.fedoraproject.org/" rel="noopener noreferrer"&gt;Fedora account (FAS)&lt;/a&gt; first before working with copr, this will be necessary for further steps as well when we reach the package review process.&lt;/p&gt;

&lt;p&gt;Once you have your new FAS account, go back to&lt;a href="https://copr.fedorainfracloud.org/coprs/" rel="noopener noreferrer"&gt;copr&lt;/a&gt; and click on the &lt;code&gt;OIDC login&lt;/code&gt;to use your FAS credentials.&lt;/p&gt;

&lt;p&gt;With those steps done, go ahed to &lt;a href="https://copr.fedorainfracloud.org/api/" rel="noopener noreferrer"&gt;copr api&lt;/a&gt; page to grab your credentials. This is very important as we can’t create a repository for you in the next steps if you don’t get your API keys set up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t worry, that page tells you exactly where to place the contents you grabbed from the site.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Installing necessary rpms
&lt;/h4&gt;

&lt;p&gt;There is a set of RPMs that are necessary for you to install on your system in order to proceed, we can start with the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fedpkg&lt;/li&gt;
&lt;li&gt;copr
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf instal fedpkg copr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you don’t like installing things directly to your system, or if you are like me who is using Fedora Silverblue, then I got you covered… I have created a toolbox environment for Fedora packaging that comes with most of what you will need configured.&lt;/p&gt;

&lt;p&gt;To use my fedora-packaging contianer, you could do it with &lt;code&gt;toolbox&lt;/code&gt;/&lt;code&gt;distrobox&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;toolbox create --image quay.io/toolbox-dev/environment/fedora-packaging fedora-packaging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once everything is ready and set up, we can now proceed to create the repository with the &lt;code&gt;make&lt;/code&gt; target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make create-copr-repository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generating the specfile
&lt;/h3&gt;

&lt;p&gt;In order to generate the specfiles for the given project you want to package, it is highly recommended that either &lt;code&gt;rust2rpm&lt;/code&gt; or &lt;code&gt;pyp2spec&lt;/code&gt; is used, depending on the type of project you are trying to package.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rust2rpm (required if you’re packaging rust applications)&lt;/li&gt;
&lt;li&gt;pyp2spec (required if you’re packaging python applications)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf install rust2rpm pyp2spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the tool is installed, it is time to run the below make target to generate the specfile automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some manual changes will be necessary in case you are packaging &lt;code&gt;python&lt;/code&gt;applications due to the limitations of the &lt;code&gt;pyp2spec&lt;/code&gt; tooling. For &lt;code&gt;rust&lt;/code&gt; RPMs, it should be straightforward.&lt;/p&gt;

&lt;p&gt;Depending on the project you will package, some patching will be required in order to have a successful build. The specifics on how to patch will be covered on a different post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the project
&lt;/h3&gt;

&lt;p&gt;Now that we already have the specfile in place, it is time to trigger our first build! First, we will need to download the sources from the specfile, given that we don’t have a dist-git set up yet, we will reloy on &lt;code&gt;srpm&lt;/code&gt; generation, which requires that you have the tarball sources present in the same directory as of your specfile. Luckily, the template also comes with two useful targets that can be used to bootstrap and automate this process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Get the sources from the specfile
make sources

# Submit a new build to copr
make build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the &lt;code&gt;build&lt;/code&gt; is triggered, and if everything is working correctly, you will see that your &lt;code&gt;srpm&lt;/code&gt; will be uploaded to copr and a build will start to happen!&lt;/p&gt;

&lt;h4&gt;
  
  
  Watching the logs with fuzzytail
&lt;/h4&gt;

&lt;p&gt;The cookiecutter template comes by default with a target for watching the logs of your copr build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To know more about &lt;code&gt;fuzzytail&lt;/code&gt;, check out my other blog post &lt;a href="https://r0x0d.com/posts/packaging-for-fedora-fuzzytail-watching-logs-on-terminal/" rel="noopener noreferrer"&gt;Packaging for Fedora: fuzzytail! Watching logs on your terminal&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking the repository in github (optional)
&lt;/h3&gt;

&lt;p&gt;Lastly, as an optional task, you can create a github repository to track your work (either because you want to version it, or you are working on mulptiple machines). This step is not required at all, so it may be safely ignored if you have enough experience on this process.&lt;/p&gt;

&lt;p&gt;There is a set of RPMs that are necessary for you to install on your system in order to proceed, we can start with the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gh-cli
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make crate-gh-repository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;If you would like to contribute to the cookiecutter template, please, feel free to do so in the &lt;a href="https://github.com/r0x0d/cookiecutter-fp" rel="noopener noreferrer"&gt;Github&lt;/a&gt; repository&lt;/p&gt;

</description>
      <category>packaging</category>
      <category>template</category>
      <category>cookiecutter</category>
      <category>fedora</category>
    </item>
    <item>
      <title>Packaging for Fedora: fuzzytail! Watching logs on your terminal</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Wed, 10 Dec 2025 20:22:00 +0000</pubDate>
      <link>https://dev.to/r0x0d/packaging-for-fedora-fuzzytail-watching-logs-on-your-terminal-163i</link>
      <guid>https://dev.to/r0x0d/packaging-for-fedora-fuzzytail-watching-logs-on-your-terminal-163i</guid>
      <description>&lt;p&gt;If you are an experienced fedora packager or even if you are starting out, you probably have come across &lt;a href="https://copr.fedorainfracloud.org" rel="noopener noreferrer"&gt;COPR&lt;/a&gt; and its tooling, right? Well, if you have, then you know how painful it is, for each build, to come back to the UI and keep refreshing manually to &lt;em&gt;watch&lt;/em&gt; your logs in “real time”.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://github.com/r0x0d/fuzzytail" rel="noopener noreferrer"&gt;fuzzytail&lt;/a&gt; comes to the party!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is fuzzytail?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;fuzytail&lt;/strong&gt; is an small application that let you interact with your builds in&lt;a href="https://copr.fedorainfracloud.org/" rel="noopener noreferrer"&gt;COPR&lt;/a&gt;, either by looking at the status of the build or by watching the logs live.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By no means fuzzytail replaces the&lt;a href="https://github.com/fedora-copr/copr" rel="noopener noreferrer"&gt;copr-cli&lt;/a&gt;, it is actually meant to be an extension to aid packagers to visualize their build logs in the terminal instead of using the UI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the time you see yourself packaging 5+ upstream projects to Fedora, you probably will end up going crazy trying to watch the builds and figuring out what exactly happened to your failed ones, this is where &lt;strong&gt;fuzzytail&lt;/strong&gt; enters to shiny!&lt;/p&gt;

&lt;p&gt;As a developer, it is much, much, &lt;strong&gt;much&lt;/strong&gt; more comfortable for me to look at stuff in my own terminal instead of my web browser, it makers me feel like a_hacker_, you know? And &lt;strong&gt;fuzzytail&lt;/strong&gt; is helping me keeping this feeling while I prepare builds for various packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fantastic! How do I get fuzzytail?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;fuzzytail&lt;/strong&gt; is available from &lt;a href="https://pypi.org/project/fuzzytail" rel="noopener noreferrer"&gt;pypi&lt;/a&gt;, therefore, a simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fuzzytail

# or

pipx install fuzzytail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will get you to the latest version.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I use fuzzytail?
&lt;/h2&gt;

&lt;p&gt;To get started with &lt;strong&gt;fuzzytail&lt;/strong&gt; is actually pretty simple. All you have to do is run the following command on your terminal after you get it installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fuzzytail &amp;lt;owner&amp;gt;/&amp;lt;project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, &lt;strong&gt;fuzzytail&lt;/strong&gt; will start in the &lt;code&gt;watch&lt;/code&gt; mode, meaning that, once you specify the &lt;code&gt;owner&lt;/code&gt; and &lt;code&gt;project&lt;/code&gt; that you are interested in, it will stream the logs directly to your terminal, that’s the most basic execution mode for the program.&lt;/p&gt;

&lt;p&gt;Don’t believe me? Here, take a look!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fr0x0d%2Fstatic%2Frefs%2Fheads%2Fmain%2Fassets%2Fposts%2Ffuzzytail-in-action.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fr0x0d%2Fstatic%2Frefs%2Fheads%2Fmain%2Fassets%2Fposts%2Ffuzzytail-in-action.gif" alt="fuzzytail in action" width="480" height="202"&gt;&lt;/a&gt;&lt;em&gt;A gif showing fuzzytail streaming the logs in a split terminal while the build happens&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In case you don’t want to stream the logs directly, it is also possible to view the logs after they happen with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fuzzytail logs &amp;lt;owner&amp;gt;/&amp;lt;project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering for chroot logs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;fuzzytail&lt;/strong&gt; has the ability to allow you to select which &lt;code&gt;chroot&lt;/code&gt; logs you want to see during the build. Maybe you only care about &lt;code&gt;fedora-43-x86_64&lt;/code&gt;, and not about rawhide or fedora 42 and etc. With &lt;strong&gt;fuzzytail&lt;/strong&gt; , this is easily selected with the &lt;code&gt;--chroot&lt;/code&gt; parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fuzzytail &amp;lt;owner&amp;gt;/&amp;lt;project&amp;gt; --chroot fedora-43-x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering for build logs only
&lt;/h3&gt;

&lt;p&gt;In some cases, you might not want to see all copr build logs, like &lt;code&gt;srpm&lt;/code&gt;,&lt;code&gt;import&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;, etc. Maybe you just care about the actual &lt;code&gt;rpm&lt;/code&gt; log, because that’s what is important for you right now, and thinking in that, &lt;strong&gt;fuzzytail&lt;/strong&gt; also has a mode to allow you to specify which logs you want to capture and display in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Will only show the rpm build logs
fuzzytail &amp;lt;owner&amp;gt;/&amp;lt;project&amp;gt; --rpm-only

# Will only show the srpm build logs
fuzzytail &amp;lt;owner&amp;gt;/&amp;lt;project&amp;gt; --srpm-only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Checking build status
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;fuzzytail&lt;/strong&gt; also has a nice command for you to check the status of the builds (without getting their logs). This command is useful for quickly finding out if your long-running build has failed or succeeded!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fuzzytail builds r0x0d/python-openapi-pydantic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will generate the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ID ┃ Package ┃ State ┃ Chroots ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 9896298 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9896292 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9896235 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9896230 │ python-openapi-pydantic │ ❌ failed │ fedora-rawhide-x86_64, fedora-43-x86_64 │
│ 9878007 │ python-openapi-pydantic │ ❌ failed │ fedora-rawhide-x86_64, fedora-43-x86_64 │
│ 9877978 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9877438 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9877277 │ python-openapi-pydantic │ ✅ succeeded │ fedora-43-x86_64, fedora-rawhide-x86_64 │
│ 9869333 │ python-openapi-pydantic │ ✅ succeeded │ fedora-rawhide-x86_64, fedora-43-x86_64 │
│ 9869332 │ python-openapi-pydantic │ ❌ failed │ fedora-43-x86_64, fedora-rawhide-x86_64 │
└─────────┴─────────────────────────┴──────────────┴─────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing to fuzzytail
&lt;/h2&gt;

&lt;p&gt;All types of contributions are very welcome to the project! If you are interested in contributing, whether with code, documentation, or even reporting problems, please feel free to do so through the repository on &lt;a href="https://github.com/r0x0d/fuzzytail" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>fedora</category>
      <category>packaging</category>
      <category>tooling</category>
      <category>fuzzytail</category>
    </item>
    <item>
      <title>Packaging for Fedora: woolly! Checking the dependency hell</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Wed, 10 Dec 2025 12:56:00 +0000</pubDate>
      <link>https://dev.to/r0x0d/packaging-for-fedora-woolly-checking-the-dependency-hell-59mm</link>
      <guid>https://dev.to/r0x0d/packaging-for-fedora-woolly-checking-the-dependency-hell-59mm</guid>
      <description>&lt;p&gt;If you’ve ever been interested in bringing software to Fedora that you use and thought would be interesting for the community, but were unsure about what you’d need to package to make it work, fear not as &lt;a href="https://github.com/r0x0d/woolly" rel="noopener noreferrer"&gt;woolly&lt;/a&gt; is here to help with this arduous process!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is woolly?
&lt;/h2&gt;

&lt;p&gt;In general, &lt;strong&gt;woolly&lt;/strong&gt; is a project I started due to a demand from my work at Red Hat. My team had a requirement to deliver two large projects on Fedora:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rhel-lightspeed/linux-mcp-server" rel="noopener noreferrer"&gt;Linux MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some people on the team already had experience in packaging, but others did not.&lt;/p&gt;

&lt;p&gt;Both projects mentioned above bring with them several dependencies (which are often not present in the Fedora repositories), therefore, it becomes a challenge for experienced and amateur packagers to discover the complete list of dependencies that will be necessary to bring from the upstream projects to downstream.&lt;/p&gt;

&lt;p&gt;So, from this need, &lt;strong&gt;woolly&lt;/strong&gt; was born.&lt;/p&gt;

&lt;p&gt;If you’ve ever had to package something for Fedora (or any other Linux distribution), you know how painful that task can be. An endless sea of dependencies, projects that don’t configure their dependencies as &lt;code&gt;optional&lt;/code&gt;, etc. All of this contributes to the difficulty of identifying and putting together an action plan to start this journey, especially for projects that are still active, since the list of dependencies can change considerably depending on the maintainers.&lt;/p&gt;

&lt;p&gt;In short, &lt;strong&gt;woolly&lt;/strong&gt; can discover the dependencies needed for your project, and tell you exactly what already exists in the Fedora repositories (which versions are present, too!), what’s missing, and generate reports that can facilitate your (or your team’s) understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  It looks perfect! How do I get the woolly?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;woolly&lt;/strong&gt; is available from &lt;a href="https://pypi.org/project/woolly" rel="noopener noreferrer"&gt;pypi&lt;/a&gt;, therefore, a simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install woolly

# or

pipx install woolly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will get you to the latest version.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I use woolly?
&lt;/h2&gt;

&lt;p&gt;Using &lt;strong&gt;woolly&lt;/strong&gt; is very easy! The user interface was designed to be intuitive and simple, so we don’t want distractions, but rather useful information! Take a look at the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;woolly check serde
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will produce the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analyzing Rust package: serde
Registry: crates.io
Cache directory: /home/r0x0d/.cache/woolly

  Analyzing Rust dependencies ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% • 0:00:05 complete!

Dependency Summary for 'serde' (Rust)
╭────────────────────────────┬───────╮
│ Metric │ Value │
├────────────────────────────┼───────┤
│ Total dependencies checked │ 10 │
│ Packaged in Fedora │ 7 │
│ Missing from Fedora │ 0 │
╰────────────────────────────┴───────╯

Dependency Tree:
serde v1.0.228 • ✓ packaged (1.0.225, 1.0.228)
└── serde_core v1.0.228 • ✓ packaged (1.0.225, 1.0.228)
    └── serde_derive v1.0.228 • ✓ packaged (1.0.225, 1.0.228)
        ├── proc-macro2 v1.0.103 • ✓ packaged (1.0.101, 1.0.103)
        │ └── unicode-ident v1.0.22 • ✓ packaged (1.0.19, 1.0.22)
        ├── quote v1.0.42 • ✓ packaged (0.3.15, 1.0.40, 1.0.41)
        │ └── proc-macro2 v1.0.103 • ✓ (already visited)
        └── syn v2.0.111 • ✓ packaged (1.0.109, 2.0.106, 2.0.111)
            ├── proc-macro2 v1.0.103 • ✓ (already visited)
            └── unicode-ident v1.0.22 • ✓ (already visited)

Log saved to: /home/r0x0d/.local/state/woolly/logs/woolly_20251210_091241.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how simple it is to use &lt;strong&gt;woolly&lt;/strong&gt; to check the dependencies of a given upstream project? &lt;code&gt;Rust&lt;/code&gt; is used by default in &lt;strong&gt;woolly&lt;/strong&gt; since the project was born from the need to check the dependencies of projects in &lt;code&gt;Rust&lt;/code&gt;, but it also has support for &lt;code&gt;Python&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;woolly check -l py flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analyzing Python package: flask
Registry: PyPI
Cache directory: /home/r0x0d/.cache/woolly

  Analyzing Python dependencies ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% • 0:00:07 complete!

    Dependency Summary for 'flask'
               (Python)
╭────────────────────────────┬───────╮
│ Metric │ Value │
├────────────────────────────┼───────┤
│ Total dependencies checked │ 13 │
│ Packaged in Fedora │ 11 │
│ Missing from Fedora │ 0 │
╰────────────────────────────┴───────╯

Dependency Tree:
flask v3.1.2 • ✓ packaged (3.1.2)
├── blinker v1.9.0 • ✓ packaged (1.9)
├── click v8.3.1 • ✓ packaged (8.1.7)
│ └── colorama v0.4.6 • ✓ packaged (0.4.6)
├── importlib-metadata v8.7.0 • ✓ packaged (8.7)
│ ├── zipp v3.23.0 • ✓ packaged (3.23)
│ └── typing-extensions v4.15.0 • ✓ packaged (4.15)
├── itsdangerous v2.2.0 • ✓ packaged (2.2)
├── jinja2 v3.1.6 • ✓ packaged (3.1.6)
│ └── markupsafe v3.0.3 • ✓ packaged (3.0.2)
├── markupsafe v3.0.3 • ✓ (already visited)
└── werkzeug v3.1.4 • ✓ packaged (3.1.3)
    └── markupsafe v3.0.3 • ✓ (already visited)

Log saved to: /home/r0x0d/.local/state/woolly/logs/woolly_20251210_091548.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Showing only optional dependencies
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Woolly&lt;/strong&gt; also has support for displaying the optional dependencies of projects, as this can be useful to check to find out which extras you can enable for your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;woolly check -l py flask --optional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously, the command above takes much longer to execute, since the project may have several optional dependencies to be consulted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analyzing Python package: flask
Including optional dependencies
Registry: PyPI
Cache directory: /home/r0x0d/.cache/woolly

  Analyzing Python dependencies ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% • 0:00:01 complete!

    Dependency Summary for 'flask'
               (Python)
╭────────────────────────────┬───────╮
│ Metric │ Value │
├────────────────────────────┼───────┤
│ Total dependencies checked │ 41 │
│ Packaged in Fedora │ 10 │
│ Missing from Fedora │ 0 │
│ │ │
│ Optional dependencies │ 27 │
│ ├─ Packaged │ 2 │
│ └─ Missing │ 0 │
╰────────────────────────────┴───────╯

Dependency Tree:
flask v3.1.2 • ✓ packaged (3.1.2)
├── blinker v1.9.0 • ✓ packaged (1.9)
├── click v8.3.1 • ✓ packaged (8.1.7)
│ └── colorama (max depth reached)
├── importlib-metadata v8.7.0 • ✓ packaged (8.7)
│ ├── zipp (max depth reached)
│ ├── typing-extensions (max depth reached)
│ ├── pytest (optional) (max depth reached)
│ ├── importlib-resources (optional) (max depth reached)
│ ├── packaging (optional) (max depth reached)
│ ├── pyfakefs (optional) (max depth reached)
│ ├── flufl-flake8 (optional) (max depth reached)
│ ├── pytest-perf (optional) (max depth reached)
│ ├── jaraco-test (optional) (max depth reached)
│ ├── sphinx (optional) (max depth reached)
│ ├── jaraco-packaging (optional) (max depth reached)
│ ├── rst-linker (optional) (max depth reached)
│ ├── furo (optional) (max depth reached)
│ ├── sphinx-lint (optional) (max depth reached)
│ ├── jaraco-tidelift (optional) (max depth reached)
│ ├── ipython (optional) (max depth reached)
│ ├── pytest-checkdocs (optional) (max depth reached)
│ ├── pytest-ruff (optional) (max depth reached)
│ ├── pytest-cov (optional) (max depth reached)
│ ├── pytest-enabler (optional) (max depth reached)
│ └── pytest-mypy (optional) (max depth reached)
├── itsdangerous v2.2.0 • ✓ packaged (2.2)
├── jinja2 v3.1.6 • ✓ packaged (3.1.6)
│ ├── markupsafe (max depth reached)
│ └── babel (optional) (max depth reached)
├── markupsafe v3.0.3 • ✓ packaged (3.0.2)
├── werkzeug v3.1.4 • ✓ packaged (3.1.3)
│ ├── markupsafe (max depth reached)
│ └── watchdog (optional) (max depth reached)
├── asgiref v3.11.0 (optional) • ✓ packaged (3.8.1)
│ ├── typing-extensions (max depth reached)
│ ├── pytest (optional) (max depth reached)
│ ├── pytest-asyncio (optional) (max depth reached)
│ └── mypy (optional) (max depth reached)
└── python-dotenv v1.2.1 (optional) • ✓ packaged (1.1)
    └── click (optional) (max depth reached)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Whenever you check the optional dependencies of a project, remember to use the &lt;code&gt;--max-depth&lt;/code&gt; parameter to limit the analysis, otherwise, &lt;strong&gt;woolly&lt;/strong&gt; will happily check all the optional dependencies of everything 😅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Showing missing only dependencies
&lt;/h3&gt;

&lt;p&gt;Following the same idea as &lt;code&gt;optional&lt;/code&gt; dependencies, &lt;strong&gt;woolly&lt;/strong&gt; also has the ability to show only what is missing from the Fedora repositories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;woolly check -l py cyclopts -m

Analyzing Python package: cyclopts
Registry: PyPI
Cache directory: /home/r0x0d/.cache/woolly

  Analyzing Python dependencies ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% • 0:00:00 complete!

  Dependency Summary for 'cyclopts'
               (Python)
╭────────────────────────────┬───────╮
│ Metric │ Value │
├────────────────────────────┼───────┤
│ Total dependencies checked │ 12 │
│ Packaged in Fedora │ 9 │
│ Missing from Fedora │ 2 │
╰────────────────────────────┴───────╯

Missing packages that need packaging:
  • cyclopts
  • rich-rst

Log saved to: /home/r0x0d/.local/state/woolly/logs/woolly_20251210_093409.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option is useful for large projects, since the list of dependencies can reach 100+, so, using the &lt;code&gt;--missing-only&lt;/code&gt; parameter, we have a view of only what is missing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating reports
&lt;/h3&gt;

&lt;p&gt;One of the coolest features we have with &lt;strong&gt;woolly&lt;/strong&gt; is the ability to generate reports in different formats, allowing you to customize how you see the results of your project’s dependencies!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Aliases&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;stdout&lt;/td&gt;
&lt;td&gt;Rich console output (default)&lt;/td&gt;
&lt;td&gt;console, terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;markdown&lt;/td&gt;
&lt;td&gt;Markdown report file&lt;/td&gt;
&lt;td&gt;md&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;JSON report file (machine-readable)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;template&lt;/td&gt;
&lt;td&gt;Custom template-based report (requires –template)&lt;/td&gt;
&lt;td&gt;tpl, jinja, jinja2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Contributing to woolly
&lt;/h2&gt;

&lt;p&gt;All types of contributions are very welcome to the project! If you are interested in contributing, whether with code, documentation, or even reporting problems, please feel free to do so through the repository on&lt;a href="https://github.com/r0x0d/woolly" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>fedora</category>
      <category>packaging</category>
      <category>woolly</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Programming languages are not just a tool</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Tue, 11 Nov 2025 20:39:45 +0000</pubDate>
      <link>https://dev.to/r0x0d/programming-languages-are-not-just-a-tool-l8m</link>
      <guid>https://dev.to/r0x0d/programming-languages-are-not-just-a-tool-l8m</guid>
      <description>&lt;p&gt;While I was browsing LinkedIn this week (I know!), I came across a post that discussed the idea that people consider programming languages to be just a tool, which, in my view, is a completely wrong conception.&lt;/p&gt;

&lt;p&gt;Unfortunately, I don't have the link to the post to reference here, but I think the idea of the debate is still valid for discussion. I vaguely remember that the post mentioned some different programming languages to try to justify its point, which I believe is the most reasonable argument for the debate, since if we analyze language by language, we can notice that, even though many have a common ancestor (the C language), their ideation and conception are totally different.&lt;/p&gt;

&lt;p&gt;Let's take the example of Rust[^1](&lt;a href="https://rust-lang.org/" rel="noopener noreferrer"&gt;https://rust-lang.org/&lt;/a&gt;) and Python[^2](&lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;https://www.python.org/&lt;/a&gt;), both are popular languages used in various open (and closed) source projects, however, the nature of both languages differs greatly, even though they can be used for the same purpose, in which Rust has a focus on performance, memory safety and stands out in embedded systems, while Python has an extreme appeal for prototyping, data science and is included in practically every current operating system.&lt;/p&gt;

&lt;p&gt;Not that the possibility of reproducing the same idea in different languages is impossible, but thinking that languages are merely tools that can be swapped between projects, and that they will continue to work the same way, is not a constant or absolute truth. Can you create an operating system[^3](&lt;a href="https://os.phil-opp.com/" rel="noopener noreferrer"&gt;https://os.phil-opp.com/&lt;/a&gt;) in Rust? The answer is yes! Can you do the same with Python? Technically possible[^4](&lt;a href="https://github.com/crcollins/pyOS" rel="noopener noreferrer"&gt;https://github.com/crcollins/pyOS&lt;/a&gt;), but extremely impractical due to the interpreted nature and overhead of the language.&lt;/p&gt;

&lt;p&gt;In some projects, you will need the performance of language X, or the ease of use of language Y, or even the availability of language Z, making your project's architecture change considerably depending on your choice, even the way you think about your programming is modified depending on the use of a particular language.&lt;/p&gt;

&lt;p&gt;Thinking this way, we have to take into consideration the aspect of language paradigms; when we work with functional languages, we have a more immutable way of thinking, which differs completely from object orientation, since in it, we think more about structures, code coupling, etc.&lt;/p&gt;

&lt;p&gt;Another very important point is the seniority of your team (considering a commercial project) with the language in question. If you have a team that is very efficient and experienced with Python, why risk building a system in Go, for example? You will end up reducing your team's performance and autonomy, sacrificing important (human) resources simply for the sake of the idea that "languages are just tools".&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>toolbox, IDEs and atomic desktops</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Fri, 22 Aug 2025 15:36:05 +0000</pubDate>
      <link>https://dev.to/r0x0d/toolbox-ides-and-atomic-desktops-15hn</link>
      <guid>https://dev.to/r0x0d/toolbox-ides-and-atomic-desktops-15hn</guid>
      <description>&lt;p&gt;My experience so far with Fedora Atomic desktops (or ostree based desktops) has been positive, of some sorte. First things first, there are a couple of features that I like about such desktops, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's easy to switch between desktop environments&lt;sup id="fnref1"&gt;1&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;All updates are signed with GPG Keys, so you know that you're pulling from trusted sources&lt;/li&gt;
&lt;li&gt;You can enable a systemd service to automatically update your system (In this case, every day)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a bunch more that I won't go into too much details. Whoever, you should know that there are a couple of "bad ux" in such environments, more related to development than anything else.&lt;/p&gt;

&lt;p&gt;In short, I think ostree environments are really well suited for daily uses and or cloud deployments (their original intention), regular users would probably not run into such cases if they are mainly using the their computer for browsing, gaming or basic text editting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running text editors (i.e; IDEs)
&lt;/h2&gt;

&lt;p&gt;One of the main deals with atomic desktops is the ability to run your favorite text editor. If you are a developer, then you are probably more likely to bump into such issues more frequently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For regular text editing, like reading a file or writing to a textual file, that should not be a problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's say that you're running vanilla Fedora and you usually install your VSCode through the official Microsoft repository and follow all the instructions, and in a couple of minutes, you have your development environment partially ready. At least, in regards of text editing. Pretty simple, right?&lt;/p&gt;

&lt;p&gt;When you make a switch to an ostree environment, you now face three options to install the same tool.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You add VSCode using &lt;code&gt;rpm-ostree&lt;/code&gt; and now you have a new package layer on top of your runnign system&lt;/li&gt;
&lt;li&gt;You decide to try the flatpak version of the same application&lt;/li&gt;
&lt;li&gt;You decide to go with toolbox/distrobox and install all the necessary tools inside it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While all of the three options are equally good, they have different approaches to installing your development packages (python, go, rust, libs, etc..) and interacting with your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first approach
&lt;/h2&gt;

&lt;p&gt;For instance, if you choose the &lt;code&gt;1.&lt;/code&gt; option, well, now you have a thirdy-party package layered on top of your system and that will integrate very well with most of the things, but, you still need to install the packages and libs somehow, right? Well, you could either continue layering your system with all the dependencies (but that's not quite why ostree is good at), or, find yourself having a toolbox/distrobox container running that you install all of those in there.&lt;/p&gt;

&lt;p&gt;For this instance, I would say that you are still in the best shape out of the three options, you are more likely to set up DevContainers and probably won't notice much difference when using your tools. The downside, at least in my opinion, is that now you have a development package layered on top of your OS that should not really be there. While this is fine, it is not an approach that I like. One of the advantages of ostree environments is that you have a reproducible environment no matter where you go, and layered such packages can break this experience with bad updates and all sort of other stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second approach
&lt;/h2&gt;

&lt;p&gt;Alright, but what about the &lt;code&gt;2.&lt;/code&gt; approach then? The VSCode package, specifically, does not really offer any support in their flatpak version, actually, it is something maintained by a community of people, and not really by Microsoft. While the folks that maintain such flatpak are amazing, you can't (and should not) really expected frequent updates or more in-depth problem solving.&lt;/p&gt;

&lt;p&gt;For instance, flatpaks are really small containers that package all you need inside it and let you execute the application in this "sandbox" env, and as you can imagine, this makes things a bit complicated when you have a flatpak (that is good mention, is read-only), being isolated and not being able to properly access the development packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The third approach
&lt;/h2&gt;

&lt;p&gt;While this approach is one of the most recommended out there (and I use that too), you might face problems such as, opening external programs if they are not properly set up inide the container, or and some other minimal problems.&lt;/p&gt;

&lt;p&gt;For instance, if you use VSCode and want to authenticated with GitHub to pull your settings, you might need to do a couple of workarounds to get a firefox or any other browser inside the container to launch it and authenticate. Personally, I don't like this approach, and it seems that there isn't a very good solution so far.&lt;/p&gt;

&lt;p&gt;Personally, I have made the switch to &lt;code&gt;neovim&lt;/code&gt; as I can install it inside my toolbox container, mainly because I wanted to use &lt;code&gt;neovim&lt;/code&gt; for a long time now, but haven't had any good opportunity, as using VSCode or any other text editor felt way more convenient.&lt;/p&gt;

&lt;h2&gt;
  
  
  The power of toolbox (or even distrobox)
&lt;/h2&gt;

&lt;p&gt;Toolbox is an amazing tool that you can spawn a container (either the default) or a custom image that you made.It allow for so many customization and possibility, and it is all sandboxed!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well, kinda of sandboxed. The toolbox container is created/ran with parameters that attach your &lt;code&gt;$HOME&lt;/code&gt; folder and other devices to the container&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short, you can enable a very powerful development environment and experience through toolbox usage and keep all the various packages individually contained within each set of containers that I maintain.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://fedoramagazine.org/trying-different-desktop-environments-using-rpm-ostree/" rel="noopener noreferrer"&gt;Trying different desktop environments using “rpm-ostree rebase”&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>fedora</category>
      <category>atomic</category>
      <category>containers</category>
    </item>
    <item>
      <title>My experience with Fedora Atomic</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Thu, 03 Jul 2025 15:34:55 +0000</pubDate>
      <link>https://dev.to/r0x0d/my-experience-with-fedora-atomic-5dpj</link>
      <guid>https://dev.to/r0x0d/my-experience-with-fedora-atomic-5dpj</guid>
      <description>&lt;h2&gt;
  
  
  Backstory
&lt;/h2&gt;

&lt;p&gt;I've beeng using Linux for the past couple of years now as my mainly driver. Started using Debian, Ubuntu, Gentoo, and now, I have estabilished Fedora as my main OS.&lt;/p&gt;

&lt;p&gt;My experience was always using the classic RPM-based Fedora daily for the past 5-6 years now. And, you know, it's been good and I never had any problems with it for the most part. Out of all the systems I have tried before, Fedora was the only one I really felt that I liked using. From package manager, to community, decisions and everything else.&lt;/p&gt;

&lt;p&gt;A year or two ago, a colleague from work introduced me the concept of &lt;a href="https://fedoraproject.org/atomic-desktops/" rel="noopener noreferrer"&gt;Atomic desktops&lt;/a&gt;. It felt weird at first, but I liked the idea of having my "core" system separated from my applications.&lt;/p&gt;

&lt;p&gt;When I tried to use &lt;a href="https://fedoraproject.org/atomic-desktops/silverblue/" rel="noopener noreferrer"&gt;Fedora Silverblue&lt;/a&gt; for the first time, it was a shock. I didn't know how to install the development packages I needed, the system had problems upgrading from one version to another, and man, everything felt so broken and clumsy that I gave up. The concept still looked very cool to me, but it was too much for me to learn back then.&lt;/p&gt;

&lt;p&gt;Up recently, I decided to give it another go, since a few years have passed, I thought that my experience would be different now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What version have I chosen now?
&lt;/h2&gt;

&lt;p&gt;For my current experience, I went with &lt;a href="https://fedoraproject.org/atomic-desktops/kinoite/" rel="noopener noreferrer"&gt;Fedora Kinoite&lt;/a&gt; due to be more familiar with the interface and feeling that it was more responsive than GNOME.&lt;/p&gt;

&lt;p&gt;GNOME UI still looks better in my opinion, but the performance of KDE looks way better.&lt;/p&gt;

&lt;h2&gt;
  
  
  How good (or bad) is to use such desktop daily?
&lt;/h2&gt;

&lt;p&gt;To be honest, it still feels a bit weird having to use &lt;code&gt;rpm-ostree&lt;/code&gt; than &lt;code&gt;dnf&lt;/code&gt;when I need to install a package, but overral, I really like the separation of "layers" that we have due to the entire OS being run in a container.&lt;/p&gt;

&lt;p&gt;Knowing that most of the applications that I need to use (VSCode, Slack, Firefox, etc...) are available through Flatpaks is also great. Not all of them are official, but the support is good enough.&lt;/p&gt;

&lt;p&gt;So far, I haven't figured out any blockers that a flatpak or a layer rebase couldn't do it for my system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Will I keep using it?
&lt;/h2&gt;

&lt;p&gt;It's very possible that I will adopt Fedora Kinoite as my main OS from now on. I like the separation of concerns here, the gpg verified updates, automatic updates, and the ability to "force" me to be more creative to solve daily problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Those problems are not complex, though. For instance, I've been dealing a lot with &lt;a href="https://github.com/containers/toolbox" rel="noopener noreferrer"&gt;toolbox&lt;/a&gt; to create development boxes or default boxes with the most used tools I use daily.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's hard for me to say "Yeah, I will go back to rpm based because it is way better" for now, so, I will give this experience a couple more months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;If you are looking for a change in your personal machines and want to try something new and exciting, I really recommend trying out any distribution of Fedora Atomic available. You don't have to go with Fedora Kinoite like I did, maybe GNOME or &lt;a href="https://fedoraproject.org/atomic-desktops/sway/" rel="noopener noreferrer"&gt;Sway&lt;/a&gt; is your thing.&lt;/p&gt;

&lt;p&gt;Maybe start with a VM so you don't lose your sanity on the first couple of days :)&lt;/p&gt;

</description>
      <category>fedora</category>
      <category>atomic</category>
      <category>containers</category>
    </item>
    <item>
      <title>Writting a GH extension with AI</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Wed, 01 Jan 2025 15:34:09 +0000</pubDate>
      <link>https://dev.to/r0x0d/writting-a-gh-extension-with-ai-m2e</link>
      <guid>https://dev.to/r0x0d/writting-a-gh-extension-with-ai-m2e</guid>
      <description>&lt;p&gt;I was looking out for some github repositories in my home page recently, with the hopes to find some interesting project or just to browse out the updates from the people that I follow. While I was looking out for those updates, I bumped into &lt;a href="https://github.com/deepseek-ai/DeepSeek-Coder" rel="noopener noreferrer"&gt;DeekSeek-Coder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At first, I thought to myself that it was just another AI experimental project, but to my fortune, I discovered gold here.&lt;/p&gt;

&lt;h2&gt;
  
  
  My history with AI
&lt;/h2&gt;

&lt;p&gt;I was always the type of person who didn't care too much about AI as I felt that it was not worth it to use it to do the job that I was supposed to do. That changed drastically when I started using &lt;a href="https://zed.dev/" rel="noopener noreferrer"&gt;zed&lt;/a&gt; and it's awesome AI integration.&lt;/p&gt;

&lt;p&gt;Zed makes interacting with AI pretty simple and straightforward. You just need to configure either a local LLM provider, an API Key to a service (like OpenAI), or you could just use the out-of-the-box Zed solution with Claude.&lt;/p&gt;

&lt;p&gt;The later was my choice for diving into the AI world. I felt that Claude had good code generation and was driving giving me good answers here and there.&lt;/p&gt;

&lt;p&gt;When I bumped into the free tier limit with this integration, I started using other providers like &lt;a href="https://chatgpt.com" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt; or even &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ChatGPT, of course, had the best results when you ask the question using that limited amout of tokens for the good model they provide, and GitHub Copilot on the free tier was... Strange...&lt;/p&gt;

&lt;p&gt;With the bad experience with GitHub Copilot I had and not wanting to pay for a subscription in ChatGPT, &lt;code&gt;DeepSeek-Coder&lt;/code&gt; felt like a good option for myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writting some code with it
&lt;/h2&gt;

&lt;p&gt;So, to test this out, I asked &lt;code&gt;DeepSeek-Coder&lt;/code&gt; to write some code for me. It couldn't be just some random code, but something that I really wanted. I asked&lt;code&gt;DeepSeek-Coder&lt;/code&gt; to write me a bash script to interact with &lt;code&gt;gh api&lt;/code&gt; command and retrieve the stargazer from a user.&lt;/p&gt;

&lt;p&gt;Why this matters, you may think? Well, I've grown to use stargazers in github a lot recently, and every time that I wanted to clone a particular repository or a set of repositories from a tag or a topic, it was a pain to do that all by hand. So I asked &lt;code&gt;DeepSeek-Coder&lt;/code&gt; to help me out with that and write some simple bash script that could do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the user starred repositories&lt;/li&gt;
&lt;li&gt;Filter the repositories by a "tag"&lt;/li&gt;
&lt;li&gt;Show it using TUI (mainly fzf) the repositories for the user to select which repo they want to download&lt;/li&gt;
&lt;li&gt;If the repo already exists, skip it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A pretty simple challenge, and something that an AI can do.&lt;/p&gt;

&lt;p&gt;All of the questions I asked in that chat window, &lt;code&gt;DeepSeek-Coder&lt;/code&gt; did it amazingly well. The code itself was not that difficult and did not contain trick regex expressions and stuff like that, but it managed to handle all my use case above pretty nicely.&lt;/p&gt;

&lt;p&gt;I need to test it a bit more and try to generate some more complex use cases, but &lt;code&gt;DeepSeek-Coder&lt;/code&gt; was on point with what I wanted and was able to generate for me a single bash script that could do all the above. Something that &lt;code&gt;GitHub Copilot&lt;/code&gt; failed to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you want to take a look at what I did using &lt;code&gt;DeepSeek-Coder&lt;/code&gt;, please feel free to check out the gh extension repository I created:&lt;a href="https://github.com/r0x0d/gh-stargazer-clone" rel="noopener noreferrer"&gt;r0x0d/gh-stargazer-clone&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>github</category>
      <category>extension</category>
      <category>bash</category>
    </item>
    <item>
      <title>SystemBus vs SessionBus</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Fri, 27 Dec 2024 15:30:11 +0000</pubDate>
      <link>https://dev.to/r0x0d/systembus-vs-sessionbus-3b3o</link>
      <guid>https://dev.to/r0x0d/systembus-vs-sessionbus-3b3o</guid>
      <description>&lt;p&gt;Have you ever tried to develop an entire application that relies on d-bus (without knowing too much of d-bus) and when you had to run that application in a headless server, all of the sudden everything stops to work?&lt;/p&gt;

&lt;p&gt;Well... That's basically what I did.&lt;/p&gt;

&lt;p&gt;Today, we gonna talk about the differences between system bus and session bus, and why it is important for you to develop your application with the correct term in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session Bus
&lt;/h2&gt;

&lt;p&gt;Session bus is a special term for d-bus that identifies a message bus (communication) between processes, and is tied to user connnection. You can use a session bus if your application has the necessity to run for this single user and is tied to that environment, the &lt;em&gt;session&lt;/em&gt;. But keep in mind that it will require that your application runs on a server that has graphical display capabilities&lt;/p&gt;

&lt;p&gt;Examples of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KDE&lt;/li&gt;
&lt;li&gt;GNOME&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  System Bus
&lt;/h2&gt;

&lt;p&gt;System bus, on the other hand, is used for system-wide process communication, they do not require a graphical session (like the Session Bus), and can be executed in headless servers without any problems.&lt;/p&gt;

&lt;p&gt;System bus is indicated for you to use whenever you have to develop an application that needs to communicate with another service in that server/computer, and does not necessarily depends on anything graphical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the difference between the two matters?
&lt;/h2&gt;

&lt;p&gt;The difference between the two is important to know mainly when developing a new application. If you want to develop something that will run in a server/cloud/ephemeral environment, you need to keep this in mind as those type of machines won't have a graphical display available for you. You need to know which type of message bus to connect before you can publish your code to production.&lt;/p&gt;

&lt;p&gt;In the end, you won't have a lot of headache if you choose to develop your service in with the "wrong" kind of message bus, but, that could mean that you will have to patch, delay, and possibily adapt your workflow to make it work with the correct bus.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I choose the correct bus?
&lt;/h2&gt;

&lt;p&gt;Essentially, you should follow a very simple rule. If you are developing a new daemon that needs to notify the user about something (that is running in the backend), your daemon needs graphical access or to communicate with KDE, GNOME and etc.. That is the perfect use case for a &lt;code&gt;session bus&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are developing a service that will talk with a external backend service (let's say an API), do some calculations, won't need to update any UI elements or, and will need to communicate with more system services, then you can go with a &lt;code&gt;system bus&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's that simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  A specific note about the system bus option
&lt;/h2&gt;

&lt;p&gt;System bus has a particularity that it needs to be told here. If you are running your service with a regular &lt;code&gt;session bus&lt;/code&gt;, you won't need any extra tweaks or tricks, as you are already authenticated and using the user session, the bus will be automatically set that your user will be able to intecract with it.&lt;/p&gt;

&lt;p&gt;However, for the &lt;code&gt;system bus&lt;/code&gt;, since that doesn't require a graphical session, you will need to create a &lt;code&gt;.conf&lt;/code&gt; file under a specific folder managed by dbus to allow your service to own the name in the bus, and also, specify which users can send and receive messages from your dbus.&lt;/p&gt;

&lt;p&gt;The file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"&amp;gt;
&amp;lt;busconfig&amp;gt;

  &amp;lt;policy context="default"&amp;gt;
    &amp;lt;allow own="com.example.service"/&amp;gt;
  &amp;lt;/policy&amp;gt;


  &amp;lt;policy context="default"&amp;gt;
    &amp;lt;allow send_destination="com.example.service"/&amp;gt;
    &amp;lt;allow receive_sender="com.example.service"/&amp;gt;
  &amp;lt;/policy&amp;gt;
&amp;lt;/busconfig&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it should be placed under: &lt;code&gt;/etc/dbus-1/system.d/com.example.service.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By doing that, you will be able to let your service to acquire the bus name you want and make also allow the specific users to communicate with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://maemo.org/maemo_training_material/maemo4.x/html/maemo_Platform_Development_Chinook/Chapter_01_DBus_The_Message_Bus_System.html" rel="noopener noreferrer"&gt;Chapter 01 - DBus The Message Bus System&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>linux</category>
      <category>programming</category>
    </item>
    <item>
      <title>Systemd unit activation via dbus</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Thu, 26 Dec 2024 15:30:11 +0000</pubDate>
      <link>https://dev.to/r0x0d/systemd-unit-activation-via-dbus-2550</link>
      <guid>https://dev.to/r0x0d/systemd-unit-activation-via-dbus-2550</guid>
      <description>&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;Recently a co-worker of my team has asked me this trivial question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey, the users will need to call &lt;code&gt;systemctl ...&lt;/code&gt; on their own to activate our daemon?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, this is a simple question, right? I mean, it implies that we want to reduce friction from the user point of view to use our tool. If they call any commands we have in our terminal client, it should activate the daemon on it's own.&lt;/p&gt;

&lt;p&gt;In my full ignorance, I thought to myself&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yeah, that's pretty easy. I think I can just change this setting in the service level and we are done...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What a fool I am.&lt;/p&gt;

&lt;p&gt;We all know that &lt;a href="https://github.com/systemd/systemd" rel="noopener noreferrer"&gt;systemd&lt;/a&gt; and&lt;a href="https://gitlab.freedesktop.org/dbus/dbus/" rel="noopener noreferrer"&gt;dbus&lt;/a&gt; are beast of their own, but what I didn't know was that just a simple change on our own service files would lead me to hours of exploration, some documentations that are not properly documentated (don't judge, we all have done that.), and to my surprise, the answer again was very simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is important?
&lt;/h2&gt;

&lt;p&gt;Well, let me try to be real quick and conscise here. I work on a tool that will ship a client and a daemon that will work together to deliver some answer to the user in their own terminal. The tool is called&lt;a href="https://github.com/rhel-lightspeed/command-line-assistant" rel="noopener noreferrer"&gt;command-line-assistant&lt;/a&gt;. The daemon encapsulates all the core logic behind the operations we do and the client is just a regular client. It show stuff on the terminal.&lt;/p&gt;

&lt;p&gt;To reduce the user friction and adoption, we thought that it would be a good idea that after you install the tool with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf install command-line-assistant

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could just easily do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c "why systemd is so complex?"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that would give you a real answer.&lt;/p&gt;

&lt;p&gt;Pretty good, right? You don't need to tweak any configuration file, any settings, nothing. We deal with that stuff for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  And why this was so difficult?
&lt;/h2&gt;

&lt;p&gt;Well, to begin with, I'm not that experienced with systemd and dbus. This is my first time working with it, and it's been amazing. I'm loving all the challenges and knowledge I'm gaining, but dude... Sometimes I wonder why those things exists.&lt;/p&gt;

&lt;p&gt;The main problem (besides the one above) is that we decided to split our dbus objects into two main categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;query - &lt;code&gt;com.redhat.lightspeed.query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;history - &lt;code&gt;com.redhat.lightspeed.history&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The query category is responsabile for exporting and managing all stuff related to user queries, like the example above about systemd. The history category, on the other hand, serve the purpose to store, read and manage the user conversation cache. This is mainly used for users to remember the interactions they had with the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coulnd't you just follow a tutorial?
&lt;/h2&gt;

&lt;p&gt;Well. I tried. And that was mainly my source of confusion...&lt;/p&gt;

&lt;p&gt;See the below snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[D-BUS Service]
Name=org.example.simple-dbus-service
Exec=/usr/sbin/simple-dbus-service
User=root
SystemdService=simple-dbus-service.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, approach this with the idea of "I don't know what I'm doing" and your first guess, if you're like me, would be that this is something managed by systemd, right?&lt;/p&gt;

&lt;p&gt;The docs for systemd gives you this nice paragraph:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For bus-activatable services, do not include a [Install] section in the systemd service file, but use the SystemdService= option in the corresponding DBus service file, for example (/usr/share/dbus-1/system-services/org.example.simple-dbus-service.service):&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Self-explanatory, right? I know...&lt;/p&gt;

&lt;p&gt;The deal with that is that this small snippet I pasted above is actually a unit service... for &lt;code&gt;dbus&lt;/code&gt;... Yeah, that's right. It turns our that dbus can have "units like" files just like systemd.&lt;/p&gt;

&lt;p&gt;Any time that you end up seeing a path that begins with&lt;code&gt;/usr/share/dbus-1/system-services&lt;/code&gt;, you know that this will be a dbus service, not &lt;code&gt;systemd&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;In short, the purpose of this file is: Act as a intermediate service for activating your systemd unit.&lt;/p&gt;

&lt;p&gt;What does the trick for activating the systemd unit is this part right here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SystemdService=simple-dbus-service.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By specifying the name of the systemd service it needs to trigger, whenever you publish a new message to your dbus object, it will trigger the systemd unit start for you.&lt;/p&gt;

&lt;p&gt;What they don't tell you is, if you have a multi-object daemon, one service like that won't ever trigger your systemd unit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alright! And how did you overcome this?
&lt;/h2&gt;

&lt;p&gt;The fix is pretty simple. For every object (or in this case, I'm calling "sub" object), you have to create a new dbus service file to hold the trigger for you.&lt;/p&gt;

&lt;p&gt;Using the above categories I mentioned about my project, &lt;code&gt;query&lt;/code&gt; and &lt;code&gt;history&lt;/code&gt;, I would need to have two dbus services that would look something like this:&lt;/p&gt;

&lt;p&gt;File: &lt;code&gt;/usr/share/dbus-1/system-services/com.redhat.lightspeed.query.service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[D-BUS Service]
Name=com.redhat.lightspeed.query
Exec=/bin/false
User=root
SystemdService=simple-dbus-service.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File: &lt;code&gt;/usr/share/dbus-1/system-services/com.redhat.lightspeed.history.service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[D-BUS Service]
Name=com.redhat.lightspeed.history
Exec=/bin/false
User=root
SystemdService=simple-dbus-service.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They can (and often will, in that setup) point to the same systemd unit file. The deal is that dbus will use the name of the service, in this case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
Name=com.redhat.lightspeed.history
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To know that you sent a message from a client and dbus needs to trigger your systemd unit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;That's mainly it! It took me some long hours debugging and trying stuff out. Working with systemd/dbus is not easy, but when you learn something new about those huge systems, you feel so good.&lt;/p&gt;

&lt;p&gt;That's it! Hope you liked the reading so far, and see you in the next post.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html" rel="noopener noreferrer"&gt;systemd service docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/31725112" rel="noopener noreferrer"&gt;How to define a d-bus activated systemd service?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rhel-lightspeed/command-line-assistant/pull/72" rel="noopener noreferrer"&gt;GH PR#72&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>How to keep track of day-to-day workflow problems?</title>
      <dc:creator>Rodolfo Olivieri</dc:creator>
      <pubDate>Thu, 26 Dec 2024 15:30:11 +0000</pubDate>
      <link>https://dev.to/r0x0d/how-to-keep-track-of-day-to-day-workflow-problems-1enb</link>
      <guid>https://dev.to/r0x0d/how-to-keep-track-of-day-to-day-workflow-problems-1enb</guid>
      <description>&lt;p&gt;TLDR; Here's the repository: &lt;a href="https://github.com/r0x0d/troubleshoot" rel="noopener noreferrer"&gt;https://github.com/r0x0d/troubleshoot&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What I'm even talking about?
&lt;/h1&gt;

&lt;p&gt;So, recently I decided to start out a repository in GitHub to track out all the workarounds/solutions for common problems that I faced regularily in my machines. Problems like: "Why is my RDP in gnome not working?" or "I have configured fingerprintd, but it does not work"&lt;/p&gt;

&lt;p&gt;Such problems are very common when you reset your machines and start from zero, or things just break when are you are sleeping. I was tired of losing countless hours looking around the internet to find that one answer from a forum in 2002 that solved the issue, hence, I created this new repository with the idea of tracking all those solutions.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do you even structure something like that?
&lt;/h1&gt;

&lt;p&gt;Well, the repository structure is quite simple. Is just a markdown file with well-defined headers. I choose to go simple here to avoid custom tooling or getting myself a new problem and make this the chicken-egg problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## &amp;lt;Operating system&amp;gt;
### &amp;lt;Category of the problem&amp;gt;
- &amp;lt;A small description&amp;gt;
-- &amp;lt;The solution&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps me to keep track of specific problems by category and by operating system. On my day to day, I usually use Linux for my work/development, and Windows for gaming.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exceptions to the simple structure
&lt;/h1&gt;

&lt;p&gt;Recently, I started to track out problems that are not OS specifics, but rather_tooling_ specifics. With that in mind, I had to add an exception to my simple structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## &amp;lt;Operating system&amp;gt;
### &amp;lt;Category of the problem&amp;gt;
- &amp;lt;A small description&amp;gt;
-- &amp;lt;The solution&amp;gt;

## Tooling

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Tooling&lt;/code&gt; header is platform agnostic. It is used for problems that could be seen either in Linux or Windows.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>github</category>
      <category>productivity</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
