{"id":17113674,"url":"https://github.com/totakke/clj-sub-command","last_synced_at":"2026-03-11T06:32:29.354Z","repository":{"id":9622950,"uuid":"11550656","full_name":"totakke/clj-sub-command","owner":"totakke","description":"A simple subcommand parser for Clojure","archived":false,"fork":false,"pushed_at":"2025-04-22T13:25:46.000Z","size":68,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-21T06:54:35.522Z","etag":null,"topics":["cli","clojure","subcommands"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/totakke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2013-07-20T17:44:04.000Z","updated_at":"2025-04-22T13:25:49.000Z","dependencies_parsed_at":"2024-11-07T18:05:11.361Z","dependency_job_id":"ad8ee3df-acce-44a9-b288-c9b809cb1637","html_url":"https://github.com/totakke/clj-sub-command","commit_stats":{"total_commits":104,"total_committers":2,"mean_commits":52.0,"dds":"0.17307692307692313","last_synced_commit":"b124b25dbb93e14e9679ebc33800fdd9e523d7f0"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/totakke/clj-sub-command","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totakke%2Fclj-sub-command","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totakke%2Fclj-sub-command/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totakke%2Fclj-sub-command/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totakke%2Fclj-sub-command/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/totakke","download_url":"https://codeload.github.com/totakke/clj-sub-command/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totakke%2Fclj-sub-command/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30373472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T06:09:32.197Z","status":"ssl_error","status_checked_at":"2026-03-11T06:09:17.086Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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","clojure","subcommands"],"created_at":"2024-10-14T17:11:34.790Z","updated_at":"2026-03-11T06:32:29.311Z","avatar_url":"https://github.com/totakke.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clj-sub-command\n\n[![Clojars Project](https://img.shields.io/clojars/v/clj-sub-command.svg)](https://clojars.org/clj-sub-command)\n[![cljdoc badge](https://cljdoc.org/badge/clj-sub-command/clj-sub-command)](https://cljdoc.org/d/clj-sub-command/clj-sub-command)\n[![build](https://github.com/totakke/clj-sub-command/actions/workflows/build.yml/badge.svg)](https://github.com/totakke/clj-sub-command/actions/workflows/build.yml)\n\nA simple subcommand parser for Clojure.\n\n## Installation\n\nclj-sub-command is available as a Maven artifact from [Clojars](https://clojars.org/clj-sub-command).\n\nClojure CLI/deps.edn:\n\n```clojure\nclj-sub-command/clj-sub-command {:mvn/version \"0.6.0\"}\n```\n\nLeiningen/Boot:\n\n```clojure\n[clj-sub-command \"0.6.0\"]\n```\n\n## Usage\n\n```clojure\n(ns my.program\n  (:require [clj-sub-command.core :refer [parse-cmds]])\n  (:gen-class))\n\n;; Options before a subcommand\n(def options\n  [[\"-p\" \"--port PORT\" \"Port number\"\n    :default 80\n    :parse-fn #(Integer/parseInt %)]\n   [\"-h\" \"--help\"]])\n\n;; Subcommands and descriptions\n(def commands\n  [[\"up\" \"Start server\"]\n   [\"down\" \"Stop server\"\n    :id :stop]])\n\n(defn -main [\u0026 args]\n  (parse-cmds args options commands))\n```\n\nExecute the command line:\n\n```sh\nmy-program -p8080 --help up --log-directory /tmp some-file\n```\n\nto produce the map:\n\n```clojure\n{:options          {:port 8080\n                    :help true}\n :command          :up\n :arguments        [\"--log-directory\" \"/tmp\" \"some-file\"]\n :options-summary  \"  -p, --port PORT  80  Port number\n                      -h, --help\"\n :commands-summary \"  up    Start server\n                      down  Stop server\"\n :errors           nil\n :candidates       [\"up\"]}\n```\n\n### Option Specifications\n\n`parse-cmds` uses [tools.cli](https://github.com/clojure/tools.cli) internally\nfor parsing the options. See tools.cli document for option specifications.\n\n### Options/Commands Summary\n\n`:options-summary` and `:commands-summary` are minimal summary strings of the\noptions and commands.\n\nOptions:\n\n```text\n  -p, --port PORT  80  Port number\n  -h, --help\n```\n\nCommands:\n\n```text\n  up    Start server\n  down  Stop server\n```\n\n`:options-summary-fn` and `:commands-summary-fn` may be supplied to `parse-cmds`\nif the default formatting is unsatisfactory.\n\n### Candidate Commands\n\n`:candidates` vector has near commands in the specifications to the given\ncommand. These candidates are also contained in `:errors` vector as an error\nmessage when the given command is incorrect.\n\n```text\nUnknown command: \"upp\"\n\nThe most similar command is\n        up\n```\n\n## Example\n\nUsing clj-sub-command with another command-line parser, such as tools.cli, is\nrecommended for parsing the rest arguments.\n\n```clojure\n(ns example.core\n  (:require [clojure.string :as string]\n            [clj-sub-command.core :refer [parse-cmds]]\n            [clojure.tools.cli :refer [parse-opts]])\n  (:gen-class))\n\n(defn error-msg [errors]\n  (str \"The following errors occurred while parsing your command:\\n\\n\"\n       (string/join \\newline errors)))\n\n(defn exit [status msg]\n  (println msg)\n  (System/exit status))\n\n;; \"up\" subcommand\n\n(def up-options\n  [[\"-v\" \"--verbose\"]\n   [\"-h\" \"--help\"]])\n\n(defn up-usage [options-summary]\n  (-\u003e\u003e [\"Usage: program-name up [options] file\"\n        \"\"\n        \"Options:\"\n        options-summary]\n       (string/join \\newline)))\n\n(defn up [args]\n  (let [{:keys [options arguments errors summary]} (parse-opts args up-options)]\n    (cond\n      (:help options) (exit 0 (up-usage summary))\n      (not= (count arguments) 1) (exit 1 (up-usage summary))\n      errors (exit 1 (error-msg errors)))\n    (if (:verbose options)\n      ...)))\n\n;; \"down\" subcommand\n\n(def down-options ...)\n(defn down-usage [options-summary] ...)\n(defn down [args] ...)\n\n;; main\n\n(def options\n  [[\"-h\" \"--help\"]])\n\n(def commands\n  [[\"up\" \"Start server\"]\n   [\"down\" \"Stop server\"]])\n\n(defn usage [options-summary commands-summary]\n  (-\u003e\u003e [\"Usage: program-name [--help] \u003ccommand\u003e [\u003cargs\u003e]\"\n        \"\"\n        \"Options:\"\n        options-summary\n        \"\"\n        \"Commands:\"\n        commands-summary]\n       (string/join \\newline)))\n\n(defn -main [\u0026 args]\n  (let [{:keys [options command arguments errors options-summary commands-summary]}\n        (parse-cmds args options commands)]\n    (cond\n      (:help options) (exit 0 (usage options-summary commands-summary))\n      errors (exit 1 (error-msg errors)))\n    (case command\n      :up   (up arguments)\n      :down (down arguments))))\n```\n\n## License\n\nCopyright © 2013 Toshiki Takeuchi\n\nDistributed under the [Eclipse Public License](LICENSE), the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotakke%2Fclj-sub-command","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftotakke%2Fclj-sub-command","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotakke%2Fclj-sub-command/lists"}