1 पॉइंट द्वारा GN⁺ 2025-08-16 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Ghostty टीम ने GTK एप्लिकेशन को पूरी तरह से फिर से लिखा और GObject type system का सक्रिय रूप से उपयोग किया
  • इस प्रक्रिया में Zig भाषा के साथ इंटीग्रेशन और Valgrind के जरिए memory issues की जांच ने महत्वपूर्ण भूमिका निभाई
  • GObject system अपनाने से पहले की तुलना में memory management और custom widget implementation सरल हो गए
  • Valgrind का उपयोग करने के परिणामस्वरूप, Ghostty की memory safety में बड़ा सुधार अनुभव किया गया
  • नया Ghostty GTK अब source build का default बन गया है और इसे 1.2 release में शामिल किया जाएगा

परिचय

  • Ghostty एक cross-platform terminal emulator है जो macOS, Linux, FreeBSD को सपोर्ट करता है
  • हर platform पर native GUI framework का उपयोग करके इसे अलग बनाया गया है
    • macOS: Swift और Xcode आधारित large-scale application
    • Linux और BSD: GTK आधारित application, X11/Wayland आदि के साथ direct integration
    • common core Zig में लिखा गया है और C ABI-compatible API प्रदान करता है
  • मौजूदा संरचना में GTK application को फिर से लिखने का कारण मूल PR में देखा जा सकता है
  • यह लेख मुख्य रूप से GObject type system के साथ integration और Valgrind से सत्यापित memory issues पर केंद्रित है

GObject type system और Zig

  • GTK का उपयोग करने पर मूल रूप से GObject type system के साथ interface करना पड़ता है
  • पहले GObject system से बचते हुए reference counting के बिना Zig objects और GObject objects के lifecycle को सीधे मिलाने की कोशिश की गई, लेकिन बार-बार memory release ठीक से न होने की समस्या आई
    • उदाहरण: Zig की तरफ की memory free हो गई, लेकिन GTK की memory अभी भी जीवित थी, या इसका उल्टा बार-बार हुआ
  • यह approach केवल correctness की समस्या नहीं थी, बल्कि GTK की खास सुविधाओं (event signals, property binding, actions) का उपयोग भी कठिन बना देती थी
  • एक ठोस उदाहरण में config struct को reload करते समय उससे जुड़े सभी GUI elements को एकसमान तरीके से update होना चाहिए था, लेकिन यह प्रक्रिया जटिल और त्रुटिपूर्ण थी
    • अब Zig Config struct को wrap करने वाले reference-counted GhosttyConfig GObject से इसे manage किया जाता है, और property change notifications के जरिए बदलाव पूरे application में स्वाभाविक रूप से फैल जाते हैं
  • custom GObject widgets बनाना भी आसान हो गया, जिससे Blueprint जैसी आधुनिक GTK UI technologies का उपयोग संभव हुआ
    • हाल में Blueprint अपनाने से GTK titlebar tabs, animated bell border जैसी नई सुविधाएँ जोड़ना आसान हुआ

Valgrind, GTK, और Zig

  • पूरे development process में Valgrind की मदद से memory leaks, undefined memory access जैसी समस्याओं की व्यवस्थित जांच की गई
  • GTK application पर Valgrind चलाना कठिन है, और इसके लिए बड़े suppression files की जरूरत पड़ती है (80% GTK खुद, बाकी 3rd party libraries और GPU drivers)
  • बार-बार की गई जांच से ऐसे जटिल memory bugs पहले ही पकड़े जा सके जो केवल कुछ स्थितियों में ही सामने आते हैं
    • उदाहरण: अगर GObject WeakRef को ठीक से initialize न किया जाए, तो target object बाद में free होने पर undefined memory access होता है, जिसे Valgrind ने पहले ही पकड़ लिया
  • वास्तविक अनुभव में, Zig codebase के अंदर कुल केवल 2 issues (1 leak, 1 undefined access) मिले, और वे भी 3rd party C API integration के दौरान हुए
    • Zig के debug allocators और Valgrind integration features भी प्रभावी साबित हुए
  • बाकी मिले memory issues अधिकतर C API boundaries और GObject system के जटिल lifecycle management से जुड़े थे
    • निष्कर्षतः जटिल libraries के C API को सुरक्षित रूप से इस्तेमाल करने के लिए Valgrind जैसे tools जरूरी हैं
  • Zig की memory safety को सहारा देने वाली सुविधाएँ केवल सैद्धांतिक चर्चा तक सीमित नहीं हैं, बल्कि व्यावहारिक project experience में भी प्रभावी साबित हुईं

