2 पॉइंट द्वारा GN⁺ 2024-02-07 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • यह गाइड पारंपरिक UNIX सिद्धांतों को आधुनिक रूप में अपडेट करते हुए, ऐसे CLI बनाने के लिए open source डिज़ाइन दिशानिर्देश है जो इंसानों के लिए इस्तेमाल में आसान हों और automation के लिए भी मजबूत हों
  • अच्छा CLI इंसान-प्रथम तरीके से काम करता है, लेकिन stdout/stderr, exit code, pipe, JSON जैसी conventions का पालन करते हुए दूसरे programs के साथ स्वाभाविक रूप से compose हो पाना चाहिए
  • help, documentation, error messages और output ऐसे होने चाहिए कि user को अगला कदम समझ आ जाए; --help, examples, suggestions, progress display और status explanation इसमें मुख्य भूमिका निभाते हैं
  • arguments, flags, interactions, settings और environment variables को scripts और terminal usage दोनों को ध्यान में रखकर डिज़ाइन करना चाहिए; secrets को flags या environment variables के ज़रिए सीधे लेना आम तौर पर कम सुरक्षित है
  • CLI का नाम, distribution और analytics collection तक user के control की भावना और long-term compatibility को नुकसान नहीं पहुँचाना चाहिए; conventions तोड़नी भी पड़े तो उद्देश्य स्पष्ट होना चाहिए

CLI डिज़ाइन का मूल दर्शन

  • यह गाइड open source दस्तावेज़ है, जो पारंपरिक UNIX सिद्धांतों के आधार पर आधुनिक command-line programs के डिज़ाइन principles और ठोस guidelines प्रदान करता है
  • पहले command line scripting platform के ऊपर REPL जैसा machine-first environment था, लेकिन आज का CLI कई tools, systems और platforms तक पहुँचने वाला text-based UI है, जिसमें इंसान-प्रथम प्रकृति अधिक मजबूत है
  • command line में पुरानी सीमाएँ और अजीब conventions हैं, लेकिन यह लगभग हर laptop पर उपलब्ध है, interactive use और automation दोनों संभव करता है, और अन्य system components की तुलना में कम तेजी से बदलता है
  • यह गाइड emacs या vim जैसे full-screen terminal programs को cover नहीं करता, और किसी खास programming language या toolchain पर निर्भर भी नहीं है

इंसान-प्रथम और compose करने योग्य CLI

  • अगर CLI मुख्य रूप से इंसानों द्वारा इस्तेमाल किया जाने वाला tool है, तो इंसान को पहले ध्यान में रखना चाहिए
    • कई CLI programs human users को target करते हुए भी पुराने machine-centric interaction design को जस का तस बनाए रखते हैं
  • साफ interfaces के साथ साथ काम करने वाले छोटे programs की UNIX philosophy आज भी महत्वपूर्ण है
    • standard input, output, error, signals और exit codes जैसी conventions programs के बीच composition संभव बनाती हैं
    • line-based plain text को pipes से भेजना आसान है, और JSON तब उपयोगी है जब अधिक structured data चाहिए हो
  • consistency वह मुख्य तत्व है जो CLI सीखने की लागत को long-term efficiency में बदलता है
    • मौजूदा patterns का पालन करने से users commands और options का अंदाज़ा आसानी से लगा सकते हैं
    • जब conventions usability को नुकसान पहुँचाएँ, तो उन्हें सावधानी से तोड़ा जा सकता है
  • अच्छा CLI न तो बहुत चुप रहता है और न ही बहुत ज़्यादा output देता है; उसे user को जरूरत भर की जानकारी पाने देना चाहिए
  • CLI को GUI की तुलना में कम discoverable माना जाता है, लेकिन comprehensive help, examples, next-command suggestions और errors पर response guidance से सीखने की क्षमता बढ़ाई जा सकती है

Interactive interaction और मजबूती

  • command-line use एक बार की execution से अधिक, कई attempts और corrections वाली बातचीत जैसा होता है
    • गलत input पर संभव corrections सुझाए जा सकते हैं
    • multi-step काम की intermediate state स्पष्ट रूप से दिखाई जा सकती है
    • खतरनाक operations से पहले confirmation लिया जा सकता है
  • CLI को वास्तव में robust होना चाहिए, और साथ ही user को भी robust लगना चाहिए
    • unexpected input को graceful तरीके से handle करना चाहिए
    • जहाँ संभव हो, operations idempotent होने चाहिए
    • डरावने दिखने वाले stack traces को default output में नहीं दिखाना चाहिए
  • user को यह महसूस कराने वाली empathy महत्वपूर्ण है कि software उसकी तरफ है
    • इसका मतलब emojis लगाना या game जैसा बनाना नहीं, बल्कि user को सफल बनाने के लिए सावधानी से design करना है
  • terminal ecosystem में inconsistency और confusion बहुत है, लेकिन कम constraints की वजह से नए inventions संभव हुए हैं
    • मौजूदा patterns का पालन करें, लेकिन productivity या user satisfaction को नुकसान पहुँचाने वाले standards को जानबूझकर छोड़ा जा सकता है

अनिवार्य बुनियादी नियम

  • जहाँ संभव हो, command-line argument parsing library का उपयोग करना चाहिए
    • arguments, flags, help, spelling suggestions आदि को consistently handle किया जा सकता है
    • उदाहरण के लिए docopt, Cobra, Click, Typer, clap, swift-argument-parser आदि हैं
  • success पर exit code 0 और failure पर non-zero value return करनी चाहिए
    • scripts exit code के ज़रिए program की success या failure तय करती हैं
  • command का primary output stdout पर भेजना चाहिए
    • machine-readable output भी default रूप से stdout पर जाना चाहिए ताकि pipes सही तरह से काम करें
  • log messages, errors आदि user को दिखाए जाने वाले messages stderr पर भेजने चाहिए
    • pipe से जोड़ते समय messages अगले command के input में mix नहीं होते

