{"id":41893583,"url":"https://github.com/lordofscripts/goapp","last_synced_at":"2026-06-11T18:00:31.264Z","repository":{"id":332813665,"uuid":"1134596015","full_name":"lordofscripts/goapp","owner":"lordofscripts","description":"A small collection of reusable packages and utilities suitable to rig up a new Go application","archived":false,"fork":false,"pushed_at":"2026-06-09T20:51:26.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T22:19:25.490Z","etag":null,"topics":["cli","go","golang","golang-library"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lordofscripts.png","metadata":{"files":{"readme":"docs/README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"lordofscripts","patreon":null,"open_collective":null,"ko_fi":"lostinwriting","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":"lostinwriting","custom":null}},"created_at":"2026-01-14T23:49:07.000Z","updated_at":"2026-06-09T20:51:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lordofscripts/goapp","commit_stats":null,"previous_names":["lordofscripts/goapp"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/lordofscripts/goapp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordofscripts%2Fgoapp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordofscripts%2Fgoapp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordofscripts%2Fgoapp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordofscripts%2Fgoapp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lordofscripts","download_url":"https://codeload.github.com/lordofscripts/goapp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordofscripts%2Fgoapp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34211067,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","go","golang","golang-library"],"created_at":"2026-01-25T14:14:47.025Z","updated_at":"2026-06-11T18:00:31.231Z","avatar_url":"https://github.com/lordofscripts.png","language":"Go","funding_links":["https://github.com/sponsors/lordofscripts","https://ko-fi.com/lostinwriting","https://buymeacoffee.com/lostinwriting"],"categories":[],"sub_categories":[],"readme":"# Go App v1.4 - Spice up your GO applications\n\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/lordofscripts/goapp)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lordofscripts/goapp?style=flat-square)](https://goreportcard.com/report/github.com/lordofscripts/goapp)\n![Build](https://github.com/lordofscripts/goapp/actions/workflows/go.yml/badge.svg)\n[![Go Reference](https://pkg.go.dev/badge/github.com/lordofscripts/goapp.svg)](https://pkg.go.dev/github.com/lordofscripts/goapp)\n[![GitHub release (with filter)](https://img.shields.io/github/v/release/lordofscripts/goapp)](https://github.com/lordofscripts/goapp/releases/latest)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\nWhen I was developing on the Microsoft Windows OS, I was a hard-core \nMicrosoft .NET developer. I lived and breathed *.NET* and *Visual Studio*.\n\nHowever, a few years ago I sort of abandoned Microsoft Windows as my main\ndevelopment platform. I did what was sensible, I returned to my roots: Linux.\nI had been a Linux-based OS developer since its early versions, prior to\nkernel 1.0 when you basically had to construct the car before you could\ndream of driving it. Back then I used C, C++ and Java, plus a lot of\nscripting languages, Perl was my favorite.\n\nWhen I returned to my Linux roots, I found out .NET (Mono) was neither\nstable nor viable serious alternative on Linux. I learned Python, but\nI must say I dislike interpreted languages.\n\nBut then I discovered Go (somewhat late I must say!) and I have been\ndoing a lot of Go development ever since! I write a lot of command-line\napplications, some GUI (using Fyne) too. But one thing was obvious, I\nfound myself needing the same things over and over again, so why not\nbundle them in a single module and rewire my applications to use this\nsmall contribution instead? I finally decided to it when developing\n*Go CaesarDisk* , so here it is.\n\n*This is stable but still work in progress as I move reusable code\nfrom some of my applications into this Go module.*\n\n## Install\n\n\u003e go get github.com/lordofscripts/goapp@latest\n\nRequirements:\n\n* GO `v1.21`\n\n## Features\n\n* There are several constructors in the `app` package to declare your\n  software version. It follows *Semantic Versioning* allowing for\n  Alpha, Beta, RC and (final) releases.\n* Your choice of enhanced, non-structured logging packages: `app/logx`\n  or `app/mlog`. These are enhanced versions of the standard `log`\n  and `log/slog` packages. Or also level-agnostic colored logging.\n* Multiplatform utility functions such as `DirExists` and `FileExists`,\n  others will be added as I see fit.\n* Assertion functions: `Assert*()`\n* Peaceful Death functions when your app needs to rest in peace: `Die*()`\n* Check whether your input is from a pipe: `IsPipeInput()`\n* Obtain a platform-agnostic configuration directory: `GetConfigDir()`\n  and ensure it is present or created for your application: `EnsureConfigDir()`\n* custom flags for the `flag` standard package: `flagx.RuneFlag`, \n  `flagx.ByteFlag`, `flagx.StringsFlag` and `flagx.DateFlag`  \n* A convenience function to detect **piped** input for Linux/Unix apps.\n  If you are debugging piped tests in VSCode, set the environment\n  variable `DD_PIPED_INPUT=1`.\n* Platform-agnostic `app.IsHiddenFile()`\n* A `app.Warning` object that implements `error` interface and user\n  can customize the `app.WarningCode` as an enumeration. See example.\n\n### Logging\n\nYou have two choices of enhanced logging ready to use:\n\n* [MLog](./MLOG.md) for tagged, logging like the standard `log/slog` but\n  with extra tags and support for logging levels, or\n* [Colored MLog](./MLOG.md#colored-logging) is a variant of MLog that\n  always logs to a colored console, it supports log levels by prefixing\n  them but the output happens *regardless* of the actual log level.\n* [Logx](LOGX.md) preformatted logging with call-tree support, it was\n  instrumental to get one of my Fyne GUI applications to work.\n\n### Command-line applications\n\nFor declaring your application/package versions:\n\n```go\n const BASE_VERSION string = \"1.3.2\"\n const REVISION int = 8\n For Alpha version v1.3.2-Alpha.8\n pver := app.NewAlphaVersion(NAME, DESC, BASE_VERSION, REVISION)\n For Beta version v1.3.2-Beta.8\n pver := app.NewBetaVersion(NAME, DESC, BASE_VERSION, REVISION)\n For Release Candidate version v1.3.2-RC.8\n pver := app.NewReleaseCandidateVersion(NAME, DESC, BASE_VERSION, REVISION)\n```\n\n\u003e For final release version v1.3.2\n\u003e pver := app.NewReleaseVersion(NAME, DESC, BASE_VERSION)\n\nGetting the version number as displayed above:\n\n\u003e pver.Short()\n\nThe app name plus its version number:\n\n\u003e fmt.Println(pver.String())\n\nOutputting your application copyright on the CLI:\n\n\u003e app.Copyright(\"Jan Knowsalot\", '\\u2615')\n\nOutputing your [Buy Me a Coffee](https://buymeacoffee.com/lostinwriting)\nprofile URL:\n\n\u003e app.BuyMeCoffee(\"lordofscripts\")\n\nThen, should your application need to rest in peace:\n\n```go\n  const EXIT_CODE int = 5\n  app.Die(\"bad thing happened\", EXIT_CODE)\n  app.DieWith(EXIT_CODE, \"%d bad things happened\", 3)\n  app.DieWithError(err, EXIT_CODE)\n```  \n\nAnd there are a few more utility functions. Please check the package\ndocumentation.\n\n### Application Configuration\n\nThe package has built-in utility functions to let your application\nuse an application configuration file in a platform-aware fashion.\nThus, it works on MacOS, Windows and Linux but the directory where\nit resides varies depending on the OS. There are several functions\nbut the one that makes use of all of them to accomplish all tasks\nin one is:\n\n```go\n const ORG_NAME string = \"acme\"\n const APP_NAME string = \"coyote\"\n const CONFIG_FILE_EXT string = \".json\" // or .yaml or .ini\n configFile, err := app.EnsureConfig(ORG_NAME, APP_NAME, CONFIG_FILE_EXT)\n```\n\nEven when an error happens, the `configFile` return value will always\nhave the expected fully-qualified name of the configuration file.\n\nThe configuration *directory* varies per OS:\n\n* **Linux \u0026 Unix**: `~/.config/ORG_NAME/APP_NAME`\n* **MacOS**: `~/Library/Application Support/ORG_NAME/APP_NAME`\n* **Microsoft Windows**: `C:\\\\Users\\USERNAME\\APPDATA\\ORG_NAME\\APP_NAME`\n\nThat path minus the `ORG_NAME/APP_NAME` part can be obtained by\ncalling `app.GetOSConfigDir()`.\n\nTo obtain the main configuration file:\n\n\u003e `cfgFilename, err := app.EnsureConfig(ORG_NAME, APP_NAME, CONFIG_FILE_EXT)`\n\nBut if you have several configuration files in addition to the main,\nfor example `coyote_templates.json` you could use:\n\n\u003e `cfgFilename, err := app.EnsureConfigWithSuffix(ORG_NAME, APP_NAME, \"_templates\", CONFIG_FILE_EXT)`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flordofscripts%2Fgoapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flordofscripts%2Fgoapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flordofscripts%2Fgoapp/lists"}