निष्कर्ष

  • यह Ghostty के GUI हिस्से को पांचवीं बार शुरुआत से फिर से बनाने का अनुभव था
    • GLFW, macOS SwiftUI, macOS AppKit+SwiftUI, Linux GTK (procedural), Linux GTK+GObject type system के क्रम में
  • बार-बार के rewrite process में हर बार नए सबक और तकनीकी विकास मिले
    • इस अनुभव का कुछ हिस्सा macOS project में भी लागू करने की योजना है
  • Ghostty GTK system maintainers के सक्रिय सहयोग पर भी जोर दिया गया
  • नया फिर से लिखा गया Ghostty GTK एप्लिकेशन अब source build का default बन गया है, और इसे 1.2 stable release में लागू किया जाएगा

1 टिप्पणियां

 
GN⁺ 2025-08-16
Hacker News टिप्पणियाँ
  • मैंने सीधे GTK के साथ काम नहीं किया है, लेकिन आपकी बात सुनकर लगा कि यह Zig में Godot bindings बनाते समय आने वाली समस्याओं से बहुत मिलता-जुलता है। Godot में classes, virtual methods, properties, signals जैसे OOP concepts बहुत हैं। और यह एक C API देता है जो इन सभी concepts को संभाल सकता है और user-defined objects व properties बनाने देता है। यह engine objects की lifetime management खुद करता है, और reference-counted objects की tree structure भी है। खासकर lifetime issues को Zig idioms के हिसाब से एक optimal API में समेटने की कोशिश करते समय चीज़ें बहुत जटिल हो जाती हैं। इन्हीं चिंताओं के चलते मैंने oopz library भी बनाई। अभी API की स्थिति यही है, और एक वास्तविक उदाहरण यहाँ देखा जा सकता है। मैं Ghostty frontend को Godot extension के रूप में भी बनाकर देखना चाहता हूँ

    • पहले मैंने किसी भाषा के लिए सीधे GTK bindings इस्तेमाल किए थे और वह काफ़ी असुविधाजनक अनुभव था। 98% चीज़ें ठीक थीं, लेकिन बाकी 2% में ऐसी स्थितियाँ थीं जहाँ “यह function object का reference लेता है या नहीं, यह दूसरे argument पर निर्भर करता है”, और इसी कारण object lifecycle analysis काफ़ी सिरदर्द बन गया था
    • धन्यवाद कहना चाहता हूँ, और साथ ही याद आया कि जब C# Godot code को performant बनाने की कोशिश की थी, तब engine types के साथ interop बहुत ज़्यादा होने से बार-बार allocations होती थीं, जो काफ़ी मुश्किल हिस्सा था। bindings बनाते समय क्या आपको भी ऐसी समस्याएँ मिलीं, यह जानना चाहूँगा
    • मुझे पता ही नहीं था कि Zig में Godot bindings बनाने का प्रोजेक्ट चल रहा है। मुझे Godot और Zig दोनों पसंद हैं, इसलिए इसे लेकर काफ़ी उत्साहित हूँ। आगे भी इस पर नज़र रखूँगा
  • यह अच्छा उदाहरण है कि अच्छी programming आखिरकार system द्वारा दिए गए तरीके के साथ तालमेल बिठाने में ही है। आप OOP या memory management के बारे में जो भी सोचें, अगर आप GTK का उपयोग करते हैं तो आपको किसी न किसी तरह GObject type system के साथ interface बनाना ही पड़ेगा। चाहें बचना चाहें, अंत में उससे बच नहीं सकते। लेकिन हमने बचने की कोशिश की, और उसका नतीजा यह हुआ कि reference-counted objects और non-reference objects की lifetimes को बाँधते समय पूरी तरह अव्यवस्था फैल गई। Ghostty GTK app में बार-बार ऐसे bugs आते थे जहाँ Zig memory free करने पर GTK memory free नहीं होती थी, या इसका उल्टा होता था

    • GTK की यह संरचना बनने की वजहों में Vala की उत्पत्ति भी शामिल है। Vala, C# से प्रेरित है, GObject का उपयोग करती है, और code को C में transpile करती है। इसलिए काफ़ी सारे GTK apps वास्तव में Vala में लिखे गए हैं। कभी-कभी लगता है कि अगर D भाषा का उपयोग किया गया होता तो शायद बेहतर रहता। D कई मायनों में compiled C# जैसा लगता है
    • किसी खराब system के आगे झुकना अच्छी बात नहीं, बल्कि एक practical choice है
  • OOP और memory management पर मेरी राय अलग हो सकती है, लेकिन इस बात से सहमत हूँ कि GTK इस्तेमाल करने पर GObject type system में उलझना लगभग तय है। इसलिए मैंने तय किया कि सीधे GTK का उपयोग ही न करूँ। unified UI theme की अपनी value है, लेकिन मेरी नज़र में GTK के फायदे इतने बड़े नहीं हैं कि उनकी कीमत चुकाकर उन्हें अपनाया जाए। open source apps में GTK के आसपास काम करने के अनुभव से मुझे यक़ीन हो गया कि GTK और GObject की सोच मेरे स्वभाव से मेल नहीं खाती। GTK के अस्तित्व से मुझे दिक्कत नहीं है। मैं बस इसे न इस्तेमाल करने का विकल्प चुनता हूँ, और मेरे लिए वह ठीक है, लेकिन कुछ लोगों का यह मानना अजीब लगता है कि यह चुनाव मानो मेरा अधिकार ही नहीं है। यह कई GUI toolkits में से सिर्फ़ एक है, और तकनीकी रूप से बहुत polished toolkit है, फिर भी कभी-कभी लगता है कि अगर GTK का share थोड़ा कम होता, तो शायद वही polish किसी ऐसे toolkit पर लगती जिसकी बुनियादी संरचना बेहतर होती। बेशक, जो मुझे अच्छा लगता है वह सबके लिए अच्छा हो, यह ज़रूरी नहीं। मैं जानना चाहता हूँ कि GTK इस्तेमाल करने वालों में कितने लोग मजबूरी में करते हैं और कितने लोग इसे सचमुच सबसे बेहतरीन toolkit मानते हैं

    • मैं भी इस बात से सहमत हूँ कि GTK और GObject की strongly opinionated style मेरी सोच से मेल नहीं खाती। मुझे Gnome ecosystem की दिशा भी काफ़ी हद तक अनुकूल नहीं लगती। Linux के लिए Ghostty में GTK का उपयोग एक बहुत practical choice है। Ghostty का Linux पर platform-native होने का लक्ष्य यहाँ परिभाषित है। GTK Linux पर सबसे व्यापक रूप से इस्तेमाल होती है, और ज़्यादातर app ecosystems में सबसे स्वाभाविक रूप से फिट बैठती है, इसलिए यह निर्णय लगभग अपरिहार्य था। आगे चलकर उम्मीद है कि libghostty के आधार पर third-party द्वारा कई तरह के frontends आएँगे। उदाहरण के तौर पर Wayland-native Ghostty frontend Wraith भी है। शानदार है
    • मुझे लगता है कि Linux पर GTK के व्यापक उपयोग की सबसे बड़ी वजह इसका “C binding” होना है। इसलिए लगभग हर भाषा के लिए bindings या तो उपलब्ध हैं या उन्हें auto-generate करना आसान है। दूसरी ओर, Qt, C++ और Python से कुछ ज़्यादा ही बँधा हुआ है, जिससे उसकी पहुँच कम हो जाती है। यह महत्वपूर्ण है कि developer जो भी भाषा इस्तेमाल करे, toolkit उसके पास जाकर उसे अपनाए। और जब कोई complex desktop app बनानी हो, तो पुरानी imperative UI toolkits वास्तव में practical साबित होती हैं, क्योंकि उनके widgets अच्छी तरह tested होते हैं और उनके patterns परिचित होते हैं। नए तरीक़ों में इसके उलट छोटी-छोटी चीज़ें भी खुद संभालनी पड़ती हैं, और जैसे ही चीज़ें थोड़ी complex होती हैं, काफ़ी मुश्किल हो जाती हैं
    • “GTK का उपयोग न करने का विकल्प है, लेकिन कुछ लोग मानो इसे दूसरों की choice मानते ही नहीं” — इस हिस्से पर आपको आमतौर पर किस तरह की आपत्तियाँ सुनने को मिलती हैं, यह जानना चाहूँगा। मेरी नज़र में GTK accessibility और non-Roman input जैसी चीज़ें काफ़ी अच्छी तरह संभालता है, और यह वे क्षेत्र हैं जिन्हें खुद से बनाने वाले developers अक्सर नज़रअंदाज़ कर देते हैं, इसलिए यही इसकी मुख्य प्रतिस्पर्धात्मक बढ़त लगती है
  • एक दिलचस्प तथ्य यह है कि Ghostty और कुछ अन्य GTK apps में अगर mouse window के बाहर जाकर वापस अंदर आता है, तो पहला scroll click अनदेखा हो जाता है। इसकी वजह 2015 में पहली बार रिपोर्ट हुआ एक बहुत पुराना bug है। Bug link। अभी तक इसे ठीक करने की कोई योजना नहीं है, और maintainer का रुख़ है कि Wayland का इंतज़ार किया जाए

    • दरअसल यह समस्या GTK की नहीं, बल्कि XInput2 की लगती है। हाँ, GTK चाहे तो Chromium द्वारा इस्तेमाल की जाने वाली heuristic जैसा workaround कर सकती है, लेकिन जड़ में यह ऊपर की परत, यानी XInput2 की समस्या है
    • उस bug report और उससे जुड़े issues पढ़ने पर पता चलता है कि इसे कई बार ठीक करने की कोशिश हुई, लेकिन अंततः कुछ heuristics पर निर्भर रहना पड़ा, और हर बार जिस समस्या को पकड़ा गया उससे भी गंभीर side effects पैदा होते रहे। आख़िरकार यह मूल रूप से X11 की बुनियाद से जुड़ी समस्या है, इसलिए जब तक उसका मूल समाधान नहीं होता, तब तक अन्य सुधारों का भी सीमित ही मतलब होगा। लेकिन X11 अब लगभग maintenance mode में है, इसलिए जब तक उसके समर्थक यह कहते रहेंगे कि “यह पूरी तरह काम करता है, और अतिरिक्त काम की ज़रूरत नहीं”, तब तक ज़्यादा उम्मीद नहीं की जा सकती। अंत में बचता यही है कि Wayland migration का इंतज़ार किया जाए
  • “मैंने हर चरण को Valgrind से verify किया” — यह सुनकर लगा कि बात बहुत obvious है, लेकिन सच कहूँ तो मैंने खुद ऐसा कभी नहीं किया, और दूसरे developers को भी ऐसा करते कम ही देखा है। आमतौर पर Valgrind तभी इस्तेमाल होता है जब कोई specific bug या performance regression सामने आए। अगर development के दौरान सक्रिय रूप से Valgrind (खासकर Memcheck, Helgrind) जैसे tools का उपयोग किया जाए, तो tool की stability बहुत बढ़ सकती है, और bugs भी introduce होते ही पकड़े जा सकते हैं, जिससे बाद में सैकड़ों commits खंगालने की मेहनत कम हो सकती है

    • मैं खुद C और C++ के साथ काम करते समय हमेशा नियमित रूप से valgrind का उपयोग करता रहा हूँ। valgrind और asan जिन errors को पकड़ते हैं, वे अक्सर तुरंत crash के रूप में सामने नहीं आते, बल्कि सूक्ष्म, कम दिखाई देने वाले, लेकिन बीच-बीच में उभरने वाले बहुत कठिन bugs बन जाते हैं, इसलिए उनका root cause ढूँढना बहुत मुश्किल होता है। इनमें security vulnerabilities भी शामिल हो सकती हैं। और जब छोटी-छोटी memory leaks इकट्ठी होती रहती हैं और बाद में कोई बड़ा issue पैदा होता है, तब पहले से जमा उन असंख्य छोटे leaks की वजह से असली कारण ढूँढना और भी कठिन हो जाता है। इसलिए proactive use बेहतर है
    • Valgrind, खासकर memcheck, को मैं bug reports में गहराई से debug करने से पहले आसानी से ठीक होने वाली समस्याओं को पहले पकड़ने के लिए proactively इस्तेमाल करता रहा हूँ। हालाँकि सबसे बड़ी समस्या इसका performance overhead है, जिसके कारण इसे interactive तरीके से चलाने का अनुभव अच्छा नहीं होता। फिर भी tests को एक बार Valgrind के साथ चलाना बहुत लाभदायक है
    • लेकिन Valgrind बहुत धीमा और महँगा है, इसलिए code edit-compile-test वाले सीधे iteration loop में इसे डालना कठिन है। testing cycles, जैसे nightly या automation, में इसका उपयोग हो सकता है, लेकिन सही integration के लिए अतिरिक्त काम करना पड़ेगा
  • Ghostty इस्तेमाल करते समय Mac पर nano में multi-line paste न कर पाना बहुत असुविधाजनक है। लगता है यह इस बात पर निर्भर करता है कि terminal “bracketed pasting” को कैसे handle करता है, लेकिन अजीब बात यह है कि iTerm2 या Terminal में यह समस्या नहीं होती

    • terminal replacement के रूप में Ghostty से 99% संतुष्ट हूँ, लेकिन copy-paste issues सचमुच निराशाजनक हैं और रोज़ सामने आते हैं
    • नए कंप्यूटर पर Ghostty को default terminal बनाने के बाद जो सबसे बड़ी कमी महसूस हुई, वह search feature का न होना है। आमतौर पर output में कुछ ढूँढने के लिए मैं shortcut का काफ़ी उपयोग करता हूँ, लेकिन यहाँ वह उपलब्ध नहीं है। वास्तव में issue में भी यही सबसे ज़्यादा माँगी गई सुविधा है
    • Ubuntu remote session में Ghostty के भीतर nano चल ही नहीं पाता
      $ nano
      Error opening terminal: xterm-ghostty.
      
      उसी environment में macOS Terminal या VS Code का integrated terminal ठीक से काम करता है
    • यह सचमुच एक bug हो सकता है, इसलिए bug report करने की सलाह दूँगा
    • Cmd+F जैसी command search का न होना सबसे ज़्यादा खलता है
  • सोच रहा हूँ कि अगर Zig की जगह Rust का उपयोग किया जाता, तो क्या memory errors रुक जातीं। ज़्यादातर समस्याएँ Zig/C interop से आईं, इसलिए लगता है Rust में भी कुछ ऐसी ही रहतीं। Go developer के नज़रिए से अंदाज़ा लगा रहा हूँ, लेकिन जब बड़े पैमाने पर C के साथ interop करना हो, तब क्या कोई ऐसी भाषा है जो और अधिक safety tools देती हो, यह जानने की उत्सुकता है

    • Rust होता तो एक समस्या ज़रूर रुक जाती, लेकिन बाकी समस्याएँ वही रहतीं। जैसा आपने कहा, असल समस्या पूरी तरह C API boundary और उसके semantics में थी, इसलिए वास्तविक safety wrapper की quality पर निर्भर करती। Rust का फायदा यह है कि वहाँ पहले से अच्छी तरह tested wrappers का ecosystem मौजूद है, इसलिए उस लिहाज़ से self-made Zig wrappers की तुलना में जोखिम कम होता, लेकिन अंततः अंतर बहुत बड़ा नहीं होता। उदाहरण के लिए, undefined memory access जिसे Rust शायद पकड़ लेता, वह वास्तव में इस PR में ठीक किया गया हिस्सा है। व्यवहार में गलत memory पहली frame में copy तो हुई थी, लेकिन उसका कहीं उपयोग या transmission नहीं हुआ, इसलिए वह गंभीर नहीं बनी। फिर भी वह निश्चित रूप से सही नहीं था
    • Rust में भी C/GObject के साथ FFI boundary पर manual memory और lifetime management की ज़रूरत पड़ती है। Rust का borrow checker बाहरी code की memory usage को verify नहीं कर सकता
    • लेख का एक मुख्य बिंदु यह भी है कि zig + valgrind के संयोजन से उम्मीद से कहीं कम memory issues मिले
    • Rust में C bindings लिखना कहीं ज़्यादा कठिन है। इसलिए हो सकता है कि Rust में GTK bindings बनाना ही व्यावहारिक न होता
  • Ghostty जैसे GPU-आधारित apps (Alacritty, WezTerm, Zed आदि) इस्तेमाल करते हुए वे मुझे तेज़ और बेहतर लगे। लेकिन विडंबना यह है कि ऐसे apps Nvidia drivers की सीमाओं को और साफ़ कर देते हैं। पहले GPU का उपयोग बहुत कम करता था, इसलिए पता नहीं चला, लेकिन Regolith i3wm जैसे compositor-रहित environments और sway/Wayland environments दोनों में screen sharing, sleep से resume, crashes जैसी चीज़ों में Nvidia drivers बहुत खराब निकले। कई versions (550/560/575/580) बदलकर भी देखा, सब एक जैसे थे। हाल ही में समझ आया कि वे पहले से ही इतने खराब थे

    • Wayland पर मेरा अनुभव भी ऐसा ही रहा। X11 पर compositing effects बंद कर देने से 1050Ti और पुराना AMD कार्ड (जिसे radeon driver चाहिए) दोनों बिना समस्या के ठीक चलते हैं। लेकिन Wayland पर stutter, crashes, broken rendering जैसी समस्याएँ थीं
  • मैं GTK type system को code पर हावी हुए बिना एक बड़ा app बना सका। लेकिन उसके बदले classes inherit या extend करने के बजाय, मैंने components के बीच सब कुछ केवल lambdas bind करके जोड़ा। नतीजा इतना गड़बड़ नहीं था, लेकिन जो developer पारंपरिक GTK style के आदी हों, उन्हें यह उलझनभरा लग सकता था

  • मुझे Ghostty को लेकर यह बढ़ा-चढ़ाकर दिखाई देने वाला उत्साह समझ नहीं आता। UI में tabs और context menu से आगे बहुत कुछ नहीं है, तो क्या इस तरह के integration work और rewrite का इतना मूल्य है? अंदाज़ा है कि शायद यह iTerm2 जैसी शक्तिशाली GUI environment तक बढ़ना चाहता है। Kitty OpenGL से tabs खुद draw करता है, इसलिए पूरी customization संभव है, और किसी जटिल framework में integrate करने में समय बर्बाद करने के बजाय वह बेहद practical features जल्दी लागू कर देता है, जैसे last command result को pager में wrap करके output देना। Kitty में remote support भी अच्छा है

    • Ghostty का UI सिर्फ tabs तक सीमित नहीं है; इसमें splits, “process exited” banner, close confirmation dialog, title change dialog, unsafe paste detection, animated alert bell, dropdown terminal, progress bar जैसी कई चीज़ें हैं। Mac पर Apple Shortcuts और Spotlight integration भी है। बेशक, इन सबके बिना भी pure implementation किया जा सकता था, लेकिन Ghostty का mission हर platform की native toolkit का उपयोग करके app को “वास्तव में native” महसूस कराना है। अगर यह approach पसंद नहीं, तो Kitty की तरह text tabs वाला विकल्प भी अच्छा है। यह अलग-अलग priorities और मूल्यों के आधार पर चुना जा सकता है। आगे GUI विस्तार भी कई तरह के योजनाबद्ध हैं, और platform-specific native features, जैसे iCloud sync, के साथ भी गहरा integration होने वाला है
    • “Kovid ने features ज़्यादा तेज़ी से implement किए” — इस दावे पर थोड़ा सावधान रहना चाहिए, क्योंकि इस account के Kovid खुद होने का संदेह पैदा करने वाला इतिहास है। वास्तव में HN और Reddit पर इसे Kitty का तटस्थ परिचय देने का नाटक करते हुए developer की आलोचना करते देखा गया है। पुराने comment history तक देखने के लिए link दिया गया है
    • ऊपर की सकारात्मक बातों के अलावा, मेरे हिसाब से ‘libghostty’ का आना game changer है। यह WebKit की तरह एक शक्तिशाली terminal implementation है, जिसे कोई भी drop-in की तरह जोड़ते ही तुरंत उपयोग कर सकता है
    • मैं भी terminal की तलाश में काफ़ी भटका हूँ, और Ghostty भले पूरी तरह आदर्श न हो, लेकिन जब कोई बेहतर संतुलित विकल्प नहीं मिला, तब मैं इसी पर आ गया। मेरे लिए यह भी काफ़ी मायने रखता है। अक्सर कोई “निर्णायक वजह” नहीं होती; बल्कि यह कि कोई बड़ी समस्या नहीं है और इसलिए आप इसे उपयोग करते रहते हैं — यही इसकी ताकत है
    • Ghostty में fonts, Kitty की तुलना में कहीं ज़्यादा सुंदर render होते हैं। Neovide और भी सुंदर है, लेकिन उसमें अभी tabs support नहीं है और वह battery भी अधिक खाता है