Help design

  • -h और --help दिए जाने पर पर्याप्त help दिखानी चाहिए
    • subcommands की अपनी help भी हो सकती है
    • -h को किसी दूसरे अर्थ में overload नहीं करना चाहिए
  • जिस command को arguments चाहिए, उसे बिना arguments चलाने पर concise help दिखानी चाहिए
    • program description
    • एक-दो example invocations
    • flags की explanation
    • अधिक detailed जानकारी के लिए --help इस्तेमाल करने की guidance
  • help में support paths शामिल करना अच्छा है
    • website या GitHub link आम हैं
  • अगर web documentation है, तो help से उस documentation पर link करना चाहिए
    • अगर subcommand के लिए specific page या anchor है, तो direct link देना उपयोगी है
  • users documentation से पहले examples का उपयोग करने की प्रवृत्ति रखते हैं, इसलिए help में examples को शुरुआत में रखना अच्छा है
    • जटिल लेकिन common use cases पहले दिखाए जा सकते हैं
    • अगर examples बहुत अधिक हों, तो उन्हें अलग cheatsheet command या web page में रखना उचित है
  • help को scan करना आसान हो, ऐसी formatting की जा सकती है
    • bold headings readability बढ़ाते हैं
    • terminal-independent तरीके से handle करना चाहिए ताकि escape characters वैसे ही दिखाई न दें
  • अगर user ने गलत input दिया है और intent का अंदाज़ा लगाया जा सकता है, तो suggestion देनी चाहिए
    • brew update jq के बदले brew upgrade jq सुझाने जैसा behavior हो सकता है
    • suggested command चलाना है या नहीं, यह पूछा जा सकता है, लेकिन automatic execution से बचना चाहिए
  • अगर किसी command को stdin से input लेना है और stdin interactive terminal है, तो तुरंत help दिखाकर exit करना चाहिए या stderr पर message print करना चाहिए

Documentation

  • help immediate summary और common tasks की guidance देती है, जबकि documentation tool के purpose, non-purpose, behavior और full usage को विस्तार से cover करती है
  • web-based documentation प्रदान करनी चाहिए
    • यह searchable होती है और specific हिस्सों पर link किया जा सकता है
    • web documentation सबसे comprehensive documentation format है
  • terminal-based documentation भी प्रदान करनी चाहिए
    • इसे जल्दी access किया जा सकता है
    • यह installed tool version के साथ synchronized रहती है
    • internet के बिना भी काम करती है
  • man pages देने पर विचार किया जा सकता है
    • कई users पहले man mycmd देखते हैं
    • git और npm की तरह help subcommand के ज़रिए man pages access किए जा सकते हैं

आउटपुट के सिद्धांत

  • इंसानों के लिए पढ़ने में आसान आउटपुट सबसे महत्वपूर्ण है
    • यह तय करने का सरल मानदंड कि कोई खास output stream इंसान द्वारा पढ़ी जा रही है या नहीं, यह है कि वह TTY है या नहीं
  • उपयोगिता को नुकसान पहुंचाए बिना machine-readable आउटपुट देना चाहिए
    • plain text lines की stream UNIX का सार्वभौमिक इंटरफ़ेस है
    • उपयोगकर्ता उम्मीद करते हैं कि output को grep जैसे टूल में पास करने पर वह अपेक्षा के मुताबिक काम करेगा
  • अगर human-friendly आउटपुट machine-friendly आउटपुट को तोड़ता है, तो --plain दिया जा सकता है
    • table output में cells को कई लाइनों में बांटने से “एक record एक line” वाली अपेक्षा टूट सकती है
    • --plain scripts के लिए बिना छेड़छाड़ वाला table-format आउटपुट देता है
  • अगर --json पास किया गया है, तो formatted JSON आउटपुट करना चाहिए
    • JSON जटिल data structures को संभालना आसान बनाता है, और jq व कई JSON CLI tools के साथ इस्तेमाल किया जा सकता है
    • web services और curl के जरिए सीधे pipe से जोड़ने के लिए भी उपयुक्त है
  • सफलता पर आउटपुट दें, लेकिन उसे छोटा रखें
    • पारंपरिक UNIX commands अक्सर कोई समस्या न होने पर आउटपुट नहीं देते, लेकिन इंसान को यह अटका हुआ लग सकता है
    • scripts के लिए no-output चाहिए तो -q option से गैर-ज़रूरी आउटपुट छिपाया जा सकता है
  • state बदलने वाली commands को उपयोगकर्ता को बताना चाहिए कि क्या बदला है
    • git push चल रहे काम और remote branch की नई state दिखाने वाला उदाहरण है
  • system की मौजूदा state आसानी से देखी जा सकनी चाहिए
    • git status repository की state और आगे चलाए जा सकने वाले commands के hints साथ में दिखाता है
  • program की आंतरिक दुनिया की सीमा पार करने वाले काम आम तौर पर explicit होने चाहिए
    • जब वह files पढ़ता या लिखता है जिन्हें उपयोगकर्ता ने arguments में नहीं दिया
    • जब वह remote server से communication करके files डाउनलोड करता है
  • रंगों का इस्तेमाल इरादे के साथ करना चाहिए
    • बहुत ज्यादा इस्तेमाल करने पर उनका अर्थ खत्म हो जाता है और पढ़ना मुश्किल हो जाता है
    • अगर TTY नहीं है, या NO_COLOR set है, या TERM=dumb है, या --no-color पास किया गया है, तो colors बंद कर देने चाहिए
  • अगर stdout interactive terminal नहीं है, तो animations आउटपुट नहीं करनी चाहिए
    • इससे CI logs में progress indicators के गड़बड़ दिखने से बचा जा सकता है
  • बहुत ज्यादा text आउटपुट करते समय less जैसे pager का इस्तेमाल किया जा सकता है
    • बेहतर है कि इसे केवल तब इस्तेमाल करें जब stdin या stdout interactive terminal हो
    • less -FIRX एक समझदार options set के रूप में इस्तेमाल किया जा सकता है

