<?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: Frank Kmiec</title>
    <description>The latest articles on DEV Community by Frank Kmiec (@itinkerthere4ican).</description>
    <link>https://dev.to/itinkerthere4ican</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%2F1339096%2F689f0730-d698-4a4f-8434-25083f59667b.png</url>
      <title>DEV Community: Frank Kmiec</title>
      <link>https://dev.to/itinkerthere4ican</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itinkerthere4ican"/>
    <language>en</language>
    <item>
      <title>Bluefin (Atomic) Linux is for Tinkerers</title>
      <dc:creator>Frank Kmiec</dc:creator>
      <pubDate>Mon, 12 Jan 2026 19:45:52 +0000</pubDate>
      <link>https://dev.to/itinkerthere4ican/bluefin-atomic-linux-is-for-tinkerers-5636</link>
      <guid>https://dev.to/itinkerthere4ican/bluefin-atomic-linux-is-for-tinkerers-5636</guid>
      <description>&lt;p&gt;During downtime over the holidays, I like to tinker with computers. Given this habit and knowing how often I break my Linux system in the process, I was pretty excited when I came across &lt;a href="https://distrobox.it" rel="noopener noreferrer"&gt;Distrobox&lt;/a&gt;, which lets you run other Linux distros in a container, protecting your host system from whatever shenanigans you want to try. It recommended the &lt;a href="https://podman.io/" rel="noopener noreferrer"&gt;Podman&lt;/a&gt; container engine over Docker and that was another exciting tool to learn about. This was going to be fun. &lt;/p&gt;

&lt;p&gt;Then, ironically, while struggling to install a recent version of Podman on Ubuntu 24.04 (not available in ubuntu repos), &lt;strong&gt;&lt;em&gt;I borked my system!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, shoot. Now what? &lt;/p&gt;

&lt;p&gt;I had learned that Distrobox and Podman come from the Redhat / Fedora Linux community and are heavily used in so-called immutable / atomic distros. I had seen some articles and videos by &lt;a href="https://www.youtube.com/@JorgeCastro" rel="noopener noreferrer"&gt;Jorge Castro&lt;/a&gt; about Fedora Silverblue, an atomic Fedora distro, and his Ubuntu-flavored customizations. I'm a longtime Ubuntu user, too, so that made Fedora more possible in my mind. I had also learned about &lt;a href="https://github.com/bootc-dev/bootc" rel="noopener noreferrer"&gt;bootc&lt;/a&gt;, a tool promising to underpin future immutable distros by using container technology to build, distribute, install and upgrade OS images on bare metal hardware. As it turns out, Jorge is one of the developers of a new bootc distribution based on Fedora Silverblue called &lt;a href="https://projectbluefin.io/" rel="noopener noreferrer"&gt;Bluefin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At this point, I had to reinstall the OS, but I would run the same risk of borking the system trying to install Podman if I reinstalled Ubuntu. I decided to give Bluefin a shot. &lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Simply put, it was the easiest installation I've ever experienced. Up and running in about 10 minutes. No hardware issues. Everything just worked. As an aside, I decided to change up my dual-boot and move Windows to a separate drive. It took more than 3 hours from the start of the install process to having a working system (no bells and whistles ... just a functional display, a user folder matching my username, and Chrome installed).&lt;/p&gt;

&lt;p&gt;It took about 5 more minutes to apply Secure Boot and whole-disk encryption with TPM unlock using user-friendly &lt;code&gt;ujust&lt;/code&gt; commands included with Bluefin (after 20 minutes of googling and nervous flip flopping). Google &lt;a href="https://dev.to/achu1612/disk-encryption-using-luks-and-tpm20-19hb"&gt;TPM setup on Linux&lt;/a&gt; if you want a sense of the complexity that drives most of us to run less securely. This is the security I want if my travel laptop is stolen.&lt;/p&gt;

&lt;p&gt;Of course, as a developer, I wanted to apply Bluefin's devmode that brings in a suite of modern development tools including Podman and Distrobox, the very tools that sent me down this path in the first place. One &lt;code&gt;ujust devmode&lt;/code&gt; command and a reboot later and I had a powerful developer workstation. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rules of the Road
&lt;/h2&gt;

