कमांड-लाइन इंटरफेस दिशानिर्देश (2021)
(clig.dev)- यह गाइड पारंपरिक 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 का उपयोग करना चाहिए
- 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 सही तरह से काम करें
- machine-readable output भी default रूप से
- 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 लेना है औरstdininteractive 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 के बिना भी काम करती है
manpages देने पर विचार किया जा सकता है- कई users पहले
man mycmdदेखते हैं gitऔरnpmकी तरहhelpsubcommand के ज़रिएmanpages access किए जा सकते हैं
- कई users पहले
आउटपुट के सिद्धांत
- इंसानों के लिए पढ़ने में आसान आउटपुट सबसे महत्वपूर्ण है
- यह तय करने का सरल मानदंड कि कोई खास output stream इंसान द्वारा पढ़ी जा रही है या नहीं, यह है कि वह TTY है या नहीं
- उपयोगिता को नुकसान पहुंचाए बिना machine-readable आउटपुट देना चाहिए
- plain text lines की stream UNIX का सार्वभौमिक इंटरफ़ेस है
- उपयोगकर्ता उम्मीद करते हैं कि output को
grepजैसे टूल में पास करने पर वह अपेक्षा के मुताबिक काम करेगा
- अगर human-friendly आउटपुट machine-friendly आउटपुट को तोड़ता है, तो
--plainदिया जा सकता है- table output में cells को कई लाइनों में बांटने से “एक record एक line” वाली अपेक्षा टूट सकती है
--plainscripts के लिए बिना छेड़छाड़ वाला table-format आउटपुट देता है
- अगर
--jsonपास किया गया है, तो formatted JSON आउटपुट करना चाहिए- JSON जटिल data structures को संभालना आसान बनाता है, और
jqव कई JSON CLI tools के साथ इस्तेमाल किया जा सकता है - web services और
curlके जरिए सीधे pipe से जोड़ने के लिए भी उपयुक्त है
- JSON जटिल data structures को संभालना आसान बनाता है, और
- सफलता पर आउटपुट दें, लेकिन उसे छोटा रखें
- पारंपरिक UNIX commands अक्सर कोई समस्या न होने पर आउटपुट नहीं देते, लेकिन इंसान को यह अटका हुआ लग सकता है
- scripts के लिए no-output चाहिए तो
-qoption से गैर-ज़रूरी आउटपुट छिपाया जा सकता है
- state बदलने वाली commands को उपयोगकर्ता को बताना चाहिए कि क्या बदला है
git pushचल रहे काम और remote branch की नई state दिखाने वाला उदाहरण है
- system की मौजूदा state आसानी से देखी जा सकनी चाहिए
git statusrepository की state और आगे चलाए जा सकने वाले commands के hints साथ में दिखाता है
- program की आंतरिक दुनिया की सीमा पार करने वाले काम आम तौर पर explicit होने चाहिए
- जब वह files पढ़ता या लिखता है जिन्हें उपयोगकर्ता ने arguments में नहीं दिया
- जब वह remote server से communication करके files डाउनलोड करता है
- रंगों का इस्तेमाल इरादे के साथ करना चाहिए
- बहुत ज्यादा इस्तेमाल करने पर उनका अर्थ खत्म हो जाता है और पढ़ना मुश्किल हो जाता है
- अगर TTY नहीं है, या
NO_COLORset है, याTERM=dumbहै, या--no-colorपास किया गया है, तो colors बंद कर देने चाहिए
- अगर
stdoutinteractive terminal नहीं है, तो animations आउटपुट नहीं करनी चाहिए- इससे CI logs में progress indicators के गड़बड़ दिखने से बचा जा सकता है
- बहुत ज्यादा text आउटपुट करते समय
lessजैसे pager का इस्तेमाल किया जा सकता है- बेहतर है कि इसे केवल तब इस्तेमाल करें जब
stdinयाstdoutinteractive 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.txtflags हैं
- जहां संभव हो, 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 देने का तरीका देना चाहिए
- अगर
stdininteractive terminal नहीं है, तो prompt छोड़कर जरूरी flags या arguments मांगने चाहिए
- खतरनाक operations से पहले confirmation लेना चाहिए
- interactive run में
yयाyesटाइप करवाया जा सकता है - non-interactive run में
-fया--forceमांगा जा सकता है - गंभीर operations में deletion target का नाम सीधे टाइप करवाया जा सकता है या
--confirm="name-of-thing"जैसा flag दिया जा सकता है
- interactive run में
- अगर file input/output लेते हैं, तो
-सेstdinयाstdoutsupport करना चाहिए- इससे temporary files के बिना दूसरी commands के output से जोड़ा जा सकता है
- जहां संभव हो, arguments, flags और subcommands के order को independently handle करना चाहिए
- क्योंकि उपयोगकर्ता अक्सर पिछली command के अंत में option जोड़कर फिर से run करते हैं
- secrets को सीधे flags से नहीं पढ़ना चाहिए
--passwordvaluepsoutput या shell history में expose हो सकती है--password-fileजैसे file input याstdinपर विचार करना चाहिए
interaction
- prompts या interactive elements केवल तब इस्तेमाल करने चाहिए जब
stdinTTY हो- 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 से आगे जारी रहना चाहिए
- temporary failure के बाद
- संभव हो तो 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इस्तेमाल करने के लिए प्रेरित करना चाहिए
- यूज़र को scripts में stable output के लिए
- catch-all subcommands से बचना चाहिए
- अगर known subcommand नहीं है तो उसे अपने-आप
runमान लेने का तरीका, बाद में नया subcommand जोड़ते समय मौजूदा usage तोड़ सकता है
- अगर known subcommand नहीं है तो उसे अपने-आप
- 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 को
envcommand के साथ इस्तेमाल करने पर usability issues आते हैं
- multi-line values को
- व्यापक रूप से इस्तेमाल होने वाले names पर मनमाने ढंग से कब्ज़ा नहीं करना चाहिए
- POSIX standard environment variables की list का reference लिया जा सकता है
- जहाँ संभव हो, general-purpose environment variables check करने चाहिए
NO_COLOR,FORCE_COLORDEBUGEDITORHTTP_PROXY,HTTPS_PROXY,ALL_PROXY,NO_PROXYSHELLTERM,TERMINFO,TERMCAPTMPDIRHOMEPAGERLINES,COLUMNS
- उपयुक्त मामलों में
.envसे environment variables पढ़े जा सकते हैं- यह उन variables के लिए उपयोगी है जो किसी particular directory में काम करते समय शायद ही बदलते हैं
.envformal 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_UNIXsocket, secret management service, या किसी अन्य IPC method से लेना चाहिए
- environment variables processes, logs,
नाम, 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में बदला गया था
- Docker Compose का शुरुआती नाम
- संभव हो तो 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 टिप्पणियां
Hacker News की राय
यह कहना सही है कि “आजकल ज़्यादातर लोगों को पता भी नहीं कि command line क्या होती है”, लेकिन TFA ने जिस 1980 के दशक को मानक माना है, तब भी यही स्थिति थी
फर्क यह है कि आज command line को जानने और इस्तेमाल कर सकने वाले लोगों की संख्या इतिहास में सबसे ज़्यादा है, कम से कम एक अंक के गुणक से, शायद दो अंकों के गुणक तक बढ़ी है, इसलिए इसे CLI का स्वर्ण युग कहा जा सकता है
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 देकर शामिल कराना आसान हो जाता है
दूर-दराज़ Amazon की किसी सभ्यता के गांव का व्यक्ति terminal के बारे में क्या सोचता है, यह relevant नहीं है
जिस चीज़ की quantity बढ़ी है, उसके qualitative change को आंकना हो तो ratio देखना चाहिए; केवल absolute number देखने पर बात सच तो होती है, लेकिन अर्थहीन निकलती है
उदाहरण के लिए, आज jazz listeners की absolute संख्या genre के cultural heyday से ज़्यादा हो सकती है, लेकिन ऐसा jazz के अधिक popular होने से नहीं, बल्कि music सुनने वाले लोगों की संख्या बढ़ने से है
फिर भी यह कहना मुश्किल है कि America में jazz अपने peak समय से अधिक महत्वपूर्ण और प्रभावशाली है
मैं चाहता हूं कि बिना वास्तविक बदलाव किए पहले से दिखाने वाला
--dry-runoption भी consider किया जाए कि कौन-सा काम होगाtool सीखते समय, या rollback मुश्किल काम चलाने से पहले complex options और file globs सही लिखे हैं या नहीं, यह check करने में यह वाकई उपयोगी है
--dry-runरखना और वास्तविक execution के लिए--executeflag मांगना बेहतर हैइसके बिना कैसे काम चलता, पता नहीं; इसने कई बार पूरी तरह बर्बादी के कगार से बचाया है
--commitपास कराना बेहतर मानता हूंजिन scripts में irreversible या मुश्किल से undo होने वाले काम होते हैं, उनमें यह तरीका अधिक सुरक्षित लगता है
जो tools बना रहा हूं, उनमें इसे कैसे design करूं, इसे लेकर confusion है
अगर data लाने के लिए API call करनी हो, तो उसे dry run कैसे बनाया जाए, समझ नहीं आता
क्या fake example और fake output देना होगा?
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का stdoutfaaहै, और stderr में version info या found content जैसे logs जाने चाहिएमैं actual output पाने के लिए grep से tool के साथ लड़ना नहीं चाहता, और यह भी नहीं चाहता कि
| catहटाने पर behavior बदल जाए और debugging मुश्किल हो जाएअगर
--helprequest किया है तो उसे stdout पर जाना चाहिए, और अगर logs request किए हैं तो logs भी stdout पर जाने चाहिएअगर information request नहीं की गई है, तो stderr सही है
अगर समय पीछे ले जा पाते तो stdin, stdout, stdext जैसे नाम रखते, तो शायद लोग इस convention को follow करते
लेकिन नाम stderr है, इसलिए developer तर्कसंगत रूप से इसे “error reporting” के लिए मानता है, और error न हो तो stdout में डाल देता है
फिर भी program structure के लिहाज़ से यह तरीका बेहतर है, और शुरुआत में ज़्यादा confusing हो सकता है, लेकिन output से ज़्यादा useful काम करवाने का फायदा मिलता है
colors को भी information मानना मुश्किल है, मेरे हिसाब से
“जहां clarity आए, वहां symbols और emoji इस्तेमाल करें” वाली सलाह से कृपया बचना चाहिए
उदाहरण में दिया गया yubikey-agent GitHub README और खिलंदड़े user interface में नापसंद आने वाली चीज़ों को साफ दिखाता है
technically, symbols और emoji अलग-अलग terminals में अलग तरह से render हो सकते हैं और messages को confusing बना सकते हैं
aesthetically भी, मज़ाकिया और चुलबुले अंदाज़ के प्रति tolerance लोगों में बहुत अलग-अलग होती है, इसलिए इन्हें बहुत संयम से और तभी इस्तेमाल करना चाहिए जब सचमुच पता हो कि क्या कर रहे हैं
colored terminal output भी पसंद है, और emoji में भी color होता है, जिससे स्थिति की overall picture जल्दी समझने में मदद मिलती है
syntax highlighting भी पसंद है, और उसके बिना code पढ़ना काफी मुश्किल लगता है
हर कोई ऐसा नहीं है; जैसे मैं उम्मीद नहीं करता कि मेरी पसंद default बने, वैसे ही विपरीत पसंद भी default के रूप में थोपनी नहीं चाहिए
कुछ लोग पसंद करते हैं और कुछ नापसंद, इसलिए default off रखें लेकिन user को चुनने दें
उदाहरण के लिए एक success के लिए, एक failure के लिए—इतना काफी है
और emoji जो information देती है, उसे text में भी ज़रूर duplicate करके देना चाहिए
जब पहली बार CLI Guidelines देखी थीं, तो उसी section पर पढ़ना बंद कर दिया था
इस बार बाकी हिस्सा भी पढ़ा, और कुल मिलाकर यह काफी ठीक लगा
मैं समझता हूँ कि कुछ CLI, जैसे
aws, इतने बड़े होते हैं कि nesting ज़रूरी हो जाती है, लेकिन nested CLI में अंदर तक जाते रहना सच में बहुत झुंझलाहट भरा हैज़्यादातर ऐप्स के लिए बेहतर है कि वे help में सारे options दिखा दें और मुझे
lessसे अपनी ज़रूरत की चीज़ ढूँढने देंयह TUI चाहें तो इस्तेमाल करने वाला pure UI/UX है, और चुनी हुई settings को किसी अलग generated file या function में पास करता है
वह file या function हमेशा terminal से सीधे call किया जा सकता है, और TUI में इस्तेमाल होने वाले सभी options और help भी उपलब्ध कराता है
इसलिए इसे script में भी इस्तेमाल किया जा सकता है, और यह अलग-अलग skill level वाले users के लिए उपयोगी है
अगर आपको ज़रूरी subcommand पता है, तो options को केवल ज़रूरी चीज़ों तक घटा देना काफी उपयोगी है, लेकिन अगर नहीं पता तो यह तकलीफ़देह हो सकता है
options की बड़ी list को grep से खंगालना भी मुश्किल है, इसलिए balance चाहिए
manpages का काम नहीं है?--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 किया गया था
आजकल दोनों ही काम Python या Lua में करना अक्सर बेहतर होता है, लेकिन shell और C सबसे व्यापक रूप से installed मिलते हैं
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 तरीका नहीं है
इंसान और 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 बनाना कल्पना करना मुश्किल है
एक ही समय पर भी अलग-अलग output संभव करने के कई तरीके हैं
बस कोई standard चाहिए जिसका सभी पालन करें, और जटिलता ठीक उसी जगह शुरू होती है
अगर समस्या यह है कि
lsimplementations में बहुत कम ऐसी हैं जो 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 में भी
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 करने की जरूरत नहीं होती
उदाहरण के लिए 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 को काम सौंपा जा सकता है
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 को ऐसा नहीं करना चाहिए
bind 'set enable-bracketed-paste on'इस्तेमाल कर सकते हैंअगर परेशान करे तो इसे बंद भी किया जा सकता है
जरूरत हो तो multiple lines भी संभव हैं, और Enter दबाने पर ही execute होता है
Fish shell के defaults अक्सर sensible रहे हैं, और prompt के अलावा अभी तक कुछ खास customize करने लायक नहीं मिला
मैंने जो इस्तेमाल किए हैं, उनमें से ज्यादातर में clipboard content से newline हटाने का option था
#type करके paste करता हूँnewline interpret हो भी जाए तो पूरी line comment बन जाती है, इसलिए safe है; असल में execute करने से पहले line की शुरुआत से बस
#हटा देना होता है