error messages

  • errors को documentation जैसा बनाने से उपयोगकर्ता का docs ढूंढने में लगने वाला समय घट सकता है
  • अनुमानित errors को पकड़कर इंसान के समझने लायक ढंग से फिर से लिखना चाहिए
    • उदाहरण: file.txt में लिखा नहीं जा सकता और शायद chmod +w file.txt की जरूरत है—ऐसा guidance
  • signal-to-noise ratio महत्वपूर्ण है
    • जितना ज्यादा irrelevant output होगा, उपयोगकर्ता के लिए समस्या समझना उतना मुश्किल होगा
    • अगर एक ही तरह की कई errors हैं, तो उन्हें एक explanation header के नीचे group किया जा सकता है
  • सबसे महत्वपूर्ण जानकारी output के अंत में रखना बेहतर है
    • उपयोगकर्ता की नजर लाल text की ओर खिंचती है, इसलिए उसे जानबूझकर कम इस्तेमाल करना चाहिए
  • अगर error unexpected है या explain करना मुश्किल है, तो debug/traceback information और bug submit करने का तरीका देना चाहिए
    • उपयोगकर्ता को overwhelm न करने के लिए debug logs को terminal के बजाय file में लिखा जा सकता है
  • bug submit करना आसान बनाना चाहिए
    • संभावित जानकारी पहले से भरे हुए URL देना इसका एक उदाहरण है

arguments और flags

  • arguments position-based parameters होते हैं, और flags named parameters होते हैं
    • cp foo bar में file paths arguments हैं
    • -r, --recursive, --file foo.txt flags हैं
  • जहां संभव हो, arguments की बजाय flags को प्राथमिकता देनी चाहिए
    • ज्यादा typing करनी पड़ती है, लेकिन अर्थ स्पष्ट होता है
    • भविष्य में input method बदलना आसान होता है
  • सभी flags के लिए long name देना चाहिए
    • जैसे -h और --help दोनों रखना
    • scripts में अर्थ को स्पष्ट दिखाने में उपयोगी है
  • one-letter flags केवल आम तौर पर इस्तेमाल होने वाले options के लिए ही इस्तेमाल करने चाहिए
    • इससे बाद में जोड़े जाने वाले flags के लिए short-name space बचाई जा सकती है
  • जब कई files पर वही सरल काम लागू करना हो, तो multiple arguments उपयुक्त हैं
    • rm file1.txt file2.txt file3.txt जैसा रूप globbing के साथ अच्छी तरह मेल खाता है
  • अगर अलग-अलग अर्थ वाले 2 या अधिक arguments हैं, तो design गलत होने की संभावना ज्यादा है
    • अपवाद के तौर पर cp <source> <destination> जैसे common और core operations में छोटापन याद रखने लायक है
  • अगर standard flag names मौजूद हैं, तो उनका पालन करना चाहिए
    • -a, --all
    • -d, --debug
    • -f, --force
    • --json
    • -h, --help
    • -n, --dry-run
    • --no-input
    • -o, --output
    • -p, --port
    • -q, --quiet
    • -u, --user
    • --version
  • defaults अधिकांश उपयोगकर्ताओं के लिए सही behavior होने चाहिए
    • अगर यह मान लें कि उपयोगकर्ता हर बार सही flag खोजकर याद रखेंगे और इस्तेमाल करेंगे, तो अधिकांश user experience खराब हो जाएगा
  • input न हो तो prompt से पूछा जा सकता है, लेकिन prompt अनिवार्य नहीं होना चाहिए
    • हमेशा flags या arguments के जरिए input देने का तरीका देना चाहिए
    • अगर stdin interactive terminal नहीं है, तो prompt छोड़कर जरूरी flags या arguments मांगने चाहिए
  • खतरनाक operations से पहले confirmation लेना चाहिए
    • interactive run में y या yes टाइप करवाया जा सकता है
    • non-interactive run में -f या --force मांगा जा सकता है
    • गंभीर operations में deletion target का नाम सीधे टाइप करवाया जा सकता है या --confirm="name-of-thing" जैसा flag दिया जा सकता है
  • अगर file input/output लेते हैं, तो - से stdin या stdout support करना चाहिए
    • इससे temporary files के बिना दूसरी commands के output से जोड़ा जा सकता है
  • जहां संभव हो, arguments, flags और subcommands के order को independently handle करना चाहिए
    • क्योंकि उपयोगकर्ता अक्सर पिछली command के अंत में option जोड़कर फिर से run करते हैं
  • secrets को सीधे flags से नहीं पढ़ना चाहिए
    • --password value ps output या shell history में expose हो सकती है
    • --password-file जैसे file input या stdin पर विचार करना चाहिए

interaction

  • prompts या interactive elements केवल तब इस्तेमाल करने चाहिए जब stdin TTY हो
    • scripts या pipe input के दौरान prompt काम नहीं करता, इसलिए error में बताना चाहिए कि कौन-सा flag पास करना है
  • अगर --no-input पास किया गया है, तो prompts या interactive behavior नहीं करना चाहिए
    • अगर input चाहिए, तो fail करें और flag से पास करने का तरीका बताएं
  • password लेते समय उपयोगकर्ता जो type कर रहा है उसे output नहीं करना चाहिए
    • terminal echo बंद करके इसे handle करें
  • उपयोगकर्ता बाहर निकल सकना चाहिए
    • network I/O आदि के कारण रुका हुआ हो तब भी Ctrl-C काम करना चाहिए
    • अगर SSH, tmux, telnet जैसे wrappers हों जिनसे Ctrl-C से exit नहीं किया जा सकता, तो escape method स्पष्ट रूप से बताना चाहिए

subcommands

  • अगर tool पर्याप्त जटिल है, तो subcommands के set से complexity घटाई जा सकती है
    • कई संबंधित tools को एक command में बांधने से इस्तेमाल और discovery आसान हो सकती है
    • global flags, help, configuration और storage mechanisms share करना अच्छा रहता है
  • subcommands के बीच consistency जरूरी है
    • समान अर्थ के लिए समान flag name इस्तेमाल करना चाहिए
    • output format भी समान होना चाहिए
  • कई levels वाले subcommands के लिए consistent naming system इस्तेमाल करना चाहिए
    • docker container create की तरह noun और verb के दो levels वाला pattern common है
    • noun verb और verb noun दोनों संभव हैं, लेकिन noun verb ज्यादा common दिखता है
  • अस्पष्ट या मिलते-जुलते नामों वाली commands से बचना चाहिए
    • update और upgrade साथ हों तो confusion हो सकता है

मजबूती

  • यूज़र द्वारा इनपुट किया गया हर डेटा validate किया जाना चाहिए
    • गलत डेटा आ सकता है, इसलिए जल्दी जांचकर समझ में आने वाले error के साथ रुकना चाहिए
  • तेज़ होने से ज़्यादा responsive होना अहम है
    • 100ms के भीतर यूज़र को कुछ न कुछ output देना अच्छा है
    • network request से पहले भी message output करें ताकि ऐसा न लगे कि program अटक गया है
  • लंबे समय तक चलने वाले कामों में progress दिखानी चाहिए
    • अगर कुछ समय तक कोई output न हो, तो program खराब लग सकता है
    • अगर progress indicator लंबे समय तक एक ही जगह रुका रहे, तो बचे हुए समय का estimate या animation दिखाकर बताया जा सकता है कि काम जारी है
  • parallel processing संभव हो तो करें, लेकिन सावधानी से
    • shell में parallel tasks की progress दिखाना मुश्किल है, और output मिल-जुल जाए तो भ्रम पैदा होता है
    • docker pull की कई progress bars यह दिखाने का उदाहरण हैं कि क्या हो रहा है
    • सामान्य कामकाज के दौरान logs को progress bar के पीछे छिपाया जा सकता है, लेकिन error आने पर logs output होने चाहिए ताकि debugging संभव हो
  • network operations में timeout होना चाहिए
    • timeout configurable होना चाहिए और उसका reasonable default होना चाहिए
  • failure के बाद recovery संभव होनी चाहिए
    • temporary failure के बाद <up> और <enter> से फिर चलाने पर interrupted point से आगे जारी रहना चाहिए
  • संभव हो तो crash-only तरीका अच्छा है
    • failure या interruption पर तुरंत exit किया जा सकता है, और cleanup को अगले run तक टाला जा सकता है
  • यूज़र tool को अप्रत्याशित तरीकों से इस्तेमाल कर सकते हैं
    • वे इसे script में wrap कर सकते हैं, unstable internet पर इस्तेमाल कर सकते हैं, कई instances एक साथ चला सकते हैं, या untested environment में run कर सकते हैं

भविष्य की compatibility

  • subcommands, arguments, flags, config files, और environment variables सभी interface हैं, और इन्हें लंबे समय तक काम करते रहने लायक बनाए रखना चाहिए
  • संभव changes additive होने चाहिए
    • मौजूदा flag behavior तोड़ने के बजाय नया flag जोड़ा जा सकता है
  • अगर non-additive change ज़रूरी हो, तो पहले से warning देनी चाहिए
    • अब recommend न किए जाने वाले flag का उपयोग होने पर future change की जानकारी दें, और अभी से इस्तेमाल किया जा सकने वाला future-compatible तरीका भी बताएं
  • human-readable output बदलना आम तौर पर ठीक है
    • यूज़र को scripts में stable output के लिए --plain या --json इस्तेमाल करने के लिए प्रेरित करना चाहिए
  • catch-all subcommands से बचना चाहिए
    • अगर known subcommand नहीं है तो उसे अपने-आप run मान लेने का तरीका, बाद में नया subcommand जोड़ते समय मौजूदा usage तोड़ सकता है
  • subcommands के arbitrary abbreviations allow नहीं करने चाहिए
    • install को i या ins के रूप में allow करने से बाद में i से शुरू होने वाला दूसरा command जोड़ना मुश्किल हो जाता है
    • aliases explicit और stable रखने चाहिए
  • यह सोचना चाहिए कि क्या 20 साल बाद भी command उसी तरह चलेगा
    • बाहरी internet dependencies बदलने या गायब होने से command रुक जाए, ऐसी time bomb नहीं बनानी चाहिए

signals और control characters

  • जब यूज़र Ctrl-C, यानी INT signal भेजे, तो जितनी जल्दी हो सके exit करना चाहिए
    • cleanup शुरू करने से पहले तुरंत कुछ बताना चाहिए
    • cleanup code में timeout होना चाहिए
  • लंबे cleanup के दौरान Ctrl-C दोबारा input हो तो cleanup skip किया जा सकना चाहिए
    • Docker Compose shutdown के दौरान बताता है कि Ctrl-C एक बार और दबाने पर containers को तुरंत force stop किया जा सकता है
  • program को यह मानकर चलना चाहिए कि वह पिछला cleanup काम पूरा हुए बिना start हो सकता है

