[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Fdart-cli-foundations":663,"blog-author-\u002Fblog\u002Fdart-cli-foundations":1729,"i-material-symbols:arrow-back-rounded":1744},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Sign in","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","VdirGIa8cUm6xLprbBeTKcw914JfyJjWfF-9hSVOX5Y",{"id":87,"extension":5,"links":88,"meta":660,"stem":661,"__hash__":662},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,295,299,303,306,310,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,453,457,461,465,469,473,477,480,483,486,489,493,497,500,504,508,512,516,520,524,528,532,536,540,544,548,551,555,559,563,567,571,574,577,580,584,587,591,595,599,603,606,610,614,617,620,623,627,631,635,638,641,644,648,652,656],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":209,"label":210,"href":211},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":213,"label":214,"href":215},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":217,"label":218,"href":219},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":221,"label":222,"href":223},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":225,"label":226,"href":227},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":229,"label":230,"href":231},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":233,"label":234,"href":235},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":237,"label":238,"href":239},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":241,"label":242,"href":243},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":245,"label":246,"href":247},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":249,"label":250,"href":251},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":253,"label":254,"href":255},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":257,"label":258,"href":259},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":261,"label":262,"href":263},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":265,"label":266,"href":267},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":269,"label":270,"href":271},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":273,"label":274,"href":275},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":277,"label":278,"href":279},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":281,"label":282,"href":283},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":285,"label":286,"href":287},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":289,"label":290,"href":291},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":293,"label":294,"href":92},"docs.desktop.download","Desktop download docs",{"key":296,"label":297,"href":298},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":300,"label":301,"href":302},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":304,"label":305,"href":207},"docs.piecesOS.install","PiecesOS install docs",{"key":307,"label":308,"href":309},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":311,"label":312,"href":313},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":315,"label":316,"href":317},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":319,"label":320,"href":321},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":323,"label":324,"href":325},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":327,"label":328,"href":329},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":331,"label":332,"href":333},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":335,"label":336,"href":337},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":343,"label":344,"href":345},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":347,"label":348,"href":349},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":351,"label":352,"href":353},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":355,"label":356,"href":357},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":359,"label":360,"href":361},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":363,"label":364,"href":365},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":367,"label":368,"href":369},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":371,"label":372,"href":373},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":375,"label":376,"href":377},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":379,"label":380,"href":381},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":383,"label":384,"href":385},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":387,"label":388,"href":389},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":391,"label":392,"href":393},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":395,"label":396,"href":397},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":399,"label":400,"href":401},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":403,"label":404,"href":405},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":407,"label":408,"href":409},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":411,"label":412,"href":413},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":415,"label":416,"href":417},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":419,"label":420,"href":421},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":423,"label":424,"href":425},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":427,"label":428,"href":429},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":431,"label":432,"href":433},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":435,"label":436,"href":437},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":439,"label":440,"href":441},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":443,"label":444,"href":445},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":447,"label":448,"href":449},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":451,"label":58,"href":452},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":454,"label":455,"href":456},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":458,"label":459,"href":460},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":462,"label":463,"href":464},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":466,"label":467,"href":468},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":470,"label":471,"href":472},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":474,"label":475,"href":476},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":478,"label":34,"href":479},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":481,"label":43,"href":482},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":484,"label":46,"href":485},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":487,"label":488,"href":485},"social.twitter","Twitter",{"key":490,"label":491,"href":492},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":494,"label":495,"href":496},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":498,"label":49,"href":499},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":501,"label":502,"href":503},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":505,"label":506,"href":507},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":509,"label":510,"href":511},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":513,"label":514,"href":515},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":517,"label":518,"href":519},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":521,"label":522,"href":523},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":525,"label":526,"href":527},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":529,"label":530,"href":531},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":533,"label":534,"href":535},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":537,"label":538,"href":539},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":541,"label":542,"href":543},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":545,"label":546,"href":547},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":549,"label":550,"href":247},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":552,"label":553,"href":554},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":556,"label":557,"href":558},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":560,"label":561,"href":562},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":564,"label":565,"href":566},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":568,"label":569,"href":570},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":572,"label":573,"href":66},"legal.privacyPolicy","Privacy policy",{"key":575,"label":576,"href":69},"legal.refundPolicy","Refund policy",{"key":578,"label":579,"href":72},"legal.terms","Terms",{"key":581,"label":582,"href":583},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":585,"label":586,"href":503},"videos.youtubeChannel","YouTube channel",{"key":588,"label":589,"href":590},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":592,"label":593,"href":594},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":596,"label":597,"href":598},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":600,"label":601,"href":602},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":604,"label":605,"href":519},"sales.feedback","Feedback discussions",{"key":607,"label":608,"href":609},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":611,"label":612,"href":613},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":615,"label":616,"href":19},"routes.home","Home route",{"key":618,"label":619,"href":56},"routes.about","About route",{"key":621,"label":622,"href":12},"routes.downloads","Downloads route",{"key":624,"label":625,"href":626},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":628,"label":629,"href":630},"routes.pricing","Pricing route","\u002Fpricing",{"key":632,"label":633,"href":634},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":636,"label":637,"href":22},"routes.enterprise","Enterprise route",{"key":639,"label":640,"href":62},"routes.contact","Contact route",{"key":642,"label":643,"href":59},"routes.updates","Updates route",{"key":645,"label":646,"href":647},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":649,"label":650,"href":651},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":653,"label":654,"href":655},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":657,"label":658,"href":659},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","NLkVE1lIUws518K-1QsSB6T-GvlXYIzcRL1HDhqarGQ",{"id":664,"title":665,"author":666,"authorPhoto":667,"authorPhotoAlt":668,"authorSlug":669,"body":670,"buttonText":1716,"buttonUrl":1716,"category":1717,"date":1718,"description":1719,"draft":1720,"editorsPick":1720,"extension":1721,"featured":1720,"image":1722,"imageAlt":1723,"meta":1724,"navigation":32,"ogImage":1716,"ogImageAlt":1716,"path":1725,"seo":1726,"stem":1727,"tags":1716,"__hash__":1728},"blog\u002Fblog\u002Fdart-cli-foundations.md","Dart CLI Foundations: CLI Tools to Streamline Your Workflow","Rutvik Tak","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdart-cli-foundations\u002Fauthor.jpeg","Rutvik Tak.","rutvik-tak",{"type":671,"value":672,"toc":1695},"minimark",[673,677,680,685,700,703,714,717,720,726,739,746,750,770,796,801,812,815,839,842,848,855,940,943,947,950,957,963,969,988,991,997,1003,1013,1047,1051,1060,1065,1071,1077,1083,1090,1094,1100,1106,1112,1118,1125,1132,1138,1144,1164,1168,1171,1174,1180,1186,1189,1193,1200,1206,1212,1229,1235,1239,1242,1271,1278,1284,1290,1296,1309,1313,1316,1320,1326,1332,1338,1348,1354,1360,1363,1366,1372,1378,1382,1388,1394,1405,1416,1421,1427,1433,1437,1440,1443,1447,1456,1462,1468,1474,1478,1481,1487,1493,1495,1501,1505,1508,1514,1520,1522,1528,1532,1535,1538,1541,1547,1553,1559,1562,1568,1574,1582,1585,1589,1606,1612,1618,1632,1635,1641,1647,1657,1660,1663,1668,1674,1678,1681,1689,1692],[674,675,676],"p",{},"Are you ready to take your software development skills to the next level? Then, it's time to dive into the world of Command Line Interface (CLI) tools with dart CLI. These tools run directly in the terminal, the familiar space for developers, and can streamline your workflow with their minimal interface and quick access.",[674,678,679],{},"In this series of articles, we will be exploring Dart CLI apps and how to build them. You'll learn about the structure of Dart CLI projects, handling arguments, working with input\u002Foutput, reading and writing to files, and finally, compiling and installing your Dart CLI apps. Embrace the full power of the terminal and join us on this exciting journey to build CLI apps in Dart.",[681,682,684],"h2",{"id":683},"getting-started","Getting Started",[674,686,687,694,695,699],{},[688,689,693],"a",{"href":690,"rel":691},"https:\u002F\u002Fdart.dev\u002Fget-dart",[692],"nofollow","Install the Dart SDK"," to get started. We will be using ",[688,696,698],{"href":223,"rel":697},[692],"Visual Studio Code"," as the development environment for our Command Line Interface (CLI) application. However, the choice of Integrated Development Environment (IDE) is not crucial and you can work with any IDE that you prefer, without affecting the learning outcome.",[674,701,702],{},"To create a new Dart CLI project, run the following dart command:",[704,705,710],"pre",{"className":706,"code":708,"language":709},[707],"language-text","dart create dart_cli -t console\n","text",[711,712,708],"code",{"__ignoreMap":713},"",[674,715,716],{},"This will create a Dart CLI project in the respective directory.",[674,718,719],{},"You can run your Dart CLI application with the following dart command:",[704,721,724],{"className":722,"code":723,"language":709},[707],"dart run bin\u002Fdart_cli.dart\n",[711,725,723],{"__ignoreMap":713},[674,727,728,729,732,733,738],{},"Here, ",[711,730,731],{},"-t"," defines the template for the Dart project. ",[688,734,737],{"href":735,"rel":736},"https:\u002F\u002Fdart.dev\u002Ftools\u002Fdart-create",[692],"Dart has several templates"," you can use to work on CLI, web or server-side projects.",[674,740,741],{},[688,742,745],{"href":743,"rel":744},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=0b324f8f6b",[692],"Save the above commands",[681,747,749],{"id":748},"understanding-project-structure-with-dart-cli","Understanding Project Structure with Dart CLI",[674,751,752,753,765,766,769],{},"Three of the most important things in our project structure are the ",[688,754,757,761,762],{"href":755,"rel":756},"https:\u002F\u002Fdart.dev\u002Ftools\u002Fpub\u002Fpackage-layout#public-directories",[692],[758,759,760],"strong",{},"bin"," and ",[758,763,764],{},"lib"," directories along with the ",[758,767,768],{},"pubspec.yaml"," file.",[771,772,773,780,786],"ul",{},[774,775,776,779],"li",{},[758,777,778],{},"bin:"," This is a public directory that is the entry point for your Dart CLI application. This includes the executable Dart file that the CLI app will run.",[774,781,782,785],{},[758,783,784],{},"lib:"," Lib includes the public libraries that your application uses. Like Dart methods, classes or any other code, this is imported into the bin directory.",[774,787,788,795],{},[688,789,792,794],{"href":790,"rel":791},"https:\u002F\u002Fdart.dev\u002Ftools\u002Fpub\u002Fpubspec",[692],[758,793,768],{},":"," The Dart CLI app is a package in itself. This file contains the package\u002FCLI app information like name, app version, any dependencies your app is using, etc. It also includes the entry point for your CLI application defined by the executables. This usually directs to the executable in the bin folder. Whenever you’ll be using your CLI app, you’ll be running this executable.",[797,798,800],"h3",{"id":799},"arguments-in-dart-cli","Arguments in Dart CLI",[674,802,803,804,807,808,811],{},"Within the ",[711,805,806],{},"bin\u002Fdart_cli.dart"," file, you’ll see that the main function accepts a list of strings called ",[758,809,810],{},"arguments",". These are inputs provided to CLI applications that you can use to know what to do.",[674,813,814],{},"Arguments are broken down into the following major types relevant to this tutorial:",[771,816,817,823,829],{},[774,818,819,822],{},[758,820,821],{},"Command:"," The command you wish to run to execute a particular task.",[774,824,825,828],{},[758,826,827],{},"Flags:"," Flags hold a boolean value. They can be used to turn on\u002Foff some flows within your program.",[774,830,831,834,835,838],{},[758,832,833],{},"Options",": Options are ",[758,836,837],{},"key-value pairs"," that you can define. You can also define options that accept a value from an allowed list of values, thus restricting the input that a user can provide for the option.",[674,840,841],{},"For example, take a look at the following command, which creates the Dart project with some additional arguments added:",[704,843,846],{"className":844,"code":845,"language":709},[707],"$ dart create dart_cli -t console --force --[no-]pub\n",[711,847,845],{"__ignoreMap":713},[674,849,850],{},[688,851,854],{"href":852,"rel":853},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=08f342bb7e",[692],"Save this code",[856,857,858,868,874,880,905,911,922],"ol",{},[774,859,860,863,864,867],{},[758,861,862],{},"dart:"," This is the executable or the program that you want to run. You can treat it as a ",[711,865,866],{},"root-command",".",[774,869,870,873],{},[758,871,872],{},"create:"," The command you want to execute.",[774,875,876,879],{},[758,877,878],{},"dart_cli:"," This is an argument for the earlier command which defines the name for the project. This is not predefined, so if there are any such arguments that a command would be accepting, then it should know about it.",[774,881,882,885,886,889,890,893,894,897,898,901,902,867],{},[758,883,884],{},"-t:"," An option where the ",[711,887,888],{},"t"," is the abbreviation used for the ",[711,891,892],{},"template"," for the project. You can also provide options like ",[711,895,896],{},"follow",", ",[711,899,900],{},"-t console"," or ",[711,903,904],{},"--template=\"console\"",[774,906,907,910],{},[758,908,909],{},"console",": This is the value for the option earlier.",[774,912,913,914,917,918,921],{},"—",[758,915,916],{},"force:"," This is a flag and is used to force the creation of a project even if the target directory already exists. You can also turn on certain flags by using the flags abbreviations (if any) provided for them, e.g., ",[711,919,920],{},"-f",". Both of these methods will turn the respective flag on.",[774,923,913,924,927,928,931,932,935,936,939],{},[758,925,926],{},"no-pub",": By default, Dart create will run ",[711,929,930],{},"pub get",", which will fetch the dependencies within your ",[758,933,934],{},"pubspec.yaml."," The prefix ",[758,937,938],{},"no"," is used to set the flag’s value to false.",[674,941,942],{},"Now that we are clear on the different types of arguments we can expect in our CLI application, let’s see how we can handle those arguments within the code.",[797,944,946],{"id":945},"parsing-arguments-in-dart-cli","Parsing Arguments in Dart CLI",[674,948,949],{},"You’ll see that within our main method, the arguments are provided as a list of strings. Working with them this way would be inefficient and unmanageable. Therefore, what we’ll do is parse the list of arguments into something that’s more approachable and friendlier to use.",[674,951,952,953,956],{},"We’ll be using the ",[758,954,955],{},"args"," package, which helps us define parsers for the raw command line arguments. You can add it to your project by running the following command:",[704,958,961],{"className":959,"code":960,"language":709},[707],"$ dart pub add args\n",[711,962,960],{"__ignoreMap":713},[674,964,965],{},[688,966,854],{"href":967,"rel":968},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=13a74a8cee",[692],[674,970,971,972,974,975,978,979,987],{},"This will add the ",[758,973,955],{}," dependency in your ",[758,976,977],{},"pubspec"," file. We used the Darts ",[688,980,983,984],{"href":981,"rel":982},"https:\u002F\u002Fdart.dev\u002Ftools\u002Fpub\u002Fcmd",[692],"package manager ",[758,985,986],{},"pub"," to add this dependency.",[674,989,990],{},"Now, take a look at the code below:",[704,992,995],{"className":993,"code":994,"language":709},[707],"void main(List arguments) async {\n final ArgParser parser = ArgParser()\n    ..addCommand(\"create\")   \n  ..addOption(\n    \"template\",\n    defaultsTo:   \"t\",\n   \u002F\u002F If allowed is non-null, then input will be restricted to the values\n   \u002F\u002F provided in allowed list.\n      allowed:   [\n        \"console\",\n        \"package\"\n        \"web\",\n        \"server-shelf\",\n       ],\n     )\n     ..addFlag(\"force\",   abbr:   \"f\");\n final ArgResults argResults = parser.parse(arguments);\n final command = argResults.command!.name!;   \n \u002F\u002F gets the command entered\n final isForced = argResults[\"force\"] as bool;\n}\n",[711,996,994],{"__ignoreMap":713},[674,998,999],{},[688,1000,854],{"href":1001,"rel":1002},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=d3b0499bd4",[692],[674,1004,1005,1006,1009,1010,794],{},"There are two important pieces of information here, the ",[711,1007,1008],{},"ArgParser"," and the ",[711,1011,1012],{},"ArgResults",[771,1014,1015,1024],{},[774,1016,1017,1020,1021,1023],{},[758,1018,1019],{},"ArgParser:"," ",[711,1022,1008],{}," can be used to define parsers to parse the arguments. You can then add to the parser the commands, flags and options that you expect to use in your CLI application.",[774,1025,1026,1029,1030,1032,1033,1035,1036,1038,1039,1042,1043,1046],{},[758,1027,1028],{},"ArgResults:"," Once you’ve created your parser, you can parse the raw ",[711,1031,810],{}," and it’ll return the ",[711,1034,1012],{}," object, which will map the raw values from the ",[711,1037,810],{}," list to the defined commands, flags and options. This makes it easier to use the arguments from input through a concrete class. You can also treat it like a ",[711,1040,1041],{},"map"," to find different values as we did above to get values for the ",[711,1044,1045],{},"force"," flag.",[797,1048,1050],{"id":1049},"io","I\u002FO",[674,1052,1053,1054,1059],{},"The ",[688,1055,1058],{"href":1056,"rel":1057},"https:\u002F\u002Fdart.dev\u002Farticles\u002Flibraries\u002Fdart-io",[692],"dart:io"," library provides us with different streams through which we can manage input\u002Foutput events. Let’s take a look at them below.",[1061,1062,1064],"h4",{"id":1063},"output-stream","Output Stream",[674,1066,1053,1067,1070],{},[711,1068,1069],{},"stdout"," from dart:io provides the standard output stream. This stream can be used to log outputs to the terminal, like below:",[704,1072,1075],{"className":1073,"code":1074,"language":709},[707],"stdout.writeln(\"Hello World!\");\n",[711,1076,1074],{"__ignoreMap":713},[674,1078,1079],{},[688,1080,854],{"href":1081,"rel":1082},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=391944bc1f",[692],[674,1084,1085,1086,1089],{},"This will output ",[711,1087,1088],{},"\"Hello World\""," and is a non-blocking operation. This means any other i\u002Fo operations will not be blocked from executing while this is running.",[1061,1091,1093],{"id":1092},"input-stream","Input Stream",[674,1095,1053,1096,1099],{},[711,1097,1098],{},"stdin"," provides the standard input stream, which we can read\u002Flisten to get the input from the terminal, like the following:",[704,1101,1104],{"className":1102,"code":1103,"language":709},[707],"final input = stdin.readLineSync();stdout.writeln(input);\n",[711,1105,1103],{"__ignoreMap":713},[674,1107,1108],{},[688,1109,854],{"href":1110,"rel":1111},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=85b64c8d78",[692],[674,1113,728,1114,1117],{},[711,1115,1116],{},"readLineSync()"," listens to the input from the standard stream. This is a blocking operation, and until input is received and the user presses return, other i\u002Fo events are blocked.",[674,1119,1120],{},[1121,1122],"img",{"alt":1123,"src":1124},"Hello World with the Dart CLI.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdart-cli-foundations\u002Fimg-001.gif",[674,1126,1127,1128,1131],{},"Alternatively, if you want a non-blocking input read, then you can use the ",[711,1129,1130],{},".pipe()"," method:",[704,1133,1136],{"className":1134,"code":1135,"language":709},[707],"final input = await stdin.pipe(stdout);\n",[711,1137,1135],{"__ignoreMap":713},[674,1139,1140],{},[688,1141,854],{"href":1142,"rel":1143},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=38234c9a80",[692],[674,1145,1146,1147,761,1150,1153,1154,1156,1157,1159,1160,1163],{},"This method is ",[758,1148,1149],{},"non-blocking",[758,1151,1152],{},"async",". It takes in another stream consumer like ",[711,1155,1069],{},", which consumes the events from the ",[711,1158,1098],{}," stream without blocking the ",[711,1161,1162],{},"output"," stream.",[1061,1165,1167],{"id":1166},"error-stream","Error Stream",[674,1169,1170],{},"It’s not uncommon to come across errors in your applications and catch them, or to explicitly throw errors if things don’t add up.",[674,1172,1173],{},"The dart:io library also provides a standard error stream that logs the errors to the console:",[704,1175,1178],{"className":1176,"code":1177,"language":709},[707],"stderr.writeln(\"Ooops! Something's not right!\")\n",[711,1179,1177],{"__ignoreMap":713},[674,1181,1182],{},[688,1183,854],{"href":1184,"rel":1185},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=50d64f936a",[692],[674,1187,1188],{},"This will log out the given error. Also, this operation is non-blocking.",[1061,1190,1192],{"id":1191},"exception-handling","Exception Handling",[674,1194,1195,1196,1199],{},"Your application may throw exceptions at runtime. You should handle these exceptions when they occur, and provide the proper message to the user to tell them what went wrong. Exceptions can be easily caught with a ",[711,1197,1198],{},"try\u002Fcatch"," block.",[704,1201,1204],{"className":1202,"code":1203,"language":709},[707],"void main(List arguments) {\n try {\n  \u002F\u002F This will throw an exception as abbr can be either null or character of length 1.\n final ArgParser parser = ArgParser()..addFlag(\"save\", abbr: \"save\");\n      } on ArgParserException catch (e) {\n  stdout.writeln(\"Failed while parsing arguments\");\n      studout.writeln(e.message);\n      exit(1);\n    } catch (e) {\n  stdout.writeln(\"Something went wrong\");\n  studout.writeln(e.message);\n          exit(1);\n}\n}\n",[711,1205,1203],{"__ignoreMap":713},[674,1207,1208],{},[688,1209,854],{"href":1210,"rel":1211},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=c83548a027",[692],[674,1213,1214,1215,1217,1218,1220,1221,1224,1225,1228],{},"Here, we used a ",[711,1216,1198],{}," block to catch any exceptions that might be thrown during the parsing of ",[711,1219,810],{},". Also, we are defining a ",[711,1222,1223],{},"catch"," block that will only catch the exceptions of type ",[711,1226,1227],{},"ArgParserException",". This makes it easier to work with different types of exceptions individually and provide outputs that are more helpful for those kinds of exceptions.",[674,1230,1231,1232,1234],{},"The last catch block will catch all other exceptions aside from the ",[711,1233,1227],{}," type, and provide a general message with the error thrown to the user.",[681,1236,1238],{"id":1237},"dart-cli-exit-codes","Dart CLI Exit Codes",[674,1240,1241],{},"Exit codes are a small number that shows the success, failure or any other state of the program to the system that called it. Within Dart, there are pre-defined exit codes appropriate for certain conditions.",[674,1243,1244,1245,1248,1249,897,1252,1248,1255,761,1258,1261,1262,1265,1266,867],{},"Generally, exit codes like ",[711,1246,1247],{},"0"," mean ",[711,1250,1251],{},"success",[711,1253,1254],{},"1",[711,1256,1257],{},"warning",[711,1259,1260],{},"2"," mean an ",[711,1263,1264],{},"error"," has occurred. See more Dart exit codes here: ",[688,1267,1270],{"href":1268,"rel":1269},"https:\u002F\u002Fdart.dev\u002Ftutorials\u002Fserver\u002Fcmdline#setting-exit-codes",[692],"src",[674,1272,1273,1274,1277],{},"The dart:io library defines a top-level property called ",[711,1275,1276],{},"exitCode",", which you can change to set the exit code for the running program:",[704,1279,1282],{"className":1280,"code":1281,"language":709},[707],"void readFile(String path) {\n try {\n  final file = File(path);\n  file.readAsLines();\n } on FileSystemException catch (e) {\n   exitCode = 2;\n }\n}\n",[711,1283,1281],{"__ignoreMap":713},[674,1285,1286],{},[688,1287,854],{"href":1288,"rel":1289},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=20364f8430",[692],[674,1291,1292,1293,1295],{},"Setting up a new ",[711,1294,1276],{}," doesn’t terminate the program. The program will continue to execute until it’s complete or an error occurs.",[674,1297,1298,1299,1301,1302,1305,1306,1308],{},"Along with the ",[711,1300,1276],{},", there is also a top-level method ",[711,1303,1304],{},"exit(exit_code)",", which sets the ",[711,1307,1276],{}," to the given code and terminates the program immediately.",[681,1310,1312],{"id":1311},"readingwriting-to-files","Reading\u002FWriting to Files",[674,1314,1315],{},"As with any other type of application, when working with a CLI, you may need to access files on a user's system for either reading or writing purposes. The dart:io library provides ways to access files on the system. Here’s how you can do that:",[797,1317,1319],{"id":1318},"reading-a-file","Reading a File",[704,1321,1324],{"className":1322,"code":1323,"language":709},[707],"final notesFile = File(\".\u002Fbin\u002Fnotes.txt\");\nfinal notes = notesFile.readAsLinesSync();\nfor (String note in notes) {\n       stdout.writeln(note);\n   }\n",[711,1325,1323],{"__ignoreMap":713},[674,1327,1328],{},[688,1329,854],{"href":1330,"rel":1331},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=14544997ee",[692],[674,1333,1053,1334,1337],{},[711,1335,1336],{},"File"," object is part of dart:io and has utility methods that you can use for reading\u002Fwriting to a file at the given path.",[674,1339,1340,1341,1344,1345,1347],{},"Here, you’re reading from a file named ",[758,1342,1343],{},"notes.txt"," within the ",[758,1346,760],{}," folder, as shown below:",[704,1349,1352],{"className":1350,"code":1351,"language":709},[707],"Learn Dart on CLI.🙌\nPractice what I learned.\n🧑🏽‍💻Build something cool with it.🔥\n",[711,1353,1351],{"__ignoreMap":713},[674,1355,1356],{},[688,1357,854],{"href":1358,"rel":1359},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=66cf41bb79",[692],[674,1361,1362],{},"The file is read as lines, and then you log each line to the output.",[674,1364,1365],{},"Output:",[704,1367,1370],{"className":1368,"code":1369,"language":709},[707],"$ dart run bin\u002Fdart_cli.dart\nLearn Dart on CLI.🙌\nPractice what I learned.🧑🏽‍💻\nBuild something cool with it.🔥\n",[711,1371,1369],{"__ignoreMap":713},[674,1373,1374],{},[688,1375,854],{"href":1376,"rel":1377},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=dc774d970f",[692],[797,1379,1381],{"id":1380},"writing-to-a-file","Writing to a File",[704,1383,1386],{"className":1384,"code":1385,"language":709},[707],"final newNotes = [\n \"Having fun learning Dart on CLI!🤩\",\n \"Dart makes it so easy to write cli apps.👍🏽\",\n \"Can't wait to build something cool with it!💙\",\n      ];\n final notesFile = File(\".\u002Fbin\u002Fnotes.txt\");\n final notesString = newNotes.join(\"\\n\");\n      notesFile.writeAsStringSync(\n          notesString,\n\u002F\u002F FileMode.append will add the new content at the end of the file.\n            mode: FileMode.append,\n\u002F\u002F   FileMode.write will override the existing file content with the new content.\n \u002F\u002F mode: FileMode.write,\n    );\n",[711,1387,1385],{"__ignoreMap":713},[674,1389,1390],{},[688,1391,854],{"href":1392,"rel":1393},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=1e624bad9a",[692],[674,1395,1396,1397,1400,1401,1404],{},"You can see that here we have defined some new notes. We are writing them to a notes file by using ",[711,1398,1399],{},".writeAsStringSync",". Before writing to the file, we joined the existing notes with ",[711,1402,1403],{},"\\\\n"," line delimiters because each note will be written on a new line.",[674,1406,1407,1408,1411,1412,1415],{},"Next, set the ",[711,1409,1410],{},"FileMode.append",", which will add the new content to the end of the file. You can set it to ",[711,1413,1414],{},".write"," if you want to override the existing content of the file.",[674,1417,1418,1420],{},[711,1419,1336],{}," has many other utility methods that you may find useful. Some of the most common ones are shown below:",[704,1422,1425],{"className":1423,"code":1424,"language":709},[707],"\u002F\u002F Creates the file at the path the File object was initialized with.\n    file.create();\n \u002F\u002F Checks if the file exists.\n    file.exists();\n \u002F\u002F Deletes the file.\n    file.delete();\n \u002F\u002F Listens to changes on file.\n    file.watch().listen((event) {\n \u002F\u002F File changed. Do something.\n   });\n",[711,1426,1424],{"__ignoreMap":713},[674,1428,1429],{},[688,1430,854],{"href":1431,"rel":1432},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=278b46bb5e",[692],[681,1434,1436],{"id":1435},"styling-your-application","Styling Your Application",[674,1438,1439],{},"Oftentimes, CLI applications can have a less appealing visual experience as coloring the output text, adding a colorful background to text and changing how users can interact with the app is challenging. This is definitely not an easy task; there are a lot of factors that go into getting this right.",[674,1441,1442],{},"Next, we’ll take a look at a logger package that makes it easier for us to style our CLI.",[797,1444,1446],{"id":1445},"adding-mason-logger","Adding Mason Logger",[674,1448,1449,1450,1455],{},"We can use ",[688,1451,1454],{"href":1452,"rel":1453},"https:\u002F\u002Fpub.dev\u002Fpackages\u002Fmason_logger",[692],"Mason logger"," to log stylized and more interactive outputs to the terminal.",[674,1457,1458,1459,1461],{},"To use it, add it as a dependency in your ",[758,1460,768],{},", or just run the following command that will add it for you:",[704,1463,1466],{"className":1464,"code":1465,"language":709},[707],"$ dart pub add mason_logger\n",[711,1467,1465],{"__ignoreMap":713},[674,1469,1470],{},[688,1471,854],{"href":1472,"rel":1473},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=7d2e498b49",[692],[1061,1475,1477],{"id":1476},"stylized-output","Stylized Output",[674,1479,1480],{},"Mason provides us with a range of different output levels like info, warning, error, success, etc. It also allows us to add a background color to text, as in the example below.",[704,1482,1485],{"className":1483,"code":1484,"language":709},[707],"import 'package:mason_logger\u002Fmason_logger.dart';void main(List arguments) async {\n final logger = Logger();\n    logger.info('\\nThis is an info.🔵\\n');\n    logger.warn('\\nThis is a warning.🌕');\n    logger.err('\\nThis is an error.🔴');\n    logger.success('\\nThis is success!🟢');\n    logger.success(\n          backgroundBlue.wrap(\"\\nLook! A text with colored background!🥳\"),\n    );\n}\n",[711,1486,1484],{"__ignoreMap":713},[674,1488,1489],{},[688,1490,854],{"href":1491,"rel":1492},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=d29d4cbad1",[692],[674,1494,1365],{},[674,1496,1497],{},[1121,1498],{"alt":1499,"src":1500},"Project output.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdart-cli-foundations\u002Fimg-002.png",[1061,1502,1504],{"id":1503},"rich-interactions","Rich Interactions",[674,1506,1507],{},"Mason can not only help with styling output, but also with implementing more common types of interactive outputs with rich experiences like below:",[704,1509,1512],{"className":1510,"code":1511,"language":709},[707],"import 'package:mason_logger\u002Fmason_logger.dart';void main(List arguments) async {\n final logger = Logger();\n \u002F\u002F Confirmation message\n final isConfirmed =\n                logger.confirm(\"This is a confirmation messsage with yes and no option.\");\n if (isConfirmed) {\n \u002F\u002F User permitted the action.\n   }\n \u002F\u002F Single choice selection\n final selectedChoice = logger.chooseOne(\"Options picker\", choices: [\n \"Choice1\",\n \"Choice2\",\n \"Choice3\",\n      ]);\n logger.info(\"Selected Choice-->$selectedChoice\");\n \u002F\u002F Multiple choice selection\n final selectedListOfChoices = logger.chooseAny(\"Options picker\", choices: [\n \"Choice1\",\n \"Choice2\",\n \"Choice3\",\n \"Choice4\",\n \"Choice5\",\n  ]);\n",[711,1513,1511],{"__ignoreMap":713},[674,1515,1516],{},[688,1517,854],{"href":1518,"rel":1519},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=543c4f9f53",[692],[674,1521,1365],{},[674,1523,1524],{},[1121,1525],{"alt":1526,"src":1527},"Output of the Dart CLI code above showing an options picker in the terminal. ","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdart-cli-foundations\u002Fimg-003.gif",[681,1529,1531],{"id":1530},"compiling","Compiling",[674,1533,1534],{},"Once you’re done with your app, it’s time to compile it so you can distribute it to stores, or anywhere else you like.",[674,1536,1537],{},"While in the dev process, the application runs on top of Dart VM, which is optimized for faster performance and execution times.",[674,1539,1540],{},"For production, you can use the Dart compiler. This offers AOT compilation to compile the program to native machine code:",[704,1542,1545],{"className":1543,"code":1544,"language":709},[707],"$ dart compile exe bin\u002Fdart_cli.dart\n",[711,1546,1544],{"__ignoreMap":713},[674,1548,1549],{},[688,1550,854],{"href":1551,"rel":1552},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=ef7b47a777",[692],[674,1554,1555,1556,1558],{},"This will generate the application executable in your ",[758,1557,760],{}," folder.",[674,1560,1561],{},"You can run the executable like so:",[704,1563,1566],{"className":1564,"code":1565,"language":709},[707],"$ .\u002Fbin\u002Fdart_cli.exe\n",[711,1567,1565],{"__ignoreMap":713},[674,1569,1570],{},[688,1571,854],{"href":1572,"rel":1573},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=593a4db4c7",[692],[674,1575,1576,1577],{},"Cross-compilation support for Dart CLI is being worked on. You can follow its progress ",[688,1578,1581],{"href":1579,"rel":1580},"https:\u002F\u002Fgithub.com\u002Fdart-lang\u002Fsdk\u002Fissues\u002F28617",[692],"here.",[674,1583,1584],{},"Another interesting fact about the executables is that they can be run without installing Dart SDK on the system they’re running on. This is because the executables are self-contained with everything needed to run properly.",[681,1586,1588],{"id":1587},"installing-dart-cli","Installing Dart CLI",[674,1590,1591,1592,1595,1596,1601,1602,1605],{},"Besides building the executable, you can also directly install the CLI app through ",[758,1593,1594],{},"pub."," However, before this step, make sure you’ve mentioned the ",[688,1597,1600],{"href":1598,"rel":1599},"https:\u002F\u002Fdart.dev\u002Ftools\u002Fpub\u002Fpubspec#executables",[692],"executables"," in your ",[758,1603,1604],{},"pubspec.yaml,"," which you’ll want to activate:",[704,1607,1610],{"className":1608,"code":1609,"language":709},[707],"..\n...\nexecutables:\n    dart_cli: dart_cli # value can be left empty and is inferred from the key\n    other_executable: todo_cli\n..\n...\n",[711,1611,1609],{"__ignoreMap":713},[674,1613,1614],{},[688,1615,854],{"href":1616,"rel":1617},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=f2ee479a8d",[692],[674,1619,1620,1621,1624,1625,1628,1629,867],{},"To add the executable, you’ll need to provide a ",[758,1622,1623],{},"key-value"," pair. If the ",[711,1626,1627],{},"value"," is not provided, then it’s inferred from the ",[711,1630,1631],{},"key",[674,1633,1634],{},"Then, run the following command to activate values globally:",[704,1636,1639],{"className":1637,"code":1638,"language":709},[707],"$ dart pub global activate --source path\n",[711,1640,1638],{"__ignoreMap":713},[674,1642,1643],{},[688,1644,854],{"href":1645,"rel":1646},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=31ec45a850",[692],[674,1648,1649,1650,1653,1654,1656],{},"Next, provide the path of the project. If you’re in the project’s directory, provide the ",[711,1651,1652],{},"project_path"," as ",[711,1655,867],{}," .",[674,1658,1659],{},"This will globally activate the CLI application by installing the executable on your system.",[674,1661,1662],{},"You can run the application from anywhere on your system like so:",[704,1664,1666],{"className":1665,"code":1638,"language":709},[707],[711,1667,1638],{"__ignoreMap":713},[674,1669,1670],{},[688,1671,854],{"href":1672,"rel":1673},"https:\u002F\u002Ftakrutvik.pieces.cloud\u002F?p=315f4da0b2",[692],[681,1675,1677],{"id":1676},"summary-on-dart-cli","Summary on Dart CLI",[674,1679,1680],{},"So, you took a leap of faith in learning to build CLI apps with Dart. You learned the basics of i\u002Fo, working with files, HTTP requests and more in Dart. Along with this, you also looked into how to compile and install CLI apps to use them on your system.",[674,1682,1683,1684,867],{},"Working with Dart on CLI applications is really amazing. The pace at which it’s evolving is astonishing to me. I’ve never grown so fond of a language that makes building CLI tools so easy. There are a lot of interesting things that you can do with Dart right now. You can learn more about them ",[688,1685,1688],{"href":1686,"rel":1687},"https:\u002F\u002Fdart.dev\u002Ftutorials\u002Fserver\u002Fget-started#6-compile-for-production",[692],"here",[674,1690,1691],{},"Going forward in this series, we’ll explore building casual\u002Futility CLI apps with Dart and maybe some CLI games! 👀 Who knows? 🤫",[674,1693,1694],{},"Make sure you subscribe to the blog to get updated when the next article drops for this series. 💙 Have an amazing day and see you later :)",{"title":713,"searchDepth":1696,"depth":1696,"links":1697},2,[1698,1699,1705,1706,1710,1713,1714,1715],{"id":683,"depth":1696,"text":684},{"id":748,"depth":1696,"text":749,"children":1700},[1701,1703,1704],{"id":799,"depth":1702,"text":800},3,{"id":945,"depth":1702,"text":946},{"id":1049,"depth":1702,"text":1050},{"id":1237,"depth":1696,"text":1238},{"id":1311,"depth":1696,"text":1312,"children":1707},[1708,1709],{"id":1318,"depth":1702,"text":1319},{"id":1380,"depth":1702,"text":1381},{"id":1435,"depth":1696,"text":1436,"children":1711},[1712],{"id":1445,"depth":1702,"text":1446},{"id":1530,"depth":1696,"text":1531},{"id":1587,"depth":1696,"text":1588},{"id":1676,"depth":1696,"text":1677},null,"Software Development","2022-10-27T00:00:00.000Z","Learn the structure of Dart CLI projects, working with input\u002Foutput, reading and writing to files, compiling and installing your Dart CLI apps.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdart-cli-foundations\u002Fhero.jpeg","Dart on CLI.",{},"\u002Fblog\u002Fdart-cli-foundations",{"title":665,"description":1719},"blog\u002Fdart-cli-foundations","DYEiCNOtBuwzsvCwG0zRWoVHX-E9bf6_LktC3RupjkQ",{"id":1730,"title":666,"body":1731,"description":1735,"draft":1720,"extension":1721,"meta":1738,"navigation":32,"path":1739,"photo":1740,"photoAlt":1716,"seo":1741,"stem":1742,"__hash__":1743},"authors\u002Fauthors\u002Frutvik-tak.md",{"type":671,"value":1732,"toc":1736},[1733],[674,1734,1735],{},"Rutvik was introduced to world of coding through animations and games. From there he loved the creative aspects of coding and solving interesting problems. At Pieces, he takes care of the Web Extension and making sure it works across all different browsers. Beside coding, he loves to help with support, dev rel content. When he's not doing either of that, you can find him working on animations, doing calisthenics or indoor rock climbing on weekends.",{"title":713,"searchDepth":1696,"depth":1696,"links":1737},[],{},"\u002Fauthors\u002Frutvik-tak","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Frutvik-tak.jpg",{"title":666,"description":1735},"authors\u002Frutvik-tak","HWkSe6txnNhDCCk74fgii1tqQGBDyeC8l7Qydvtn8ko",{"left":1745,"top":1745,"width":1746,"height":1746,"rotate":1745,"vFlip":1720,"hFlip":1720,"body":1747},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]