loading...
Cover image for Shareable CLI demo?

Shareable CLI demo?

deciduously profile image Ben Lovy ・2 min read

Hi folks!

Over the weekend I was enlisted to produce a proof of concept demo, to pitch as part of a project proposal presentation. Perfect!

I did so, and they're happy (pleased?) with the result. The demo I've produced is a CLI application that reads an input file from the filesystem specified at runtime. It outputs to stdout and takes input from stdin. Very barebones demo. I implemented this program in Rust, and suffices for this purpose. They are planning to screenshare during the presentation to show off the capability.

However, it would be ideal if there were some way to share this demo easily - they could just provide a URL and get something to play with.

Options I've considered:

1) Refactor into a WASM module, build a very simple JS webapp with DOM elements for inputs and outputs. I've started doing this, but it's non-trivial.
2) Throw the whole thing on a DigitalOcean droplet and let people ssh to the box.
3) Re-implement the whole thing in JavaScript.

I will not be doing #3, this demo has a total useful life of a single day, and it's not worth the effort. If the project is picked up, we're starting from scratch.

I did take a stab at #1, but it's not straightforward. I hadn't anticipated this need, so it's not a completely straightforward refactor to also not break the current stdout/stdin functionality. I think this is the nicest option, but it is not simple to produce from my current code in one day. With a little more time, this is absolutely what I would do, but I don't want to rush it.

That leaves me with #2, but I don't really know how safe or reasonable that is. What I'm thinking is that I'd just pop the compiled executable on a droplet with all the demo input files there ready to go, and then users could log in remotely and execute from there. Is that horrendous?

Pressure is low - what I've produced to date will be fine, this is a nice-to-have that would be great to deliver. I've only got this afternoon to pull it together, though, so complexity needs to be low.

How would you solve this problem?

Aside: one of my first ever billable pieces of work was in Rust and I am just over the moon about that.

Photo by Thomas Jensen on Unsplash

Posted on by:

Discussion

pic
Editor guide
 

If it's reading from stdin and spitting out on stdout...

Option 4

... can't you just hook it up to a route on a web server?

That way people could 'demo' it using curl.

Or you could build a thin web frontend using a smidgen of vanilla JavaScript.

 

I could if it were just crunching an input and spitting an output, but it runs the user through a series of interactive prompts. I don't think curl is suited for this, could be wrong?

 

Yup, curl won't cut it.

Are the prompts for 'configuration' only? If so you could still stick it on a server, but take some querystring params for the options (built into a web page UI), then do the major work server side.

Another option... perform the interaction over TCP instead of HTTP - now you can use netcat to demo it.

Another option... perform the interaction over TCP instead of HTTP - now you can use netcat to demo it.

(I like this idea so much I almost want to write a 'framework' for it...)

  • start a TCP listener
  • on connection, start the cli tool in a separate process
  • hook stdin and stdout of the tool to the TCP connection
  • ????
  • PROFIT

The WASM thing is absolutely overkill, with you there 100%.

Are the prompts for 'configuration' only?

Not really - the prompts are the main event. It builds a branching tree of prompts from the input file provided, and can refer to previously received responses.

The "real" option would be to ditch text prompts and build graphical widgets, which sounds fun, too, but not a one-day thing.

This definitely sounds like it fits. I've never mucked about with TCP before but I don't think there's anything in my way conceptually, at least.

I've just scrapped around with this in Go - I'm sure you can convert to Rust with ease - using cowsay as the target command line app:

package main

import (
    "fmt"
    "net"
    "os"
    "os/exec"
)

func main() {
    listen, err := net.Listen("tcp", "127.0.0.1:6000")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    conn, err := listen.Accept()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    cmd := exec.Command("cowsay")
    cmd.Stdin = conn
    cmd.Stdout = conn
    cmd.Start()
    cmd.Wait()
}

/thread

Above and beyond, David, thanks for the sample!

That might be exactly the ticket - no real need to translate to Rust, I might just start with your Go template if you don't mind, that looks like less friction.

 
 

Ah jeeze, you may have just completely solved this problem. I didn't realize you could include other files to read!

I think I owe you a beer or something.

 

Ah, shoot - looks like they don't support external dependencies for Rust, and I'm leaning on a parsing library.

 

Can you cut and paste the relevant bits into a file? And include that file?

I'll play with it, but I think I need to be able to pull in the parsing crate to the build. It would probably be feasible to implement parsing by hand now that I've figured out the file format, which solves the problem, but not quickly.

Better than rewriting the whole thing in JavaScript, though?

Heh. How so very right you are.

 

When I hear "demo" and "low effort" I immediately think of zeit and netlifly. I haven't tried them with Rust, but in many cases you can deploy your code as an endpoint and curl against it with very little effort.

 

Oh, that's cool! I've heard of these platforms but not used either, will definitely take a look. Thank you!

 

I looked it up and unfortunately there's no Rust support, so you'll still be doing the WASM two-step if you go this route.

Oh wow, thanks for the research. Good to know.

I think the WASM<->JS app I'm building will work, and I do think I can deliver in a (long) day, but it felt like I was overthinking what sounds like a simple ask.

 

Why don't you have an interactive session this afternoon where you poll the audience and use their prompts? You might be solving a problem you don't have.

And if they want to play with it, buy yourself time after the demo. 1) you have limited time 2) you don't want to disengage them from the presentation

 

This would be the best solution if I had access to the audience. I'm remote and will not be the one giving the presentation tomorrow.

I think the eventual solution here will be to pont them to download a zip file with a precompiled bundle. Not quite a seamless as a URL, but that's already done and will work in about three clicks.

 

Why are you giving them access to it anyway? I understand wanting to wow the audience, but at the same time you risk your IP with your idea, no?

No real IP risk. This is an engineering unit pitching a project to their own company.

 

Maybe Live Share? I keep trying to find excuses to use that...

 

This is interesting, might fit. Thanks, never heard of this.

 

You'd have to have your demo users running VS Code though.

True. I know some will, but likely not all. And if I'm requiring them to install something, they may as well just download my precompiled bundle from github.

Looking through this post and replies... If I were you I'd focus on making sure the demo is solid and doesn't break. And record a backup if something fails during the presentation.

What you want to do doesn't seem worth the sweat equity at this time

 
 

Whoa, more than fine. Looks like a one-stop solution. Never heard of this, thank you so much.