&lt;p&gt;Bluefin is opinionated and aims to keep system and user separate in order to ensure a stable system. This is where the immutability comes in. Only the &lt;code&gt;/etc&lt;/code&gt; and &lt;code&gt;/var&lt;/code&gt; directories are writeable. Before you write this off as a non-starter, know that most other system directories you might need to interact with to configure and run the system are linked to sub-directories in &lt;code&gt;/etc&lt;/code&gt; and &lt;code&gt;/var&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/home&lt;/code&gt; -&amp;gt; &lt;code&gt;/var/home&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/usr/local&lt;/code&gt; -&amp;gt; &lt;code&gt;/var/usrlocal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/opt&lt;/code&gt; -&amp;gt; &lt;code&gt;/var/opt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/mnt&lt;/code&gt; -&amp;gt; &lt;code&gt;/var/mnt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/media&lt;/code&gt; -&amp;gt; &lt;code&gt;/run/media&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables you to add systemd unit files and rules, install software in &lt;code&gt;/usr/local&lt;/code&gt;, update &lt;code&gt;/etc/fstab&lt;/code&gt; and &lt;code&gt;/etc/hosts&lt;/code&gt;, for example. &lt;/p&gt;

&lt;p&gt;Coming from Ubuntu and using the apt package manager, I expected to have to learn the Fedora dnf package manager, but as it turns out, Bluefin recommends the following alternatives, depending on what you want to install: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flatpak:&lt;/strong&gt; For GUI applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.projectbluefin.io/command-line/" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt;:&lt;/strong&gt; For CLI and TUI apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distrobox / Toolbox:&lt;/strong&gt; For apps or binaries not available via Flatpak and Homebrew
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://coreos.github.io/rpm-ostree/administrator-handbook/#hybrid-imagepackaging-via-package-layering" rel="noopener noreferrer"&gt;rpm-ostree&lt;/a&gt;:&lt;/strong&gt; For low-level packages needed on the host system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This might seem like a lot of complexity compared with &lt;em&gt;apt install this&lt;/em&gt; and &lt;em&gt;apt install that&lt;/em&gt;, but the result is clean separation and ease of maintenance.&lt;/p&gt;

&lt;p&gt;Flatpaks are isolated and can be easily removed without impacting the system. &lt;/p&gt;

&lt;p&gt;Everything installed by Homebrew is under &lt;code&gt;/home/linuxbrew/.linuxbrew&lt;/code&gt;, clearly separate from the system packages and easily removed without incident. &lt;/p&gt;

&lt;p&gt;Containers exist to isolate filesystems and processes, so Distrobox is your ultimate tinkering playground. Install anything from any distribution and export it to make it run as if installed on the host system. If you break your container, or just don't like what you installed, you can delete it easy peasy and your system will still be working like new. &lt;/p&gt;

&lt;p&gt;Finally, rpm-ostree gives you the means to install whatever packages you need as a layer on top of the host filesystem image managed by Bluefin. As an example, I installed the &lt;strong&gt;envycontrol&lt;/strong&gt; package to be able to turn off the nvidia gpu in my laptop to save battery. &lt;/p&gt;

&lt;p&gt;Now, rpm-ostree, in particular, gives you the ability to bork your system. And this is where the image-based nature of Bluefin is the ultimate backstop. &lt;/p&gt;

&lt;h2&gt;
  
  
  Updates and Restoring When Things Go Wrong
&lt;/h2&gt;

&lt;p&gt;Bluefin uses OCI images and bootc to enable image-based updates that are staged and applied automatically after a reboot. That means packages aren't updated piecemeal with fingers crossed. Instead, a tested stable image replaces the prior tested stable image and you are, in most cases, blissfully unaware. Even more magical, it does this without interfering with your apps, configurations and customizations thanks to rpm-ostree and the clean separation described earlier. &lt;/p&gt;

&lt;p&gt;Now, every user's combination of hardware, packages, apps and configuration is unique, so it's still possible that an update could break your system, or more likely that you add some ill-advised package or config via rpm-ostree and break it yourself. However, in that unlikely event, rolling back to a working system is as easy as selecting it from a menu at boot time. Amazing!&lt;/p&gt;

&lt;p&gt;Now, restoring the immutable system doesn't restore your personal data if lost due to, for example, a drive failure. So, having a backup strategy is still important, but the built-in rollback for the host system makes having a workable backup strategy a lot easier. &lt;/p&gt;

&lt;p&gt;Implementing a backup strategy short of block device replication is an exercise in hard choices. What do I backup? Where is all the important stuff located? How do I reapply what I backed up when I'm ready to restore the system? Is it a different process depending on how it got broke? &lt;/p&gt;

&lt;p&gt;With Bluefin, getting back to a current working system is a reboot. After that, I keep a list of my flatpaks, homebrew installs, rpm-ostree layered packages, the few specific system customizations I've made to &lt;code&gt;/etc/fstab&lt;/code&gt; and &lt;code&gt;/etc/hosts&lt;/code&gt;, for example, and backup &lt;code&gt;/home&lt;/code&gt;. (NOTE: This will get easier still with new tools and options that I'm still learning from Bluefin)&lt;/p&gt;

&lt;h2&gt;
  
  
  Tinkering
&lt;/h2&gt;

&lt;p&gt;With so much thought having gone into the stability and recoverability of the system, Bluefin (and &lt;a href="https://universal-blue.org/" rel="noopener noreferrer"&gt;ublue&lt;/a&gt;, in general) gives me a lot more confidence about tinkering with new software. &lt;/p&gt;

&lt;p&gt;Ideally, I'll find what I'm looking for available as a flatpak or via Homebrew, which are nearly certain to be problem-free. If not, I can launch a Distrobox container and install just about anything from any Linux distro. I might break the container, but I won't break my system. &lt;/p&gt;

&lt;p&gt;If developing software, I'll use a &lt;a href="https://docs.projectbluefin.io/devcontainers" rel="noopener noreferrer"&gt;devcontainer&lt;/a&gt; launched in VS Code and any system dependencies will be installed in the container, leaving my host system conflict-free. &lt;/p&gt;

&lt;p&gt;Finally, infrequently, like when I'm experimenting with a whole new paradigm in operating systems, some things will need to be installed on the host system. As noted above, rpm-ostree gives me that option and the confidence of knowing that undoing any damage is a reboot away. &lt;/p&gt;

&lt;p&gt;This is going to be fun!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>atomic</category>
      <category>bluefin</category>
      <category>immutable</category>
    </item>
    <item>
      <title>Goscript: Go For (go-pher?) Scripting</title>
      <dc:creator>Frank Kmiec</dc:creator>
      <pubDate>Tue, 15 Apr 2025 16:29:44 +0000</pubDate>
      <link>https://dev.to/itinkerthere4ican/goscript-go-for-go-pher-scripting-ak9</link>
      <guid>https://dev.to/itinkerthere4ican/goscript-go-for-go-pher-scripting-ak9</guid>
      <description>&lt;p&gt;Scripts are short bits of code typically written to automate a series of otherwise manual steps or accomplish a small task. With that focus on quickly getting some task done, a compiled, strongly-typed, multi-threaded language might not be your first thought, but Go has a lot going for it when it comes to scripting. With a bit of support, it can be a compelling choice.   &lt;/p&gt;

&lt;p&gt;Using Go for scripting isn't a new idea. It's attractive because Go has a fantastic standard library and a large ecosystem of third-party packages, the compiler is very fast and a tool like &lt;code&gt;go run&lt;/code&gt; almost makes it &lt;em&gt;feel&lt;/em&gt; like an interpreted scripting language. And, as a natively compiled language, Go is &lt;strong&gt;&lt;em&gt;fast&lt;/em&gt;&lt;/strong&gt;. Some say Go is too verbose for scripting, but I'll take "easy to read and understand" over "cryptic but powerful" every time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fkmiec/goscript" rel="noopener noreferrer"&gt;Goscript&lt;/a&gt; is an opinionated tool aimed at making scripting in Go more convenient. It was inspired by &lt;a href="https://github.com/bitfield/script" rel="noopener noreferrer"&gt;bitfield/script&lt;/a&gt;, which brings functionality similar to Unix pipes to Go. By opinionated, I mean that &lt;strong&gt;Goscript&lt;/strong&gt; embraces Go modules (rather than GOPATH with modules turned off) and uses a dedicated module project for your "scripts". It asks you to update your PATH as part of the setup so that your scripts can be immediately available as system-wide commands. It enables treating Go code like a local script with --exec and shebang options, but encourages reuse by letting you name your commands and then saving them, together with source, in your dedicated Goscript project. Finally, its many options are designed to make the project fade into the background and make writing scripts in Go convenient and easy like your favorite scripting language. &lt;/p&gt;

&lt;h2&gt;
  
  
  Goscript Features:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Execute simple go code directly on the command line with automatic imports for stdlib and your most-used third-party packages&lt;/li&gt;
