Hacker News new | past | comments | ask | show | jobs | submit login
Gooey: Turn almost any Python command line program into a full GUI application (github.com/chriskiehl)
769 points by lsferreira42 on Dec 9, 2023 | hide | past | favorite | 118 comments



Hey, what the -- this is my thing. ^_^ What's it doing at the top of HN?

A quick reply to some of the comments about argparse. Gooey is super old at this point. Argparse was a solid choice at the time when Gooey started. These days, Gooey itself speaks in JSON and is decoupled from argparse itself. However, argparse remains the main "blessed" interface (mostly because nobody else has built a different one).

Some fun FYIs: You can also invoke any arbitrary executable[0], not just python, which is pretty handy.

Re: last commit being 2 years ago. It gets harder to justify working for free on niche software as you get older and priorities change :( If it's any consolation, I DO feel guilty all the time. I have no idea why, but where I live, there's "GOOEY" graffiti tagged all over the place, so it's a nice ever-present reminder of the issue tracker that's currently going unloved. haha.

[0] https://chriskiehl.com/article/gooey-as-a-universal-frontend


Argparse is still a pretty solid choice, because it's so ubiquitous and well documented and fairly easy. Typer and Click are both very nice, with some good ergonomics, but I find Typer's "tutorial" style documentation to be rather hard to search to find answers to things like "What arguments does Typer.App() take?"

I have a program I'm working on right now that does user-initiated argument parsing, and argparse is a great fit for it. I'd love to have a text-based UI as an option to drop users into, but Textualize requires Click (IIRC), and using Textual directly in my code to create the UI I've spent hours on and had absolutely no luck even getting started.


Argparse also does not require tens of external libraries.


That right there is the real winner. I already get queasy when my dependency list gets too long. Invoking an extra collection for what is mostly developer quality of life is not a trade-off I like to make.


Notably, argparse is way faster than click/typer. If you just need a few —options it’s probably preferable.


While Typer looks nice, I found it to be annoying. It outputs everything depending on the width of your terminal emulator with spaces instead of newlines. Not sure who thought that was a good idea, but try copy pasting any output of it in any chat or anywhere that is not the same width in chars as your terminal emulator. The output becomes complete shit and unreadable. The second thing is, that it forces you to adhere to its paradigm of being a global mutable state object, instrad of being passed around neatly like argsparse, which makes code less understandable and tests needlessly more complicated.

Overall I have found it to be very much not worth it adding typer as a dependency. Hard pass.


On the other hand, I've switched to using Typer for most of my argument parsing because it's not an object I have to pass around. It lets me have the arguments co-located with the code, which is convenient. Especially for more complicated argument parsing, like one of my commands for our deploy process which has maybe 15 sub-commands, that sort of parsing with argparse is kind of a nightmare.


The solution to this kind of issue is something like parameters (See for example https://www.gnu.org/software/guile/manual/html_node/Paramete...). They are also thread safe. One can easily set them in tests without having to mock things. I am not sure it is possible to even have something like this in Python. Have not seen it anywhere in Python.

> Passing arguments to functions is thread-safe, but that soon becomes tedious when there’s more than a few or when they need to pass down through several layers of calls before reaching the point they should affect. Introducing a new setting to existing code is often easier with a parameter object than adding arguments.

But also, if you really wanted to, you could set the argsparse object to a global variable and then import it everywhere else. So that is not a limitation.


My issue with argparse isn't that it's not global, it's that you have to create sub-parsers for multiple commands, and then add arguments to those subparsers. Those parsers are all typically defined in a central location, but copying arguments between those parsers as I define new commands can get them jumbled up because the sub-parser comes along with the argument:

    sub1 = [create subparser]
    sub1.add_argument('-x')
    sub2 = [create subparser]
If I copy "sub1.add_argument" and put it under "sub2", and forget to change "sub1" to "sub2", it is a hard to track down bug. I've had this happen a lot as the parser gets more complex.

Typer completely eliminates this potential bug, because the arguments are defined as type annotations in the sub-command function itself.


Gee if only there was a way to reuse logic within a program.

> arguments are defined as type annotations in the sub-command function itself

So you duplicate logic in your type definitions instead of as instructions. Whatever makes you happy i guess.


This is a really cool idea. I love interface disconnected from APIs. We have so many annoyances these days because applications can't be programmatically controlled. Honestly, I'd like to see legislation saying all application functionality needs to have APIs.


I think legislation demanding most tools have an API would be a good thing. Not 'tho shalt expose a REST endpoint'. But instead something like 'every operation a user can do with this tool, they also need to be able to trigger with an interface that is programable, and that interface needs to be documented'.

Saying 'our programable interface is the gui, use autohotkey' is fine, as long as you properly document all click regions.

This would be a massive productivity boost to anyone using such tools. It would also be great for disabled people.


I would not like to have to concern myself with exposing government-compliant APIs when coding any arbitrary tool...the free market can reward good development.


> the free market can reward good development

ha ha

No way, especially because all the people taking most market-business-related decisions (eg which software to buy) are not tech-oriented. If we had more power on these decisions, that would mean that development, and even advertising of products, would be closer to what the parent comment suggest. But alas.


> the free market can reward good development.

Markets cannot regulate nuanced behavior like this. Microsoft is a trivial example of anti-user practices and generally garbage design nonetheless being adopted due to their tremendous efforts of corporate propaganda and scaremongering the decision makers about their products.


> Honestly, I'd like to see legislation saying all application functionality needs to have APIs.

The security implications of this give me heart palpitations.


The opportunities for abuse are manifold.


This is true, but the abuse would still be possible today if someone is reverse engineering software or talking to servers where everything is over APIs anyway. I'm talking about local interface decoupled with a local API from implementation. The problem today is that programmers can't compose or build software on top of other software they have.


> I'm talking about local interface decoupled with a local API from implementation.

To expose this "local API" usefully, you must either:

1. Share memory with other processes (new attack vector), or 2. Listen on some kind of network or native socket for messages and authn+authz the commands that come through it based on some security protocol (new attack vector).

The value proposition of an API is to allow control and data flow between an application and some external entity. It seems to me that it has security implications by definition.


Maybe think of incentives rather than legislation


Hey! Cool project! I have a question: why do you dump out sys.argv to a local file in the CWD? [0] tmp.txt is hardly a unique name… or am I missing something?

[0] https://github.com/chriskiehl/Gooey/blob/be4b11b8f27f500e732...


Seems like it's potentially used for debugging, especially given that pycharm apparently appends additional params when invoking a new process (as noted in the comment at the top of the file).


> These days, Gooey itself speaks in JSON and is decoupled from argparse itself.

This sounds cool. I saw the headline and before clicking anything, my first thought was "bet this heavily depends on argparse", so this is surprising - in a very nice way.

I'm a hardcore getopt fan, mostly because I believe the developer's convenience is nowhere as important as the convenience of the user, and the user shouldn't need to care what programming language or option parsing library the developer chose. argparse, Click, Go's flag/X11-style, and many other similar libraries break conventions that are ingrained in half a century's collective muscle memory.

But with a layer in the middle, it sounds like you can eat your cake and have it too.


> Gooey is super old at this point.

It's only super old because you abandoned it (and I don't mean to be judgemental, it is what it is). Worse yet, no viable alternative has shown up to replace it nor either of its forks gained traction.


No its super old cause it was created a long time ago? Why dont you go update it or make a free up to date version? Why do people act like software creators owe the world something?


And Python itself was released in 2000! No wonder everyone has abandoned it these days, it's ancient!


Thank you for your work, awesome software.

I'm wondering if there's a way to use python-fire instead of argpraser with gooey?


Graffiti?? Where do you live? Any pics of it?


Presumably Seattle; Gooey is a prolific tagger. This appears to be their instagram: https://www.instagram.com/gooeygue/


Shouldn't this be qualified with "argparse-based"?

Argparse is good for simple stuff but there are many Click based CLI's and a lot of popular CLI libraries build on top of Click. There are also other Python CLI tools that aren't built on argparse or Click, though I will say that these two are probably the most popular ones.

Is this confirmed to work with Click? I only see references to argparse. I would go so far to say, if the answer is no, that "almost any" is a flat out lie, and a much more accurate title would be "Turn almost any argparse-based Python command line program into a full GUI application".

Also, the last substantial commit was over two years ago. This isn't itself a bad thing, but given the open issue count does not really signal confidence in the project.

Otherwise it is a cool project. I would like to see more of this - it's one of those neat force multipliers, as referenced in the README, that some enterprising person could implement as a CLI and then share their automation for the rest of the nontechnical office in an easy way. Kind of like how Access did the same thing for DB's. Like Access, you would butt up against limitations once you started to introduce some level of size or complexity, but it could be "good enough" for a lot of small office use cases.


I'm curious about the deficiencies you see in argparse... my bias is to minimize 3rd party dependencies ...


I was genuinely seeking feedback. I use argparse regularly. I have found it somewhat difficult to use when creating nested subparsers. That Click is part of the The Pallets Project gives me more confidence in it being maintained indefinitely, but ...


I used it for exactly this in my previous role. I automated a lot of tasks and built tools for my previous team. Most of them weren't Python programmers so I used gooey to create simple GUI's on top of my scripts. It worked really well.


Mind you give some examples? curious.


One does not need to be a $lang programmer to use a CLI tool written in $lang.


What can't you do with argparse exactly?


[flagged]


We've banned this account for breaking the site guidelines frequently and ignoring our requests to stop.

If you don't want to be banned, you're welcome to email hn@ycombinator.com and give us reason to believe that you'll follow the rules in the future. They're here: https://news.ycombinator.com/newsguidelines.html.


That would also allow to get yourself exported, instead


It does? Could you explain why you think that?



The author’s comment actually confirms that it doesn’t currently support anything else other than argparse though. The author says they wrote it to be generic enough to extend to other libraries easily, which is great, but that is not the same at all as currently supporting said libraries. They provided a link that said it supports any cli, but when you follow the link, the instructions tell you to implement an argparse compatible wrapper for your cli in Python, which of course, is supporting argparse


Sure, I was talking about the workaround mentioned here:

> You can also invoke any arbitrary executable [https://chriskiehl.com/article/gooey-as-a-universal-frontend], not just python, which is pretty handy.

Rhetorics aside, you can use Gooey for any CLI tool using a small Python glue (pardon the pun) code, so it was not a flat out lie.


I know we are in semantics land now but most people would probably say that shelling out to another process doesn’t really constitute an integration. Put another way, you could just say that you could easily turn any CLI into a simple Python CLI with only a few lines of code with argparse itself, and that argparse supports any other CLI by just wrapping it, removing mentioning the Gooey part entirely. You’re essentially describing just the benefits and drawbacks of Python’s subprocess and argparse libraries at this point and not really saying anything about Gooey aside from the fact that it is argparse compatible.

In other words: “Hey look at this cool thing argparse can do, and because Gooey is basically api compatible with argparse, it can do it too!” And don’t get me wrong, I think Python’s expressiveness with the argparse library and in general its ability to make CLI’s in very few lines of code is great. But really the magic is argparse and Python in that regard.


> I know we are in semantics land now but most people would probably say that shelling out to another process doesn’t really constitute an integration.

Most people would be an exaggeration. Purists may think that, but the reality is most GUI wrappers use subprocessing.

While I agree that click integration would be nice, how would you turn any CLI tool to a GUI application without shelling out?

> But really the magic is argparse and Python in that regard.

True, but this is simply semantics. If I submit a PR to the Gooey project that lets you write a YAML configuration file to declaratively document the interface of a CLI tool, then automatically convert that config file to Python source, would that be any different? Is it because it's YAML you manually write and not Python? Or even something that uses ChatGPT to convert a man page to an argparse wrapper? The argparse is the trivial part. The real magic is Gooey.


... That comment proves you wrong.

There is no extant non-argparae integration


Related:

Gooey: Turn almost any Python command line program into a GUI application - https://news.ycombinator.com/item?id=27490291 - June 2021 (115 comments)

Gooey: Turn command line programs into GUI applications - https://news.ycombinator.com/item?id=8218785 - Aug 2014 (74 comments)


I wish that the OS and shell had better insight on how to run programs without need for specific library parsing libraries.

I'd love to see programs communicate through a typed JSON/proto format that shed enough details to make this more independent, and get useful shell command structuring/completion or full blown GUIs from simply introspecting the expected input and output types.

Today it seems that the best you can get is still made out of carefully placed straws as programs need to export completion files to many shells, there's vastly different styles for flags across programs and parsing libraries, and obviously, there's no GUIs around.


Now you have a thing called powershell. Though as more serious answer plan9 was probably the only OS that really tried this.


Is there anything good Plan 9 hasn’t tried? I feel like every time I hear about a good OS idea, someone brings up Plan 9. Haha.


Kind of like some generic gRPC interchange/CLI API with native OS support? Something like that could be neat. I conjecture the main problem with gRPC is that a lot of developers (myself included) find dealing with it a bit unwieldy compared to more native (by native I mean in-language) solutions.


If you look into IPC primitives in each OS you can find goodies that do expose structured metadata about what interfaces are available and how they can be called. D-Bus, sd-bus, COM, Binder, to name a few.

It’s just that the tooling around it isn’t as easily exposed and they aren’t tailored for on-demand launch via command line. If the shell treated such as a more first class citizen, good results may come out.

Another big problem is portability, if you designed your app with sdbus, it’s not going to work on a non systemd distro, even less on Windows. What’s needed is a standardized abstraction layer on top.


> I'd love to see programs communicate through a typed JSON/proto format that shed enough details to make this more independent, and get useful shell command structuring/completion or full blown GUIs from simply introspecting the expected input and output types.

You should try PowerShell. It's basically Microsoft's .NET ecosystem molded into an interactive command line. I'm not entirely sure if PoweShell can make full use of the static types that build up its core, but its ability to exchange objects in the command line is almost unmatched.

On Linux you can use `jc` (https://github.com/kellyjonbrazil/jc) combined with `jq` (https://jqlang.github.io/jq/) to glue together command lines, but that's still two extra steps you need to deal with compared to PS's built-in capabilities.


I don't have a windows machine and I don't plan on having one.

I didn't know of `jc`, but it seems that using nushell (https://github.com/nushell/nushell) gets you a better experience.


PowerShell is available on macOS and Linux as well (source on Github: https://github.com/PowerShell/PowerShell). It may not be as well-integrated with things like system services management, but the language still works well. You can still use all the command line tools you're used to on Linux, of course.

nushell does look interesting, though the lack of a .deb repository does put it pretty low on my to-do list.


I sometimes find GUIs equivalent to comfort-food as you can just stroll through a gui interface without lot of cognitive overload that may come from a rarely used CLI.

A bit tangential to current discussion, but i came across CUDATEXT editor a few months ago here which provides a single file python API to let me use arbitrary GUI elements like MENU, INPUTS etc which editor is itself using. I currently generate my blog from editor itself with configuration done through these simple GUI elements.


See also:

"Textual: lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser." [1]

[1]: https://github.com/textualize/textual/


They have something similar to Gooey as well: https://github.com/Textualize/trogon "Easily turn your Click CLI into a powerful terminal application"


Wow, how is that even possible? The terminal examples are way more detailed than I would have imagined possible.


Yeah that's interesting. I didn't think handling mouse clicks was possible. Wonder how it's done.


A lot of popular terminal apps support mouse clicks. Off the top of my head vim, emacs, htop, and links2 all have mouse support.


for most xterm-compatible terminals, you send an escape sequence that enables mouse tracking, and then mouse clicks turn into escape sequences.


That's cool! Thanks


Adding Textual support to camply [1] was apparently very easy. I didn't to the implementation; I just contribute to the project sometimes: https://juftin.com/camply/command_line_usage/#tui

[1] https://juftin.com/camply/


Hey, I just want to say thanks for making this wonderful piece of software! I love gooey and have used it extensively for several different programs. For me, it perfectly fits this area where you have a python script that does something important, and now you need to set it up so that non-programmers can use it as well.


This reminds me naked objects. The idea was that you only define Java classes with some annotations + theme and the whole GUI (or web frontend) application will be generated for you.

Very cool idea but it never worked out (to my knowledge).


Django has a similar philosophy: define your models and they are reflected directly into database tables and you can auto-generate forms using them.

IMO, the trouble is that it couples vertical concerns (presentation, domain, infrastructure). It's fine as long as the domain model has trivial presentational and database representations.

However, if you want to make a complex interface with many convenience features, you'll have to let those requirements bleed into your domain layer; and if want to create complex domain models, it's impractical to enforce invariants at the language level (since anything with a reference to a Model can do arbitrary things to it).


I would love something that could do the reverse.


I would like to be able to use a gui to set up parameter sweeps based on info pulled from argparse and then convert back to a shell script that runs and saves the output sensibly.


I'm trying to solve the part of the problem that generates the output, the argparse part would not be that hard to write.

https://github.com/blooop/bencher/tree/main


Not quite; turn any GUI application into a Python command line program.


This feels maybe possible with QT. Since the inputs are all defined in code.


A WYSIWYG editor that spits out a CLI you mean? That would pretty neat, though I think would necessarily be kind of constrained. I wonder who has tried that approach, I can't think of any examples


Actually, something like a "zotero for argparse" would be cool. Where you enter arguments, their type, help string, defaults etc in a gui and then you can check the ones you need for a given python script and copy the relevant python code into your paste buffer.

I don't think it would be a massive time saver however what I usually do now is find some previous script that had similar arguments and copy them, and then copy-paste-edit to add new arguments.

The other advantage is you could enter the arguments agnostically and export as whatever language you're working in.


http://docopt.org/

Not quite what you asked for, but close: type example invocations to generate the CLI, and just pull the arguments from a dictionary at runtime.


Chatgpt soon probably!


how? you're going to modify the binary so that it can accept command line parameters? or clone the GUI's functionality in a CLI? that's akin to just creating the application from scratch.


With the old Macintosh Programmer's Workshop (MPW; a text-based shell for Mac OS of the 80s and 90s) there was similar functionality called Commando for almost every command. The commando information was kept in a 'cmdo' resource. Something similar could be done today with extended attributes, if support wasn't so hit or miss.

Oh, apparently, A/UX had commando as well. If you double-clicked a terminal command from the Finder, it would pop up the commando box to choose your CLI options, then run it in a shell window. Today, running a terminal command from Finder just runs it without any arguments in a shell window.

https://cohost.org/boredzo/post/804893-i-still-want-a-moder

http://toastytech.com/guis/aux3.html


Wow, what a nice coincidence to see this on HN! Just two days ago, I was hacking up a similar project. https://github.com/livetheoogway/python-uime This one is a much smaller hack to spruce up your local scripts. Although it's still a work in progress with features pending, I'd really appreciate any initial feedback or thoughts. Thanks for checking it out!

[0] https://github.com/livetheoogway/python-uime


Motion


There are also similar applications for usage with clap-rs.[1][2]

[1]: https://github.com/MichalGniadek/klask

[2]: https://github.com/grantshandy/claui


How would one integrate this with a CLI tool that expects some user input during execution?

Would love to package this around a bisect script I use to debug issues for my game engine. Giving it a GUI would make it possible to share it with users such that they too can help bisect problems.


there's a near complete isomorphism between cli/tui arg parse and web url routing

someone is surely doing a smalltalkish metaclass trick to turn any object into a local tty or http or rest or else interfaced thing


When all you have is a web framework, everything looks like an url.


Anything that can be handled by a compiler can be hacked to interface with anything that can be handled by an interpreter. That’s the kind of fundamental daoist “code is data is code” that underlies the power of computing.


It also turns out that code is mathematical proofs and proofs are code, thanks to the Curry-Howard isomorphism. https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspon...


yeah but so far these are all separate microcosms with no clear common model


Did something similar with my pokemon emerald randomizer. This parses output of wasm/wasi program's --help output and generates a web interface https://cloudef.github.io/pokeemerald-randomizer/ the aruments are then passed to the wasi/wasm binary to generate the final rom.


I wonder if Gooey could be made to target generating a React or even JS-free vanilla web app, instead of a native GUI?

In spirit, Gooey reminds me of one of my favorite low-code tools for technically savvy individuals to put a web frontend in front of arbitrary CLI programs:

Python Script Server

https://github.com/bugy/script-server


Suggesting a look at this hack of mine, which I was working on over the weekend https://github.com/livetheoogway/python-uime


“Instead of a native GUI, let us launch an entire browser” is how we got 100+ MB Hello World apps.


Hey SGarland, thanks for replying!

Launching it only on demand is an interesting idea, and I totally get your sentiment on bloat. I was a 90s teen, 32MB of ram was enough for just about everything at the time, while today that's "embedded" territory, haha. Still, these days my web browser is generally already open.

Anyhow, maybe my writing could have been more clear. I was thinking of it differently, running the app as a persistent webserver. Then I could access the things from anywhere. "Accessible from any web browser" is one of the primary properties I like about the Python Script Server (mentioned/linked in my first post).

Just imagine if someone somehow figured out how to make a Gooey equivalent for Go or Rust. If done well, it could become very popular. Especially considering the difficulty of creating UIs in those languages! Much more challenging than Python.


Ok, a webserver I could get behind, yes. It’s everything being made into Electron apps that bothers me. Spotify takes up well over 1 GiB of RAM, and for what?


When it's launching a new tab in an existing browser it's rather less overhead, and also tends to be convenient in a way nothing I've dealt with other than Tcl/Tk is.

(notably Tcl/Tk deals with remote X over ssh nicely and far too many things these days don't so much)


See also: Zenity, KDialog and GNU Dialog.


Nice.

Now we'd like the converse program: one that transforms any GUI application into a cmdline tool or wraps it. ;-)


Is there an counterpart tool for ffmpeg with those parameters in GUI? That would be an omnipower app...


The Handbrake suggestion is a good one if your only interest is transcoding ... which barely scratches the breadth of what ffmpeg as a tool can do.

Try: https://amiaopensource.github.io/ffmprovisr/

for a 'better' ffmpeg CLI documentation, your mileage may vary, it's task and example focused.

Try: https://github.com/topics/ffmpeg-gui

for 66 variations on a GUI for ffmpeg of which I have no comment, I'm an old school CLI user through and through.


There are gajillions of ffmpeg UIs like Handbrake. But for me, more oftan than not GPT is the fastest way.


Try Handbrake!


And then there is me who tries to fight with all my clients to have their GUI friendly applications to, at least, have command parameters, so that it can be automated through services/task scheduler/cron


Would be nice to combine this with Google Fire: https://google.github.io/python-fire/guide/


Does this only build Windows applications, or can it do the same for MacOS/Linux?

be great if you could build/package python code easily to run on native OS's without having the user install python, etc first.


It works a treat on those other operating systems and pairs well with pyinstaller to make a single executable.


There is PyInstaller, cx_Freeze, etc. for that.

I've used PyInstaller to create standalone Windows EXEs for simple programs like command-line utilities, and even for simple wxPython GUI apps.

Worked well, although I've read that there may be some issues for more complex or bigger apps.


Reminds me of this previous HN submission Blotato: https://news.ycombinator.com/item?id=38206235


Cool! I've wanted to write something similar to turn a python cli into a web app, something like those sites that convert file types but general purpose.


Suggesting a look at this hack of mine for web apps https://github.com/livetheoogway/python-uime


I've wondered about doing something like this in C++ with imgui and boost program_options.

I'm very happy to see an example of it already done in Python!


Generating a graphical form for the options and arguments does not turn a command line program into "a full GUI application".


Very happy to see something like this! Wish it had been around years ago to save me the hours I spent wrangling gui2py


Python getting a lot of love on HN recently.

>Feels good man


Does this work with any OS?


So is it a kind of Swagger for command line apps?


That's incredible


looks pretty neat honestly to make ur programs more easily accessible. gui programming is always such a mess!. hunter42 :').


"Almost any Python command line program" seems to be an exaggeration. It relies on the command-line program using argparse, and explicitly doesn't work for any that rely on optparse, which, sure, is older, but also means that things which rely on the popular Click command-line library won't work either.


> which, sure, is older

And deprecated for going on 11 major versions of Python.


Which is arguably a good reason Click should look for an alternative basis (though, OTOH, the reasons Click remains on optparse are, arguably, a reason that optparse, while it perhaps should not be further developed but for bug fixes, should not be considered deprecated), but in fact a lot of Python command-line programs depend on Click, so something that only works on argparse-based programs does not, in fact, support "almost any Python command line program".

Interestingly, there is a gooey-inspired GUI generator for Click-based programs: https://github.com/szsdk/quick




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: