You can learn more about this git repository by cloning it like this:
git clone https://supertxt.net/git/urltocmd
--hash=124dbb3 --date=2025-04-20T12:54:54-04:00 "Rewrite README to outline how the commands work at present"
--hash=d7df48c --date=2025-04-19T17:49:16-04:00 "Add search text capability for OpenAPI subcommands"
--hash=8b98844 --date=2025-04-19T17:16:10-04:00 "Check for missing required parameters"
--hash=579a583 --date=2025-04-18T20:11:25-04:00 "Add an explicit OpenAPI prefix"
--hash=c2621ee --date=2025-04-18T19:05:00-04:00 "Print help if the ssc is invoked without any command"
--hash=38209c8 --date=2025-04-18T18:39:09-04:00 "Reorganize repo layout for reusable functions"
--hash=4c8529e --date=2025-04-17T06:38:38-04:00 "Apply the same operation to subcommand normalization in urltocmd"
--hash=c14f5f7 --date=2025-04-14T18:31:22-04:00 "Normalize operation ids as subcommands with kebab case"
--hash=1c938c6 --date=2025-04-07T07:15:11-04:00 "Add true URL detection when prettying the JSON output"
--hash=ca3c672 --date=2025-04-06T19:30:17-04:00 "Fix URL appending between prefix and the OpenAPI operation suffixes in ssc"
--id=main --hash=124dbb3 --date=2025-04-20T12:54:54-04:00
Convert a URL into a command that is suitable for running on a command-line.
urltocmd https://somewebsite.org/foo%20bar/baz -- somewebsite.org \ cat \ "foo bar/baz"
Doesn't the command look easier to understand than the original URL?
A command-line can be compressed into a single line using the `--single-line` flag for easier copy and pasting.
urltocmd https://wikipedia.org/wiki/Carlisle --single-line -- wikipedia.org cat wiki/Carlisle
There is an accompanying tool 'ssc' that runs commands in the style that 'urltocmd' produces, making a request to the server and getting its response.
ssc wikipedia.org cat wiki/Carlisle -- <Output here>
These tools exist to increase awareness of the pitfalls of URLs and highlight how CLI can be a nicer, and more ergonomic interface.
URLs are difficult to read:
URLs require special tools to interpret, such as web browsers and `curl` bypassing natural OS mechanisms. Besides, why are 99% of them repeating the "http(s)://" over and over?
So, why not use commands instead? They are a much more natural interface, and are certainly more readable. They interact well with the operating system. You can ask them for help using `--help`, or even a Unix manual page.
One of the goals is to help and increase the number of site-specific command-line interfaces that can be run directly at the shell. Instead of using curl to interact with your favorite website, you can have a site-specific command that works with the typical paths, query parameters of it instead. If it becomes sophisticated enough, it can be shared with the world, and perhaps the website might make an official one someday.
Meanwhile, these two tools can help you today!
You can use this tool to convert URL's to commands as shown above. It can also take some of the more popular curl options, like the http method so that you can POST/PUT/HEAD.
urltocmd -XPOST https://somesite.com/abc -- somesite.com \ cat \ --http-method=POST abc
The ssc tool can run these commands too and ultimately POST the request. You can add HTTP headers too using the curl option.
urltocmd -XPOST -H'My-Header: ABCDE' https://somesite.com/def -- somesite.com \ cat \ --http-method=POST \ '--http-header=My-Header: ABCDE' \ def
The urltocmd also works with OpenAPI specifications. For example, you can use it with GitHub like this:
urltocmd --openapi=https://raw.githubusercontent.com/github/rest-api-description/refs/heads/main/descriptions/api.github.com/api.github.com.json https://api.github.com/users/supertxtnet -- api.github.com \ users \ get-by-username \ --username=supertxtnet
With the OpenAPI specification it is able to produce richer commands, subcommands, and options. There is an identical '--openapi' option in ssc so that it can run interpret the special commands, and also print help for them.
You can save time and space having to provide the openapi option every time you run these tools by using the special '--install' mode with urltocmd. It saves and caches the OpenAPI URL for you:
urltocmd --install --openapi=... https://api.github.com/users/supertxtnet -- site-specific command has been installed in /home/supertxt/.ssc/bin/api.github.com wrote OpenAPI url file for future updates: /home/cmcgee/.ssc/api.github.com/openapi.url wrote a copy of the OpenAPI specification here: /home/cmcgee/.ssc/api.github.com/openapi.json
Now you can run the command without the '--openapi' option and it uses its cache:
urltocmd https://api.github.com/users/supertxtnet -- api.github.com \ users \ get-by-username \ --username=supertxtnet
This is the same result we got above, but with much less typing. The 'ssc' tool can also use it too so that it knows how to assemble the server requests. There is also a site-specific command for 'api.github.com' that has been added to the '~/.ssc/bin' directory. If you add this to your shell's PATH then you can run the commands that urltocmd gives you without having to put 'ssc' in front of it. The install mode creates a site-specific command for you.
If you were trying to run these site-specific commands you are likely to get '401: Unauthorized' errors because you're not authenticated. Many sites, such as GitHub have special authorization header that you use to authenticate yourself with each request. You can usually generate an access token or API token by going to the site with your web browser and copy it. You can then install your token as an authorization header for every request to api.github.com like this:
urltocmd --install -H"Authorization: -" https://api.github.com -- Enter header Authorization value: Bearer ABCDE <-- This is pasted in from the token generated by GitHub, and prefixed with Bearer based on GitHub's instructions
urltocmd creates a file to hold sensitive headers in your '~/.ssc' directory, and protects the file using filesystem permissions so that no other users can read the header. The value was read from standard input instead of a command-line parameter or environment variable to help and prevent snooping the value.
After both the OpenAPI specification and the authorization header are cached, the site-specific command 'api.github.com' will be able to make its requests authenticated as you.
The ssc command is a little like curl, but without the URL and has one less letter to type each time. For example, this will do an HTTP GET on a specific resource of a fictional RESTful site example.com:
ssc example.com cat pets.json -- ["Polly the parrot", "Dolly the sheep", "Ginger the duck"]
This is much like how you could read the contents of a file on another computer using ssh. The command is nearly identical for simple read operations, just with "ssc" in place of "ssh".
And now let's look at a particular pet. Spaces are fine, we just put quotes around them.
ssc example.com cat "pets/Polly the parrot.json" -- { "name": "Polly the parrot", "city": "London" }
Or get, modify and put an update to the city to Carlisle:
ssc example.com cat "pets/Polly the parrot.json" | jq '.city="Carlisle"' | ssc example.com cat -XPUT -d@-.json "pets/Polly the parrot.json"
We can also pass site parameters to places where typically you would use URL query parameters. Let's list all of the pets in Carlisle:
ssc example.com cat pets.json --city=Carlisle -- ["Polly the parrot", "Ginger the duck"]
Underneath, the ssc tool is creating a URL for these requests. We can ask it for the URL using the `print-url` command:
ssc example.com cat pets.json --city=Carlisle -Aprint-url -- https://example.com/pets?city=Carlisle
Note that in more complex scenarios like PUT requests ssc is creating a full HTTP request with the HTTP method, request body, and redirecting the output to from standard input. In those cases there's more than just a simple URL involved, it's more like a complex curl command, so the print URL function might produce an error. You can print an entire curl command using "print-curl".
ssc example.com cat -XPOST -d@-.json pets.json -H "Authorization: Bearer ABCDE" -Aprint-curl -- curl -H "Authorization: Bearer ABCDE" -d- -XPOST https://example.com/pets
In the above examples, you can see that the file extension ".json" used extensively. Site specific commands make use of file extensions in place of content types and accept headers for paths and data. They're simpler, easier, and have a longer history than media types. They also fit more naturally in the command-line. Internally, the ssc tool will automatically add in the "Content-Type" and "Accept" headers for known file extensions. However, if the REST endpoint won't accept paths with the file extension in them then you can use the path that it accepts, and use the type option ("-T") to give the ssc the requested file type like this:
ssc example.com cat -T.json pets
Because site specific commands are aware of the content type of their expected output for a particular command they support file extension reflection '--srefl' for any command to see the type of output they would produce, if it is run. This can be used by tools that support querying a command from the reflective interface, such as the browsing shell that can render images.
ssc example.com cat logo.jpg --srefl=ext -- .jpg
REST API's can become really intricate, usually much more than the simple example above. We would like to use OpenAPI as a way to identify higher-level commands instead of paths. This can increase the ergonomics (ie. less typing involved) of the site specific commands. Also, the OpenAPI specification can help users to see the capabilities of a site. Let's try inspecting a website using its OpenAPI specification published online, but more like how we would ask a command-line tool for its help:
ssc shopping.example.com --openapi=https://shopping.example.com/api/spec.yaml --help -- Usage: shopping.example.com [command] The following commands are available: * cat - display result of an HTTP API * srch - search using a full text query * showShoppingCartContents * addItemToCart * searchForWidgets
You can repeat the above command with your up-arrow (in most modern shells), remove the "--help" flag and replace it with any of the commands to access the functionality. But, we are still having to remember to type the "ssc" command, and providing that long URL to the spec. Let's make things a little easier for ourselves by installing the shoping site as a command on our system that remembers the OpenAPI specification. We can do this by using the `urltocmd --install` option.
urltocmd --install --openapi=https://shopping.example.com/api/spec.yaml https://shopping.example.com
Often API's require a special authorization header. We can ask `urltocmd` to prompt us for the header's value, which saves it to a file protected using filesystem permissions and we don't need to provide it again. The special value '-' in the value of the Authorization header below performs the protected transfer of the information:
urltocmd --install -H 'Authorization: -' https://shopping.example.com Enter header Authorization value: Bearer ABCDE
Now, if you add the `~/.ssc/bin` directory to your PATH you get the site-specific command wrapper with the OpenAPI specification and the authorization header. You can now run the commands just like regular commands on your system.
shopping.example.com showShoppingCartContents --user=me
Or, even get more detailed help for the command in the expected way:
shopping.example.com showShoppingCartContents --help -- Usage: showShoppingCartContents --user=<userId> [--limit=10] [--foo=<bar>]