&lt;li&gt;Execute Go source files directly with the --exec option or by including the Unix shebang&lt;/li&gt;
&lt;li&gt;Compile Go code into named binaries for repeated use, enabling you to build up a library of custom commands&lt;/li&gt;
&lt;li&gt;Automatically "go get" missing modules required by imports (and remove them when the code importing them is deleted)&lt;/li&gt;
&lt;li&gt;Organize all of your Go "scripts" in one project, accessible system-wide&lt;/li&gt;
&lt;li&gt;Generate a template source file for your next Go script&lt;/li&gt;
&lt;li&gt;List, edit and export sources and binaries for existing commands &lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, implied in the term "script" is the idea that the code is relatively small and uncomplicated. If you need multiple source files or a complex build process, you will want to create a dedicated Go project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Do &lt;code&gt;go install github.com/fkmiec/goscript@latest&lt;/code&gt; followed by &lt;code&gt;goscript --setup help&lt;/code&gt; and follow the instructions. &lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The goscript executable will wrap any code specified on the command line with a main function and apply any specified imports before compiling and optionally executing the code. If no name is given, temporary files will be created and cleaned up. If a name is provided, then the binary file will be &lt;code&gt;[project folder]/bin/[name]&lt;/code&gt; and the source file will be &lt;code&gt;[project folder]/src/[name].go&lt;/code&gt;.By adding the &lt;em&gt;[project]&lt;/em&gt; and &lt;em&gt;[project]/bin&lt;/em&gt; folders to your PATH environment variable, the goscript command can be used anywhere on your system and the resulting binaries you build with it will also be immediately available to execute like other system commands (such as ls, cat, echo, grep, etc.).&lt;/p&gt;

&lt;p&gt;If the --file option is used, then &lt;strong&gt;Goscript&lt;/strong&gt; will assume the file is a complete Go source file and build it as is, automatically downloading missing modules required by imports. The --exec option can be included to run it immediately. On Linux and Mac, a shebang at the top of a Go source file works similarly. The --template option can print out a skeleton source file as a starting point, including a shebang line at the top in case your aim is to produce a locally executable script. While the shebang is incompatible with Go, &lt;strong&gt;Goscript&lt;/strong&gt; automatically strips it out before compiling. &lt;/p&gt;

&lt;p&gt;Nearly every other &lt;strong&gt;Goscript&lt;/strong&gt; option is intended to let you work with Go code where you are and put the project and modules back of mind. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's See Some Examples
&lt;/h2&gt;

&lt;p&gt;We'll use toy examples to keep things simple and demonstrate some features of &lt;strong&gt;Goscript&lt;/strong&gt;. An inaugural "Hello World!" can be executed directly on the command line 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;gt; $ goscript --exec --code 'fmt.Println("Hello Goscript!")'    
Hello Goscript!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to &lt;code&gt;go run&lt;/code&gt;, &lt;strong&gt;Goscript&lt;/strong&gt; produced a binary and immediately executed it. Unlike &lt;code&gt;go run&lt;/code&gt;, however, &lt;strong&gt;Goscript&lt;/strong&gt; automatically supplied the package declaration, imports and main function. &lt;/p&gt;

&lt;p&gt;Adding the &lt;code&gt;--name&lt;/code&gt; option will save the binary and source files to the project, which you can see with the --list option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ goscript --exec --name hello --code 'fmt.Println("Hello Goscript!")'    
Hello Goscript!