configuration और environment variables

  • configuration का तरीका specificity, stability, और complexity के हिसाब से बदलना चाहिए
    • हर run में अक्सर बदलने वाली settings के लिए flags उपयुक्त हैं
    • user, project, या machine के हिसाब से बदलने वाली अपेक्षाकृत stable settings के लिए flags और environment variables उपयुक्त हैं
    • project के अंदर सभी users के लिए stable settings के लिए version-controlled command-specific config file उपयुक्त है
  • XDG Base Directory Specification का पालन करना अच्छा है
    • इसका उद्देश्य ~/.config जैसी general-purpose config locations को support करके home directory में dotfiles की बढ़ोतरी कम करना है
  • अगर आप अपने program की config नहीं, बल्कि किसी और file को automatic modify करते हैं, तो user की consent लें और साफ़ बताएं कि आप क्या कर रहे हैं
    • मौजूदा system config file में append करने के बजाय नई config file बनाना बेहतर है
  • configuration priority उच्च से निम्न क्रम में लागू होनी चाहिए
    • flags
    • चल रहे shell के environment variables
    • project-level configuration
    • user-level configuration
    • system-wide configuration
  • environment variables ऐसे behavior के लिए उपयुक्त हैं जो command चलने के context के अनुसार बदलता है
  • environment variable names में maximum portability के लिए केवल uppercase letters, digits, और underscores का इस्तेमाल होना चाहिए, और वे digit से शुरू नहीं होने चाहिए
  • values संभव हो तो one-line होनी चाहिए
    • multi-line values को env command के साथ इस्तेमाल करने पर usability issues आते हैं
  • व्यापक रूप से इस्तेमाल होने वाले names पर मनमाने ढंग से कब्ज़ा नहीं करना चाहिए
    • POSIX standard environment variables की list का reference लिया जा सकता है
  • जहाँ संभव हो, general-purpose environment variables check करने चाहिए
    • NO_COLOR, FORCE_COLOR
    • DEBUG
    • EDITOR
    • HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY
    • SHELL
    • TERM, TERMINFO, TERMCAP
    • TMPDIR
    • HOME
    • PAGER
    • LINES, COLUMNS
  • उपयुक्त मामलों में .env से environment variables पढ़े जा सकते हैं
    • यह उन variables के लिए उपयोगी है जो किसी particular directory में काम करते समय शायद ही बदलते हैं
  • .env formal config file का substitute नहीं है
    • अक्सर इसे source control में save नहीं किया जाता
    • इसमें केवल string type होता है
    • इसे व्यवस्थित रखना आसानी से बिगड़ सकता है
    • encoding issues आ सकते हैं
    • इसमें sensitive credentials और key material आना आसान है
  • secrets environment variables से नहीं पढ़ने चाहिए
    • environment variables processes, logs, docker inspect, systemctl show आदि के ज़रिए expose हो सकते हैं
    • secrets को credentials file, pipe, AF_UNIX socket, secret management service, या किसी अन्य IPC method से लेना चाहिए

नाम, distribution, analytics collection

  • CLI program का नाम सरल और याद रखने में आसान होना चाहिए, क्योंकि users इसे अक्सर type करते हैं
    • बहुत generic होने पर यह दूसरे commands से conflict कर सकता है या users को confuse कर सकता है
  • नाम में lowercase और जरूरत पड़ने पर dash ही इस्तेमाल करना बेहतर है
    • curl अच्छे नाम का उदाहरण है और DownloadURL अच्छा उदाहरण नहीं है
  • नाम छोटा होना चाहिए, लेकिन बहुत छोटे नाम cd, ls, ps जैसी बेहद आम utilities के लिए उपयुक्त होते हैं
  • नाम type करने में आसान होना चाहिए
    • Docker Compose का शुरुआती नाम plum था, लेकिन एक हाथ से type करने में असहज होने के कारण इसे fig में बदला गया था
  • संभव हो तो single binary के रूप में distribute करना चाहिए
    • अगर single binary मुश्किल हो, तो platform के default package installer का इस्तेमाल करके ऐसे तरीके से distribute करना चाहिए कि removal आसान हो
    • language-specific tools, जैसे code linters, यह मान सकते हैं कि user के पास उस language का interpreter है
  • removal आसान होना चाहिए
    • install करने के तुरंत बाद हटाना चाहने के मामले आम हैं, इसलिए removal instructions को installation instructions के नीचे रखना अच्छा है
  • usage metrics tool improvement में मदद कर सकते हैं, लेकिन CLI users उम्मीद करते हैं कि उनका अपने environment पर control होगा
  • consent के बिना usage या crash data नहीं भेजना चाहिए
    • यह स्पष्ट करना चाहिए कि क्या collect किया जा रहा है, क्यों collect किया जा रहा है, कितना anonymize किया जाता है, कैसे anonymize किया जाता है, और कितने समय तक रखा जाता है
    • आदर्श रूप से opt-in अच्छा है; अगर default collection यानी opt-out चुना जाए, तो website पर या first run के समय साफ़ बताना चाहिए और इसे बंद करना आसान होना चाहिए
  • analytics collection के alternatives पर भी विचार किया जा सकता है
    • web documentation को instrument करना
    • downloads को instrument करना
    • users से सीधे बात करना और documentation व repositories में feedback और feature requests को प्रोत्साहित करना