&amp;gt; $ goscript --list                                                       
hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;--cat&lt;/code&gt;, we can see that the code was wrapped in a main function and the fmt package was imported for us. Using the &lt;code&gt;--code&lt;/code&gt; option, &lt;strong&gt;Goscript&lt;/strong&gt; will automatically add imports for packages in the standard library and any packages listed in the project's imports.json file. The imports.json file also enables specifying a different package alias (e.g. "re" rather than "regexp").&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ goscript --cat hello                                                 
#!/usr/bin/env -S goscript
package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello Goscript!")
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note also that &lt;code&gt;--cat&lt;/code&gt; added a shebang (#!/usr/bin/env -S goscript) to the top of the file in the event your intent was to execute locally as a script. More on that later.&lt;/p&gt;

&lt;p&gt;Since the &lt;em&gt;[project]/bin&lt;/em&gt; folder is on the PATH, you can execute the compiled command directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ hello                                                              
Hello Goscript!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--cat&lt;/code&gt; option can also be used together with the &lt;code&gt;--name&lt;/code&gt; option to copy an existing command to a new name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ goscript --cat hello --name greet                                         
A copy of hello was saved as greet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use an IDE, such as VSCode, you are probably used to a high level of support when writing Go code. If you try to edit locally (ie. outside of your project), your IDE may not have the proper context to provide you that support. The &lt;code&gt;--edit&lt;/code&gt; option enables you to easily open the command source within the project directory in your favorite editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ goscript --edit greet                                                    

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

&lt;/div&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%2Fhaxq1lqpkfrf39yq232p.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%2Fhaxq1lqpkfrf39yq232p.png" alt="VSCode_greet" width="763" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can then edit the file to take a command-line argument and recompile. You can recompile a specific command simply by passing the &lt;code&gt;--name&lt;/code&gt; option, or all commands using &lt;code&gt;--recompile&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;&amp;gt; $ goscript --recompile                                                     

&amp;gt; $ greet World                                                               
Hello World!

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

&lt;/div&gt;



&lt;p&gt;If you prefer, you can &lt;code&gt;--export&lt;/code&gt; the greet command as a script, complete with a working shebang line (similar to the &lt;code&gt;--cat&lt;/code&gt; example shown above). This will also do a "soft delete" in the project, removing the binary but saving a copy of the source without the .go extension, making it effectively invisible to the Go compiler. That renamed source file will be shown if you &lt;code&gt;--list&lt;/code&gt; commands, pointing out the option to &lt;code&gt;--restore&lt;/code&gt; the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ goscript --export greet &amp;gt; greet.gs                                                                                                                     
&amp;gt; $ goscript --list                                                         
hello
greet (requires --restore)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can modify the permissions on the "greet.gs" file we just created and execute it as a script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ chmod 744 greet.gs                                                                                                                                  
&amp;gt; $ ./greet.gs Shebang                                                         
Hello Shebang!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to use a package outside Go's standard library, there is a &lt;code&gt;--goget&lt;/code&gt; option to pull it into the project. However, since Go's package convention is geared toward online repos (e.g. github), &lt;strong&gt;Goscript&lt;/strong&gt; will often be able to automatically &lt;code&gt;go get&lt;/code&gt; external packages that are imported, adding them to both the go.mod file and the imports.json file. &lt;strong&gt;Goscript&lt;/strong&gt; will also run &lt;code&gt;go mod tidy&lt;/code&gt; to clean up go.mod when using the &lt;code&gt;--export&lt;/code&gt; or &lt;code&gt;--delete&lt;/code&gt; options. &lt;/p&gt;

&lt;p&gt;As an example, let's write a simple uppercase utility that imports the github.com/bitfield/script package. We can write this outside the project in a file called "tmp.go" (Note, the .go extension isn't required).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "github.com/bitfield/script"
    "strings"
)

func main() {
    script.Stdin().FilterLine(strings.ToUpper).Stdout()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use &lt;code&gt;--file&lt;/code&gt; and &lt;code&gt;--name&lt;/code&gt; to import the code to the project with the name "upper".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; $ goscript --file tmp.go --name upper

&amp;gt; $ echo uppercase | upper                                                    
UPPERCASE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing the code demonstrates that the external package was added, but we can also view the updated go.mod file using the &lt;code&gt;--dir&lt;/code&gt; option to reference the project location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ cat `goscript --dir`/go.mod                                               
module goscripts

go 1.22.1

require (
    github.com/bitfield/script v0.24.1 // indirect
    github.com/itchyny/gojq v0.12.13 // indirect
    github.com/itchyny/timefmt-go v0.1.5 // indirect
    mvdan.cc/sh/v3 v3.7.0 // indirect
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise, the imports.json file now includes a mapping for "github.com/bitfield/script" to support automatic import with the &lt;code&gt;--code&lt;/code&gt; option when using the alias "script".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ cat `goscript --dir`/imports.json                                        
{
    "script": "github.com/bitfield/script"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, as you can see from that last example, bitfield/script makes it easy to write commands that can be combined in a pipeline just like built-in Unix utilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; $ ./greet.gs Pipes | upper                                                  
HELLO PIPES!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Scripting in Go is fun and powerful. &lt;strong&gt;Goscript&lt;/strong&gt; can make it more convenient to use Go for scripts. To get started, visit the repo at &lt;a href="https://github.com/fkmiec/goscript" rel="noopener noreferrer"&gt;https://github.com/fkmiec/goscript&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