1 टिप्पणियां

 
GN⁺ 2024-02-07
Hacker News की राय
  • यह कहना सही है कि “आजकल ज़्यादातर लोगों को पता भी नहीं कि command line क्या होती है”, लेकिन TFA ने जिस 1980 के दशक को मानक माना है, तब भी यही स्थिति थी
    फर्क यह है कि आज command line को जानने और इस्तेमाल कर सकने वाले लोगों की संख्या इतिहास में सबसे ज़्यादा है, कम से कम एक अंक के गुणक से, शायद दो अंकों के गुणक तक बढ़ी है, इसलिए इसे CLI का स्वर्ण युग कहा जा सकता है

    • monolith को तोड़ने के लिए app के कुछ हिस्सों में command-line tools जोड़ रहा हूं
      global state और dependencies reasoning में बाधा डालती हैं, और आखिरकार debugging और performance optimization को भी मुश्किल बना देती हैं
      500 lines, 1,000 lines, 5,000 lines, 10,000 lines, कभी-कभी 50,000 lines के code को अलग से execute होने लायक निकाल दें, तो बहुत कुछ कहीं ज़्यादा स्पष्ट हो जाता है
      सही तरीके से किया जाए तो यह Functional Core, Imperative Shell structure भी ला सकता है, क्योंकि Unix philosophy के अनुरूप command line में side-effect-free operations ज़्यादा और side-effect वाले operations कम होने चाहिए
      ऐसा छोटा command बनाया जा सकता है जो किसी खराब निर्णय से ठीक पहले की system state generate करके output करे, और production environment में भी व्यावहारिक रूप से सुरक्षित रूप से चलाया जा सके
      फिर bus factor में शामिल होने चाहिए ऐसे व्यक्ति को भी ऐसे tools देकर शामिल कराना आसान हो जाता है
    • “लोग” को “computer users” से बदल दें तो लेखक का मुद्दा सही है
      दूर-दराज़ Amazon की किसी सभ्यता के गांव का व्यक्ति terminal के बारे में क्या सोचता है, यह relevant नहीं है
    • absolute number और ratio में फर्क करना चाहिए
      जिस चीज़ की quantity बढ़ी है, उसके qualitative change को आंकना हो तो ratio देखना चाहिए; केवल absolute number देखने पर बात सच तो होती है, लेकिन अर्थहीन निकलती है
      उदाहरण के लिए, आज jazz listeners की absolute संख्या genre के cultural heyday से ज़्यादा हो सकती है, लेकिन ऐसा jazz के अधिक popular होने से नहीं, बल्कि music सुनने वाले लोगों की संख्या बढ़ने से है
      फिर भी यह कहना मुश्किल है कि America में jazz अपने peak समय से अधिक महत्वपूर्ण और प्रभावशाली है
    • असली सवाल यह है कि 1980 के दशक के computer users में ratio के हिसाब से भी क्या ऐसा ही था
  • मैं चाहता हूं कि बिना वास्तविक बदलाव किए पहले से दिखाने वाला --dry-run option भी consider किया जाए कि कौन-सा काम होगा
    tool सीखते समय, या rollback मुश्किल काम चलाने से पहले complex options और file globs सही लिखे हैं या नहीं, यह check करने में यह वाकई उपयोगी है

    • अगर command को undo नहीं किया जा सकता और side effects बड़े हैं, तो default को --dry-run रखना और वास्तविक execution के लिए --execute flag मांगना बेहतर है
    • PowerShell का WhatIf मेरी सबसे पसंदीदा features में से एक है
      इसके बिना कैसे काम चलता, पता नहीं; इसने कई बार पूरी तरह बर्बादी के कगार से बचाया है
    • उल्टा, मैं default behavior को वास्तविक बदलाव न करने वाला बनाना पसंद करता हूं, और सच में चलाने के लिए --commit पास कराना बेहतर मानता हूं
      जिन scripts में irreversible या मुश्किल से undo होने वाले काम होते हैं, उनमें यह तरीका अधिक सुरक्षित लगता है
    • dry run flag वाले command-line tools के उदाहरण जानना चाहता हूं
      जो tools बना रहा हूं, उनमें इसे कैसे design करूं, इसे लेकर confusion है
      अगर data लाने के लिए API call करनी हो, तो उसे dry run कैसे बनाया जाए, समझ नहीं आता
      क्या fake example और fake output देना होगा?
    • मेरे हिसाब से dry-run ऐसा function होना चाहिए जिसे किसी भी command से pipe किया जा सके: do_thing.py | dry-run
      इसे prompt में “काम की प्रक्रिया step-by-step समझाओ” मांगने जैसा समझ सकते हैं
  • बात सिर्फ इतनी नहीं होनी चाहिए कि standard output interactive terminal न हो तो animation न दिखाएं; बल्कि stdout पर animation कभी भी नहीं दिखाना चाहिए
    TFA कुल मिलाकर अच्छा था, लेकिन stderr और stdout का फर्क समझाने वाला हिस्सा ढूंढते हुए यह देखकर निराशा हुई कि ऐसा नहीं किया गया
    stderr सिर्फ errors के लिए नहीं, बल्कि logs और सभी informational output के लिए सही जगह है, और अगर terminal हो तो animation भी वहीं डाली जा सकती है
    stdout वास्तविक, उपयोगी output होना चाहिए, और terminal है या नहीं, इससे independent consistent होना चाहिए
    उदाहरण के लिए echo foo | mysed 's/oo/aa/' | cat में mysed का stdout faa है, और stderr में version info या found content जैसे logs जाने चाहिए
    मैं actual output पाने के लिए grep से tool के साथ लड़ना नहीं चाहता, और यह भी नहीं चाहता कि | cat हटाने पर behavior बदल जाए और debugging मुश्किल हो जाए

    • “stdout useful output है” नियम को थोड़ा refine करें तो stdout वही होना चाहिए जो user ने request किया हो
      अगर --help request किया है तो उसे stdout पर जाना चाहिए, और अगर logs request किए हैं तो logs भी stdout पर जाने चाहिए
      अगर information request नहीं की गई है, तो stderr सही है
    • rule अच्छा है, लेकिन नाम अफसोसजनक है
      अगर समय पीछे ले जा पाते तो stdin, stdout, stdext जैसे नाम रखते, तो शायद लोग इस convention को follow करते
      लेकिन नाम stderr है, इसलिए developer तर्कसंगत रूप से इसे “error reporting” के लिए मानता है, और error न हो तो stdout में डाल देता है
      फिर भी program structure के लिहाज़ से यह तरीका बेहतर है, और शुरुआत में ज़्यादा confusing हो सकता है, लेकिन output से ज़्यादा useful काम करवाने का फायदा मिलता है
    • तो फिर animation कहां दिखानी चाहिए, यह जानना चाहता हूं
      colors को भी information मानना मुश्किल है, मेरे हिसाब से
  • “जहां clarity आए, वहां symbols और emoji इस्तेमाल करें” वाली सलाह से कृपया बचना चाहिए
    उदाहरण में दिया गया yubikey-agent GitHub README और खिलंदड़े user interface में नापसंद आने वाली चीज़ों को साफ दिखाता है
    technically, symbols और emoji अलग-अलग terminals में अलग तरह से render हो सकते हैं और messages को confusing बना सकते हैं
    aesthetically भी, मज़ाकिया और चुलबुले अंदाज़ के प्रति tolerance लोगों में बहुत अलग-अलग होती है, इसलिए इन्हें बहुत संयम से और तभी इस्तेमाल करना चाहिए जब सचमुच पता हो कि क्या कर रहे हैं

    • मुझे ऐसा output पसंद है
      colored terminal output भी पसंद है, और emoji में भी color होता है, जिससे स्थिति की overall picture जल्दी समझने में मदद मिलती है
      syntax highlighting भी पसंद है, और उसके बिना code पढ़ना काफी मुश्किल लगता है
      हर कोई ऐसा नहीं है; जैसे मैं उम्मीद नहीं करता कि मेरी पसंद default बने, वैसे ही विपरीत पसंद भी default के रूप में थोपनी नहीं चाहिए
    • अगर यह optional feature हो तो अच्छा है
      कुछ लोग पसंद करते हैं और कुछ नापसंद, इसलिए default off रखें लेकिन user को चुनने दें
    • guideline के तौर पर, output में इस्तेमाल होने वाली emoji vocabulary को अधिकतम दो तक सीमित रखना अच्छा होगा
      उदाहरण के लिए एक success के लिए, एक failure के लिए—इतना काफी है
      और emoji जो information देती है, उसे text में भी ज़रूर duplicate करके देना चाहिए
    • जोरदार सहमति
      जब पहली बार CLI Guidelines देखी थीं, तो उसी section पर पढ़ना बंद कर दिया था
      इस बार बाकी हिस्सा भी पढ़ा, और कुल मिलाकर यह काफी ठीक लगा
  • मैं समझता हूँ कि कुछ CLI, जैसे aws, इतने बड़े होते हैं कि nesting ज़रूरी हो जाती है, लेकिन nested CLI में अंदर तक जाते रहना सच में बहुत झुंझलाहट भरा है
    ज़्यादातर ऐप्स के लिए बेहतर है कि वे help में सारे options दिखा दें और मुझे less से अपनी ज़रूरत की चीज़ ढूँढने दें

    • मैं बहुत सारे TUI ऐप बना रहा हूँ, और हर ऐप में कम technical लोगों, जैसे QA, के इस्तेमाल के लिए एक अच्छा TUI frontend जोड़ता हूँ
      यह TUI चाहें तो इस्तेमाल करने वाला pure UI/UX है, और चुनी हुई settings को किसी अलग generated file या function में पास करता है
      वह file या function हमेशा terminal से सीधे call किया जा सकता है, और TUI में इस्तेमाल होने वाले सभी options और help भी उपलब्ध कराता है
      इसलिए इसे script में भी इस्तेमाल किया जा सकता है, और यह अलग-अलग skill level वाले users के लिए उपयोगी है
    • यह subcommands की संख्या और वे commands कितनी स्पष्ट हैं, इस पर निर्भर करता है
      अगर आपको ज़रूरी subcommand पता है, तो options को केवल ज़रूरी चीज़ों तक घटा देना काफी उपयोगी है, लेकिन अगर नहीं पता तो यह तकलीफ़देह हो सकता है
      options की बड़ी list को grep से खंगालना भी मुश्किल है, इसलिए balance चाहिए
    • क्या यह man pages का काम नहीं है?
    • subcommand के --help को parent command में expand करके डालने का तरीका मददगार हो सकता है
      उदाहरण के लिए, git stash --help हर item सहित git stash की help ज्यों की त्यों दिखाए
  • “परंपरागत रूप से UNIX commands मुख्यतः इस धारणा के साथ लिखे गए थे कि उन्हें दूसरे programs इस्तेमाल करेंगे” यह व्याख्या सही नहीं है
    मूल रूप से वे login shell के अंदर interactive use के लिए ही ज़्यादा intended थे
    stdout पर output बनाने वाले programs (ls, cat, find, tty, who, date) और शांत text filters (tr, grep, cut, uniq, sort, wc) थे, और उस दौर में एक-line commands से basic computing tasks किए जा सकते थे
    जटिल programs C में लिखे जाते थे, और sed तथा AWK जैसी domain-specific languages आने के बाद string processing ज़्यादा करने वाले कुछ programs shell में चले गए
    shell कोई सामान्य programming environment नहीं है, और न ही उसे कभी उस उद्देश्य के लिए design किया गया था

    • कभी 10,000 lines का C program shell की 10 lines में हो जाता है, और कभी 1,000 lines का shell program C की 100 lines में हो सकता था
      आजकल दोनों ही काम Python या Lua में करना अक्सर बेहतर होता है, लेकिन shell और C सबसे व्यापक रूप से installed मिलते हैं
    • सामान्य हो या न हो, shell एक programming language है, और शुरुआती Unix में यह बात कहीं ज़्यादा स्पष्ट थी
      sh, bash, ksh, csh में बँट जाना भी इसका अच्छा उदाहरण है
      standard POSIX toolset को कई shell languages की standard library के रूप में देखना काफी उचित लगता है
  • आज की Unix command line एक तरफ “बेहद उपयोगी” है, और दूसरी तरफ design के स्तर पर टूटी हुई है
    नीचे वाली चीज़ C या Rust में लिखने में कितना समय लगेगा, यह सोचें तो इसकी उपयोगिता साफ़ है:
    curl -sS https://go.dev/doc/devel/release | html2text | grep -o -P '\bgo\d+\.\d+\.\d+\b' | sort -V | uniq | tail -1
    लेकिन यह design के स्तर पर क्यों टूटी है, इसके लिए https://news.ycombinator.com/item?id=29747034 देखें
    समस्या यह है कि command-line interface को इंसानों के पढ़ने लायक और साथ ही machines के पढ़ने लायक होना चाहिए, और इसे हल करने का कोई standard तरीका नहीं है

    • वह उदाहरण खुद ही अच्छी तरह दिखाता है कि यह design के स्तर पर क्यों टूटी है
      इंसान और machine दोनों के एक साथ पढ़ सकने की समस्या का शायद कोई standard solution हो सकता था
      Apple ने desktop UI के visual abstraction के अर्थ को concrete बनाने के लिए Human Interface Guidelines बनाई थीं
      लेकिन command line उन लोगों ने नहीं बनाई थी जो Apple designers की तरह सोचते थे, बल्कि उन लोगों ने बनाई थी जो सोचते थे कि “laziness, impatience और hubris virtues हैं, तो मैं जो चाहता हूँ उसे minimum code में कैसे व्यक्त करूँ”
      उस समय यह गलत चुनाव भी नहीं था और हर byte मायने रखता था, लेकिन वह design decision अब ऐसे toolchain में धँस चुका है जिसे हिलाया नहीं जा सकता
      लगता है कि इससे बेहतर कुछ पाने के लिए POSIX toolchain को लगभग छोड़ना पड़ेगा, और मौजूदा आधार पर discoverable और conceptually consistent UX बनाना कल्पना करना मुश्किल है
    • computers आखिरकार हमारी सेवा के लिए हैं, इसलिए अंतिम समाधान machine को इंसान जितना अच्छा पढ़ने लायक बनाना होना चाहिए
    • असल में यह “एक साथ” से ज़्यादा आम तौर पर यह है कि इंसान और machine एक ही command को अलग-अलग समय पर इस्तेमाल करते हैं
      एक ही समय पर भी अलग-अलग output संभव करने के कई तरीके हैं
      बस कोई standard चाहिए जिसका सभी पालन करें, और जटिलता ठीक उसी जगह शुरू होती है
    • वह उदाहरण design के स्तर पर टूटे होने को साबित नहीं करता, बल्कि अपेक्षाकृत आसान समाधान भी दिखाता लगता है
      अगर समस्या यह है कि ls implementations में बहुत कम ऐसी हैं जो filenames को newline के बजाय NUL character से terminate करने देती हैं, तो समाधान इतना स्पष्ट दिखता है कि लगता है मैं कुछ miss कर रहा हूँ
      क्या shell interface किसी वजह से इसे reject करता है?
    • लेख में जिस तरीके की बात है वह --json जैसा machine-readable output mode है
  • “सीक्रेट वैल्यूज़ को environment variables से न पढ़ें” कहते हुए credentials file, pipe, AF_UNIX socket, secret management service, और अन्य inter-process communication सुझाए गए हैं; इनमें से कौन-सा सबसे सुविधाजनक और portable है, यह जानने की उत्सुकता है
    यह भी जानना चाहूँगा कि secret management service सिर्फ काम में इस्तेमाल होती है या personal projects में भी

    • CLI Guidelines के लेखकों में से एक हूँ
      command line में secret values को संभालने पर थोड़ा और गहराई से लिखा लेख https://smallstep.com/blog/command-line-secrets/ पर है
      credentials file सरल और portable विकल्प है
      files में पहले से permissions model होता है, और वे external services या proprietary APIs पर निर्भर नहीं होतीं
      अगर कोई program credentials file स्वीकार करता है, तो वह systemd credentials के साथ भी compatible होता है
      systemd credentials, unencrypted credentials files की तुलना में अधिक सुरक्षित हैं; वे encrypted होते हैं और उन्हें TPM से बाँधा भी जा सकता है, लेकिन credentials इस्तेमाल करने वाले software को खुद TPM support करने की जरूरत नहीं होती
    • अच्छा होगा अगर program secret value लाने वाला command specify करने दे
      उदाहरण के लिए mbsync(https://isync.sourceforge.io/mbsync.html) में IMAP authentication password देने के करीब तीन तरीके हैं
      अगर password set न करें तो run time पर prompt आता है, और config file में plaintext password भी डाला जा सकता है, लेकिन share करने के लिए यह असुविधाजनक है
      साथ ही password लाने वाला command set किया जा सकता है, जिससे pass(1)(https://www.passwordstore.org/) जैसे password manager या interactive graphical prompt को काम सौंपा जा सकता है
    • secret management service शायद सबसे सुविधाजनक होगी
      documentation अच्छी होने के कारण, खुद से अतिरिक्त कुछ बनाए बिना आसानी से setup किया जा सकता है
      Doppler(https://Doppler.com) या AWS Secrets Manager(https://aws.amazon.com/secrets-manager/) जैसे secret managers का फायदा है कि वे secret values को सुरक्षित जगह पर protect करते हैं और उनके exposure को न्यूनतम करते हैं
      यहाँ तक कि internal developers के लिए भी exposure कम किया जा सकता है, जिससे उन data leaks को रोकने में मदद मिलती है जिन्हें आसानी से टाला जा सकता था
      ऐसे leaks पूरी company को जोखिम में डाल सकते हैं और लगातार अधिक आम होते जा रहे हैं
  • संबंधित लेख: Command Line Interface Guidelines - https://news.ycombinator.com/item?id=38053692 - अक्टूबर 2023, 1 comment
    Command Line Interface Guidelines - https://news.ycombinator.com/item?id=31651161 - जून 2022, 1 comment
    Command Line Interface Guidelines - https://news.ycombinator.com/item?id=25492119 - दिसंबर 2020, 5 comments

  • clipboard से paste की गई string के अंत में newline character हो तो कुछ terminals का अपने-आप command execute कर देना सच में परेशान करता है
    निजी तौर पर मुझे लगता है कि command-line interface को ऐसा नहीं करना चाहिए

    • Bash में bind 'set enable-bracketed-paste on' इस्तेमाल कर सकते हैं
    • macOS का iTerm newline वाली string paste करने पर confirmation माँगता है
      अगर परेशान करे तो इसे बंद भी किया जा सकता है
    • Fish shell default रूप से उम्मीद के मुताबिक सिर्फ insert करता है, और execute करने से पहले command edit करने देता है
      जरूरत हो तो multiple lines भी संभव हैं, और Enter दबाने पर ही execute होता है
      Fish shell के defaults अक्सर sensible रहे हैं, और prompt के अलावा अभी तक कुछ खास customize करने लायक नहीं मिला
    • clipboard manager आज़माने लायक है
      मैंने जो इस्तेमाल किए हैं, उनमें से ज्यादातर में clipboard content से newline हटाने का option था
    • अगर पता हो कि newline अधिकतम एक ही होगा, तो पहले # type करके paste करता हूँ
      newline interpret हो भी जाए तो पूरी line comment बन जाती है, इसलिए safe है; असल में execute करने से पहले line की शुरुआत से बस # हटा देना होता है