<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ terminal - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ terminal - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:30:10 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/terminal/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Agentic Terminal Workflow with GitHub Copilot CLI and MCP Servers ]]>
                </title>
                <description>
                    <![CDATA[ Most developers live in their terminal. You run commands, debug pipelines, manage infrastructure, and navigate codebases, all from a shell prompt. But despite how central the terminal is to developer  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-agentic-terminal-workflow-with-github-copilot-cli-and-mcp-servers/</link>
                <guid isPermaLink="false">69f212526e0124c05e1857b5</guid>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mcp ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mcp server ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Caleb Mintoumba ]]>
                </dc:creator>
                <pubDate>Wed, 29 Apr 2026 14:14:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/3e4e3d7e-6cbf-4742-a63b-f9a2579f2318.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Most developers live in their terminal. You run commands, debug pipelines, manage infrastructure, and navigate codebases, all from a shell prompt.</p>
<p>But despite how central the terminal is to developer workflows, AI assistance there has remained shallow: autocomplete a command here, explain an error there.</p>
<p>That changes when you combine GitHub Copilot CLI with MCP (Model Context Protocol) servers. Instead of an AI that reacts to isolated prompts, you get a terminal that understands your project context, queries live data sources, and chains tool calls autonomously – what the industry is starting to call an agentic workflow.</p>
<p>In this tutorial, you'll learn exactly how to wire these two systems together, step by step. By the end, your terminal will be able to do things like understand your Git history before suggesting a fix, query your running Docker containers before writing a compose patch, or pull live API schemas before generating a request.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-what-is-github-copilot-cli">What is GitHub Copilot CLI?</a></p>
</li>
<li><p><a href="#heading-what-is-the-model-context-protocol">What is the Model Context Protocol?</a></p>
</li>
<li><p><a href="#heading-how-mcp-servers-work-in-a-terminal-context">How MCP Servers Work in a Terminal Context</a></p>
</li>
<li><p><a href="#heading-step-1-install-and-configure-github-copilot-cli">Step 1 – Install and Configure GitHub Copilot CLI</a></p>
</li>
<li><p><a href="#heading-step-2-set-up-your-first-mcp-server">Step 2 – Set Up Your First MCP Server</a></p>
</li>
<li><p><a href="#heading-step-3-wire-copilot-cli-to-your-mcp-server">Step 3 – Wire Copilot CLI to Your MCP Server</a></p>
</li>
<li><p><a href="#heading-step-4-build-a-real-agentic-workflow">Step 4 – Build a Real Agentic Workflow</a></p>
</li>
<li><p><a href="#heading-step-5-extend-with-multiple-mcp-servers">Step 5 – Extend with Multiple MCP Servers</a></p>
</li>
<li><p><a href="#heading-debugging-common-issues">Debugging Common Issues</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before you start, make sure you have the following:</p>
<ul>
<li><p><strong>Node.js</strong> v18 or later (<code>node --version</code>)</p>
</li>
<li><p><strong>npm</strong> v9 or later</p>
</li>
<li><p>A GitHub account with Copilot enabled. The free tier (available to all GitHub users) is sufficient to follow this tutorial. Pro, Business, and Enterprise plans unlock higher usage limits but aren't required.</p>
</li>
<li><p><strong>GitHub CLI</strong> (<code>gh</code>) installed. We'll use it to authenticate.</p>
</li>
<li><p>Basic familiarity with the terminal and JSON configuration files</p>
</li>
<li><p>(Optional) <strong>Docker</strong> installed if you want to follow the Docker MCP example in Step 5</p>
</li>
</ul>
<p>You don't need prior experience with MCP or agentic AI systems, as this guide builds that understanding from the ground up.</p>
<h2 id="heading-what-is-github-copilot-cli">What is GitHub Copilot CLI?</h2>
<p>GitHub Copilot CLI is the terminal-native interface to GitHub's Copilot AI. Unlike the IDE plugin (which assists with code completion), Copilot CLI is designed specifically for shell workflows. It exposes three main commands:</p>
<ul>
<li><p><code>gh copilot suggest</code> proposes a shell command based on a natural language description</p>
</li>
<li><p><code>gh copilot explain</code> explains what a given command does</p>
</li>
<li><p><code>gh copilot alias</code> generates shell aliases for Copilot subcommands</p>
</li>
</ul>
<p>Here's a quick example of <code>suggest</code> in action:</p>
<pre><code class="language-shell">gh copilot suggest "find all files modified in the last 24 hours and larger than 1MB"
</code></pre>
<p>Copilot will return something like:</p>
<pre><code class="language-shell">find . -mtime -1 -size +1M
</code></pre>
<p>It will also ask if you want to copy it, run it directly, or revise the request. This interactive loop is already useful – but by itself, Copilot CLI has no awareness of your project context. It doesn't know your repo structure, your running services, or your deployment environment. That's where MCP comes in.</p>
<h2 id="heading-what-is-the-model-context-protocol">What is the Model Context Protocol?</h2>
<p>The <strong>Model Context Protocol (MCP)</strong> is an open standard introduced by Anthropic in late 2024. Its goal is straightforward: give AI models a standardized way to connect to external tools, data sources, and services.</p>
<p>Think of MCP as a universal adapter layer between an AI model and the real world. Without MCP, each AI integration is custom-built: one plugin for GitHub, another for Postgres, another for Slack, all with incompatible interfaces. MCP defines a single protocol that any tool can implement, and any compatible AI client can consume.</p>
<p>An MCP server exposes <strong>tools</strong> (functions the AI can call), <strong>resources</strong> (data the AI can read), and <strong>prompts</strong> (reusable instruction templates). The AI client in our case, a Copilot-powered terminal discovers these capabilities at runtime and uses them autonomously to complete a task.</p>
<p>A few notable MCP servers that are already production-ready:</p>
<table>
<thead>
<tr>
<th>MCP Server</th>
<th>What it exposes</th>
</tr>
</thead>
<tbody><tr>
<td>@modelcontextprotocol/server-filesystem</td>
<td>Read/write access to local files</td>
</tr>
<tr>
<td>@modelcontextprotocol/server-git</td>
<td>Git log, diff, blame, branch operations</td>
</tr>
<tr>
<td>@modelcontextprotocol/server-github</td>
<td>GitHub Issues, PRs, repos via API</td>
</tr>
<tr>
<td>@modelcontextprotocol/server-postgres</td>
<td>Live query execution on a Postgres DB</td>
</tr>
<tr>
<td>@modelcontextprotocol/server-docker</td>
<td>Container inspection, logs, stats</td>
</tr>
</tbody></table>
<p>The full registry lives at <code>github.com/modelcontextprotocol/servers</code>.</p>
<h2 id="heading-how-mcp-servers-work-in-a-terminal-context">How MCP Servers Work in a Terminal Context</h2>
<p>Before we get hands-on, it's worth understanding the communication model.</p>
<p>MCP servers run as local processes. They communicate with the AI client over <strong>stdio</strong> (standard input/output) or over an <strong>HTTP/SSE transport</strong>. The client sends JSON-RPC messages to the server, and the server responds with structured data.</p>
<p>Here's the simplified flow:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66f71ee288cc311f84e563bc/e1844dc5-a869-4201-ad8a-fd1cb305f646.png" alt="An architectural flowchart illustrating the Model Context Protocol (MCP) workflow. The process starts with a user typing a natural language prompt, passes through the Copilot CLI (the MCP client), communicates via JSON-RPC over stdio with an MCP Server (e.g., server-git), executes real tools like git log, returns a structured result to Copilot, which finally synthesizes a context-aware response for the user." style="display:block;margin:0 auto" width="1408" height="768" loading="lazy">

<p>The key word here is <strong>grounded</strong>. Without MCP, Copilot responds based purely on its training data and your prompt. With MCP, it can call <code>git log --oneline -20</code> before answering your question about recent regressions and its answer is based on <em>your actual code history</em>, not a generalized assumption.</p>
<h3 id="heading-step-1-install-and-configure-github-copilot-cli">Step 1 – Install and Configure GitHub Copilot CLI</h3>
<p>If you haven't already, install the GitHub CLI:</p>
<pre><code class="language-shell"># macOS
brew install gh

# Ubuntu/Debian
sudo apt install gh

# Windows (via winget)
winget install --id GitHub.cli
</code></pre>
<p>Then authenticate:</p>
<pre><code class="language-shell">gh auth login
</code></pre>
<p>Follow the interactive prompts. Select <strong>GitHub.com</strong>, then <strong>HTTPS</strong>, and authenticate via browser when prompted.</p>
<p>Now install the Copilot CLI extension:</p>
<pre><code class="language-shell">gh extension install github/gh-copilot
</code></pre>
<p>Verify the installation:</p>
<pre><code class="language-shell">gh copilot --version
</code></pre>
<p>You should see output like <code>gh-copilot version 1.x.x</code>.</p>
<p><strong>Optional but recommended: set up shell aliases.</strong> This makes the workflow much faster. For <code>bash</code> or <code>zsh</code>:</p>
<pre><code class="language-shell"># Add to your ~/.bashrc or ~/.zshrc
eval "$(gh copilot alias -- bash)"   # for bash
eval "$(gh copilot alias -- zsh)"    # for zsh
</code></pre>
<p>After reloading your shell (<code>source ~/.bashrc</code>), you can use <code>ghcs</code> as shorthand for <code>gh copilot suggest</code> and <code>ghce</code> for <code>gh copilot explain</code>.</p>
<h3 id="heading-step-2-set-up-your-first-mcp-server">Step 2 – Set Up Your First MCP Server</h3>
<p>We'll start with <code>server-git</code>. It's the most immediately useful for a development workflow and has zero external dependencies.</p>
<p>Install it globally via npm:</p>
<pre><code class="language-shell">npm install -g @modelcontextprotocol/server-git
</code></pre>
<p>Test that it runs:</p>
<pre><code class="language-shell">mcp-server-git --version
</code></pre>
<p>This server exposes the following tools to any compatible MCP client:</p>
<ul>
<li><p><code>git_log</code> retrieve commit history with filters</p>
</li>
<li><p><code>git_diff</code> diff between branches or commits</p>
</li>
<li><p><code>git_status</code> current working tree status</p>
</li>
<li><p><code>git_show</code> inspect a specific commit</p>
</li>
<li><p><code>git_blame</code> annotate file lines with commit info</p>
</li>
<li><p><code>git_branch</code> list or switch branches</p>
</li>
</ul>
<p>Now create a configuration file. MCP clients look for a file called <code>mcp.json</code> to discover available servers. Create it in your project root or in a global config directory:</p>
<pre><code class="language-shell">mkdir -p ~/.config/mcp
touch ~/.config/mcp/mcp.json
</code></pre>
<p>Add the following content:</p>
<pre><code class="language-markdown">{
  "mcpServers": {
    "git": {
      "command": "mcp-server-git",
      "args": ["--repository", "."],
      "transport": "stdio"
    }
  }
}
</code></pre>
<p>A few notes on this config:</p>
<ul>
<li><p><code>command</code> is the binary to run. Make sure it's on your <code>$PATH</code>.</p>
</li>
<li><p><code>args</code> passes <code>--repository .</code> so the server scopes itself to the current working directory.</p>
</li>
<li><p><code>transport: "stdio"</code> means communication happens over standard input/output the simplest and most stable option for local servers.</p>
</li>
</ul>
<h3 id="heading-step-3-wire-copilot-cli-to-your-mcp-server">Step 3 – Wire Copilot CLI to Your MCP Server</h3>
<p>This is where the two systems connect. GitHub Copilot CLI supports MCP via its <code>--mcp-config</code> flag (available from version 1.3+). You point it at your <code>mcp.json</code>, and Copilot will automatically initialize the declared servers before processing your prompt.</p>
<p>Here's the basic invocation:</p>
<pre><code class="language-shell">gh copilot suggest --mcp-config ~/.config/mcp/mcp.json "why did the build break in the last commit?"
</code></pre>
<p>When you run this inside a Git repository, Copilot CLI will:</p>
<ol>
<li><p>Start the <code>mcp-server-git</code> process</p>
</li>
<li><p>Call <code>git_log</code> to retrieve recent commits</p>
</li>
<li><p>Call <code>git_diff</code> on the most recent commit</p>
</li>
<li><p>Synthesize an answer based on the actual diff output</p>
</li>
</ol>
<p>Try it yourself on a repo with a recent failing commit. The difference in response quality compared to a plain <code>gh copilot suggest</code> is immediately obvious.</p>
<p><strong>Tip: avoid retyping the flag every time.</strong> Add a shell function to your <code>.bashrc</code>/<code>.zshrc</code>:</p>
<pre><code class="language-shell">function aterm() {
  gh copilot suggest --mcp-config ~/.config/mcp/mcp.json "$@"
}
</code></pre>
<p>Now you just type:</p>
<pre><code class="language-shell">aterm "what changed between main and feature/auth?"
</code></pre>
<p>And you're running a fully context-aware, MCP-powered query from a single short command. This function name <code>aterm</code> for <em>agentic terminal</em> is what we'll use throughout the rest of this tutorial.</p>
<h3 id="heading-step-4-build-a-real-agentic-workflow">Step 4 – Build a Real Agentic Workflow</h3>
<p>Let's move beyond individual queries and build a workflow that chains multiple tool calls to complete a real developer task: <strong>diagnosing a regression</strong>.</p>
<p>Imagine you pushed a feature branch and your CI pipeline failed. You don't know exactly which change caused it. Here's how your agentic terminal handles it:</p>
<h4 id="heading-query-1-understand-what-changed">Query 1: understand what changed</h4>
<pre><code class="language-shell">aterm "summarize all commits on feature/auth that aren't on main yet"
</code></pre>
<p>Copilot calls <code>git_log</code> with branch filters, then returns a structured summary of commits unique to your branch. No copy-pasting SHAs manually.</p>
<h4 id="heading-query-2-isolate-the-diff">Query 2: isolate the diff</h4>
<pre><code class="language-shell">aterm "show me everything that changed in the auth middleware between main and feature/auth"
</code></pre>
<p>This triggers <code>git_diff</code> scoped to the path containing your middleware. Copilot returns the diff with an explanation of what each change does.</p>
<h4 id="heading-query-3-find-the-likely-culprit">Query 3: find the likely culprit</h4>
<pre><code class="language-shell">aterm "which of those changes could cause a JWT validation failure?"
</code></pre>
<p>At this point, Copilot has the diff in its context window from the previous tool calls. It reasons over the actual code changes not generic knowledge about JWT and pinpoints the likely issue.</p>
<h4 id="heading-query-4-generate-the-fix">Query 4: generate the fix</h4>
<pre><code class="language-shell">aterm "write the corrected version of that validation function"
</code></pre>
<p>Copilot generates a targeted fix based on the specific code it retrieved via MCP. You get a patch you can directly apply, not a generic code template.</p>
<p>This four-step sequence – understand, isolate, reason, fix – is a complete agentic loop. Each step is grounded in live repository data retrieved through MCP tools. The AI is not hallucinating context. Instead, it's reading your actual codebase.</p>
<h3 id="heading-step-5-extend-with-multiple-mcp-servers">Step 5 – Extend with Multiple MCP Servers</h3>
<p>One MCP server is useful. Multiple MCP servers working together is where the workflow becomes genuinely powerful. Let's add two more: <code>server-filesystem</code> and <code>server-docker</code>.</p>
<p>Install the additional servers:</p>
<pre><code class="language-shell">npm install -g @modelcontextprotocol/server-filesystem
npm install -g @modelcontextprotocol/server-docker
</code></pre>
<p>Update your <code>mcp.json</code>:</p>
<pre><code class="language-markdown">{
  "mcpServers": {
    "git": {
      "command": "mcp-server-git",
      "args": ["--repository", "."],
      "transport": "stdio"
    },
    "filesystem": {
      "command": "mcp-server-filesystem",
      "args": ["--root", "."],
      "transport": "stdio"
    },
    "docker": {
      "command": "mcp-server-docker",
      "transport": "stdio"
    }
  }
}
</code></pre>
<p>With all three servers active, your terminal can now answer cross-domain questions:</p>
<pre><code class="language-shell">aterm "my Express app container keeps restarting, check the logs and compare with what the healthcheck in my Dockerfile expects"
</code></pre>
<p>To answer this, Copilot will:</p>
<ol>
<li><p>Call <code>docker_logs</code> (server-docker) to pull the container's recent stderr output</p>
</li>
<li><p>Call <code>read_file</code> (server-filesystem) to read your <code>Dockerfile</code></p>
</li>
<li><p>Parse the <code>HEALTHCHECK</code> instruction</p>
</li>
<li><p>Cross-reference the log errors with the health endpoint path</p>
</li>
<li><p>Return a diagnosis explaining the mismatch and suggest the fix</p>
</li>
</ol>
<p>This is an <strong>agentic workflow</strong>: the model autonomously decides which tools to call, in what order, and synthesizes the results into a coherent answer. You didn't tell it to read the Dockerfile. It inferred that was necessary based on your question.</p>
<p><strong>A note on security:</strong> When running <code>server-filesystem</code>, always scope it to a specific directory using <code>--root</code>. Never point it at <code>/</code> or your home directory. Similarly, <code>server-docker</code> has access to your Docker socket run it only in trusted environments.</p>
<h2 id="heading-debugging-common-issues">Debugging Common Issues</h2>
<p><code>mcp-server-git: command not found</code></p>
<p>The npm global bin directory isn't on your <code>$PATH</code>. Fix:</p>
<pre><code class="language-shell">export PATH="\(PATH:\)(npm bin -g)"
# or for newer npm versions:
export PATH="\(PATH:\)(npm prefix -g)/bin"
</code></pre>
<p>Add this line to your <code>.bashrc</code>/<code>.zshrc</code> to persist it.</p>
<h4 id="heading-copilot-cli-doesnt-seem-to-be-using-mcp-tools">Copilot CLI doesn't seem to be using MCP tools</h4>
<p>Check your Copilot CLI version:</p>
<pre><code class="language-shell">gh copilot --version
</code></pre>
<p>MCP support requires version 1.3 or later. Update with:</p>
<pre><code class="language-shell">gh extension upgrade copilot
</code></pre>
<p>Also verify your <code>mcp.json</code> is valid JSON a trailing comma or missing bracket will silently prevent server initialization.</p>
<h4 id="heading-mcp-server-starts-but-returns-no-data">MCP server starts but returns no data</h4>
<p>Run the server manually to check for errors:</p>
<pre><code class="language-shell">mcp-server-git --repository .
</code></pre>
<p>If it exits immediately, check that you're running the command inside a valid Git repository. For <code>server-docker</code>, make sure the Docker daemon is running and your user has access to the Docker socket:</p>
<pre><code class="language-shell">sudo usermod -aG docker $USER
# Then log out and back in
</code></pre>
<h4 id="heading-responses-are-slow-with-multiple-servers">Responses are slow with multiple servers</h4>
<p>Each MCP server is a separate subprocess. Spawning several at once adds startup latency, especially on slower machines. Two optimizations:</p>
<ol>
<li><p>Only declare the servers you actually need for a given project in your <code>mcp.json</code></p>
</li>
<li><p>Use project-specific config files instead of one global config:</p>
</li>
</ol>
<pre><code class="language-shell"># project A (backend)
aterm --mcp-config ./mcp-backend.json "..."

# project B (infra)
aterm --mcp-config ./mcp-infra.json "..."
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've just built an agentic terminal workflow from scratch. Here's a quick recap of what you did:</p>
<ul>
<li><p>Installed and configured GitHub Copilot CLI with shell aliases for fast access</p>
</li>
<li><p>Set up MCP servers (<code>server-git</code>, <code>server-filesystem</code>, <code>server-docker</code>) and wired them through a <code>mcp.json</code> config</p>
</li>
<li><p>Created a shell function (<code>aterm</code>) that transparently passes your MCP config to every Copilot query</p>
</li>
<li><p>Built a multi-step agentic loop for diagnosing regressions using live Git data</p>
</li>
<li><p>Extended the setup with cross-domain tool orchestration across Git, filesystem, and Docker</p>
</li>
</ul>
<p>The architecture you've built here is not a demo – it's a production-ready pattern. You can extend it with any MCP-compatible server: <code>server-postgres</code> for database-aware queries, <code>server-github</code> for issue and PR context, or custom MCP servers you write yourself for your internal APIs.</p>
<p>The terminal has always been the most powerful surface in a developer's environment. With Copilot CLI and MCP, it's finally becoming an intelligent one.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Manage Python Packages with uv ]]>
                </title>
                <description>
                    <![CDATA[ Python package managers let you install and manage dependencies—like NumPy, pandas, and so on—right from your terminal. In this article, you will learn how to use uv—an extremely fast Python package manager. Prerequisites To get the most out of this ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-manage-python-packages-with-uv/</link>
                <guid isPermaLink="false">69089c3b30ea29f0efb3f4fd</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ package ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hew Hahn ]]>
                </dc:creator>
                <pubDate>Mon, 03 Nov 2025 12:12:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762169941014/9e66858d-3ba4-434e-a9f1-84d42a316192.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Python package managers let you install and manage dependencies—like NumPy, pandas, and so on—right from your terminal.</p>
<p>In this article, you will learn how to use <code>uv</code>—an extremely fast Python package manager.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this tutorial, you will need to:</p>
<ul>
<li><p>Know how to execute commands in your terminal,</p>
</li>
<li><p>Be familiar with basic Python development/scripting.</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-should-you-use-uv">Why Should You Use uv?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-uv">How to Install uv</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-a-project-with-uv">How to Set up a Project with uv</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-commonly-used-uv-commands">Commonly Used uv Commands</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-add-a-dependency">How to Add a Dependency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-remove-a-dependency">How to Remove a Dependency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-run-python-code">How to Run Python Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-move-your-project">How to Move Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-and-run-tools">How to Add and Run Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-run-tools-without-adding-them-to-your-project">How to Run Tools Without Adding Them to Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-multiple-python-versions">How to Manage Multiple Python Versions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-migrate-from-pip-to-uv">How to Migrate from pip to uv</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-why-should-you-use-uv">Why Should You Use uv?</h2>
<p><code>uv</code> is a free and open-source Python project management tool. Written in Rust, <code>uv</code> is fast and easy-to-use. It has become a standard package manager for modern Python development. You can also use it to manage your virtual environments, making it a good alternative for <code>pip</code> and <code>venv</code>.</p>
<p><a target="_blank" href="https://docs.astral.sh/uv/">Speed tests</a> have shown that <code>uv</code> is faster than other popular package managers when it comes to installing dependencies.</p>
<h2 id="heading-how-to-install-uv">How to Install uv</h2>
<p>To install <code>uv</code>, simply execute the following command in your terminal:</p>
<p>For Linux/macOS:</p>
<pre><code class="lang-bash">curl -LsSf https://astral.sh/uv/install.sh | sh
</code></pre>
<p>For Windows:</p>
<pre><code class="lang-powershell">powershell <span class="hljs-literal">-ExecutionPolicy</span> ByPass <span class="hljs-literal">-c</span> <span class="hljs-string">"irm https://astral.sh/uv/install.ps1 | iex"</span>
</code></pre>
<h2 id="heading-how-to-set-up-a-project-with-uv">How to Set up a Project with uv</h2>
<p>To start a new project with <code>uv</code>, run the following command:</p>
<pre><code class="lang-bash">uv init freecodecamp-project
</code></pre>
<p>This creates the folder <code>/freecodecamp-project</code> in your working directory with the following structure:</p>
<pre><code class="lang-bash">├── .gitignore <span class="hljs-comment"># hidden text file that lists files to be ignored by git</span>
├── .python-version <span class="hljs-comment"># hidden text file that keeps record of your Python's version number</span>
├── README.md
├── main.py
└── pyproject.toml
</code></pre>
<p><code>README.md</code> is a markdown file, which you can use to communicate information about your project (just as a repository README file on GitHub). <code>pyproject.toml</code> is the configuration file for your project. You can edit it to change your project’s name, version and description. It also keeps track of dependencies you add to project. Last but not least, <code>main.py</code> is where you put your Python code.</p>
<h2 id="heading-commonly-used-uv-commands">Commonly Used uv Commands</h2>
<p>Before you can run any <code>uv</code> commands, move your terminal into your project folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> freecodecamp-project
</code></pre>
<h3 id="heading-how-to-add-a-dependency">How to Add a Dependency</h3>
<p>To add a dependency (for example, NumPy), run:</p>
<pre><code class="lang-bash">uv add numpy
<span class="hljs-comment"># or if you need a specific version</span>
uv add <span class="hljs-string">'numpy==2.3.0'</span>
</code></pre>
<p>This automatically adds a virtual environment and a <code>.lock</code> file with a new entry:</p>
<pre><code class="lang-bash">├── .venv <span class="hljs-comment"># hidden folder inside of which your required packages will be installed</span>
└── uv.lock
</code></pre>
<p>The <code>.lock</code> file keeps record of the exact versions of your dependencies and their required packages. You should never modify it directly.</p>
<h3 id="heading-how-to-remove-a-dependency">How to Remove a Dependency</h3>
<p>To remove a dependency, run:</p>
<pre><code class="lang-bash">uv remove numpy
</code></pre>
<p>This will also remove the corresponding entry from the <code>.lock</code> file.</p>
<h3 id="heading-how-to-run-python-code">How to Run Python Code</h3>
<p>To run your Python script, execute:</p>
<pre><code class="lang-bash">uv run main.py
</code></pre>
<p>This will run the code inside the created virtual environment with the installed dependencies in one step! That is, you don’t need to explicitly activate the virtual environment and then run your code.</p>
<h3 id="heading-how-to-move-your-project">How to Move Your Project</h3>
<p>Sometimes you may want to move your project to another machine. Maybe you want to share it with colleagues, or set it up on a production server. Getting to run your code on another machine has never been easier than with <code>uv</code>. You can simply copy your project folder to the destination environment and run the following command in the destination terminal:</p>
<pre><code class="lang-bash">uv sync --locked
</code></pre>
<p>This installs the exact versions of your project dependencies!</p>
<h3 id="heading-how-to-add-and-run-tools">How to Add and Run Tools</h3>
<p>Sometimes you may need tools like <code>ruff</code>, a Python linter (code formatter), which you can add just like any other dependency to your project:</p>
<pre><code class="lang-bash">uv add ruff
</code></pre>
<p>To run an installed tool, execute:</p>
<pre><code class="lang-bash">uv run ruff check
</code></pre>
<h3 id="heading-how-to-run-tools-without-adding-them-to-your-project">How to Run Tools Without Adding Them to Your Project</h3>
<p>Sometimes you may not want to add tools to your dependencies. For example, because you just want to make one-off checks. <code>uv</code> has got you covered with <code>tool run</code>. Simply run:</p>
<pre><code class="lang-bash">uv tool run ruff check
<span class="hljs-comment"># or equivalently </span>
uvx ruff check
</code></pre>
<p>This will run the tool in an isolated environment independent.</p>
<h3 id="heading-how-to-manage-multiple-python-versions">How to Manage Multiple Python Versions</h3>
<p>If your system has Python installed, <code>uv</code> will use it. Otherwise, it will automatically install the latest Python version when you execute Python code or create a virtual environment with <code>uv</code>. However, you can also use it to manage multiple Python versions:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># install the latest Python version</span>
uv python install
<span class="hljs-comment"># install multiple Python versions</span>
uv python install 3.11 3.12
<span class="hljs-comment"># list all installed Python versions</span>
uv python list
<span class="hljs-comment"># set the version to be used in the current project (.python-version)</span>
uv python pin 3.11
</code></pre>
<h3 id="heading-how-to-migrate-from-pip-to-uv">How to Migrate from pip to uv</h3>
<p><code>uv</code> works as drop-in replacement for <code>pip</code>, meaning that you can use common <code>pip</code> commands with <code>uv</code>. Let’s say you received a <code>requirements.txt</code> file. To install the listed dependencies, you can run:</p>
<pre><code class="lang-bash">uv pip install -r requirements.txt
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You just learned how to use <code>uv</code>! Before <code>uv</code>, managing dependencies, virtual environments and Python versions had been notoriously cumbersome. As an ML engineer at <a target="_blank" href="https://mljobs.io">MLjobs.io</a>, I can safely say that <code>uv</code> has been a game changer. Check out <code>uv</code>'s <a target="_blank" href="https://docs.astral.sh/uv/">documentation</a> to learn more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate AI into Your Terminal Using OpenCode ]]>
                </title>
                <description>
                    <![CDATA[ Artificial intelligence is no longer just a helper, it’s becoming a real coding partner. Over the past year, developers have seen tools like GitHub Copilot and ChatGPT transform how code is written. But these tools mostly live in editors or browsers.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/integrate-ai-into-your-terminal-using-opencode/</link>
                <guid isPermaLink="false">68e8540e389372f3cb828525</guid>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Fri, 10 Oct 2025 00:32:14 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760056302216/02783203-e22e-4f23-b5b9-2eae9523124c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Artificial intelligence is no longer just a helper, it’s becoming a real coding partner. Over the past year, developers have seen tools like GitHub Copilot and ChatGPT transform how code is written. But these tools mostly live in editors or browsers. </p>
<p><a target="_blank" href="http://opencode.ai/">OpenCode</a>, an open-source project, takes a different path. It brings an AI assistant directly into your terminal, letting you write, debug, and refactor code using natural language. All this without ever leaving the command line.</p>
<p>It combines the power of large language models with real-world developer workflows, so you can build software faster, with fewer distractions.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-opencode">What is OpenCode?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-use-opencode">Why Use OpenCode?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-opencode-works">How OpenCode Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-power-of-context">The Power of Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-privacy-and-control">Privacy and Control</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-use-cases">Real-World Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-community-and-ecosystem">Community and Ecosystem</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-future-of-ai-powered-development">The Future of AI-Powered Development</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-opencode">What is OpenCode?</h2>
<p>OpenCode is an open-source AI coding assistant that works right inside your terminal. It’s built for developers who prefer command-line speed but still want the intelligence of modern AI models. </p>
<p>You can think of it as having ChatGPT or Claude built into your local development environment, except it’s fully open and under your control.</p>
<p>Imagine typing a command like <code>opencode fix error in main.go</code>, and the AI instantly reads your code, finds the problem, and suggests a clean fix. That’s the magic of OpenCode.</p>
<p>The project is hosted at <a target="_blank" href="https://github.com/sst/opencode">github.com/sst/opencode</a> and has quickly become one of the most popular open-source AI tools for developers. As of October 2025, it has more than 26,000 stars on GitHub, proving that developers are hungry for coding tools that blend automation and simplicity.</p>
<h2 id="heading-why-use-opencode">Why Use OpenCode?</h2>
<p>Most AI coding assistants work inside editors like VS Code or JetBrains. OpenCode, on the other hand, lives in your terminal. This means it can work with any language, any editor, and any environment. </p>
<p>You can use it while building a backend in Go, a frontend in React, or even while managing infrastructure scripts.</p>
<p>OpenCode uses your project context to understand your code deeply. It scans through your files, recognizes dependencies, and maintains context across multiple commands. This allows it to perform complex operations like:</p>
<ul>
<li><p>Refactoring multiple files in one go</p>
</li>
<li><p>Adding new features based on natural language instructions</p>
</li>
<li><p>Explaining errors and suggesting fixes</p>
</li>
<li><p>Reviewing your code before you commit</p>
</li>
</ul>
<p>All of this happens without needing to upload your code to the cloud. Everything stays local, which is a major advantage for teams handling private or sensitive codebases.</p>
<h2 id="heading-how-opencode-works">How OpenCode Works</h2>
<p>OpenCode connects your local files, git history, and LLMs together. When you run a command like <code>opencode explain this function</code>, it gathers context from the files you’re working on, passes that to an AI model, and shows the response directly in your terminal.</p>
<p>The setup is simple. You can install OpenCode using a single command:</p>
<pre><code class="lang-plaintext">curl -fsSL https://opencode.ai/install | bash
</code></pre>
<p>Once installed, you can start using it by running:</p>
<pre><code class="lang-plaintext">opencode
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759742736177/89f883ae-fdfa-412c-a524-d72bcfab2138.png" alt="Opencode" class="image--center mx-auto" width="1000" height="475" loading="lazy"></p>
<p>The tool will open an interactive terminal interface where you can chat, run tasks, and even let the AI make edits automatically. It supports multiple model providers, including OpenAI, Anthropic, and local models like Ollama.</p>
<p>Behind the scenes, OpenCode uses a plugin-like architecture that makes it easy to extend. Developers can write “actions” or “skills” that teach the AI how to perform domain-specific tasks — like generating <a target="_blank" href="https://www.freecodecamp.org/news/learn-kubernetes-handbook-devs-startups-businesses/">Kubernetes</a> manifests, writing API routes, or setting up unit tests.</p>
<p>Once Opencode is installed, go to the project repository and type <code>opencode</code> . Then type <code>/init</code> for Opencode to analyze your repository and created <code>agents.md</code> file. </p>
<p>You can then start asking questions like “What does this repository do?”. Here is a sample output from my portfolio website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759742758416/b9e560cb-88f9-4488-8bd0-0c4cd504ba0c.png" alt="Opencode project summary" class="image--center mx-auto" width="1000" height="255" loading="lazy"></p>
<p>You can use the the <a target="_blank" href="https://opencode.ai/docs">OpenCode documentation</a> to learn more tips and tricks to work with OpenCode. </p>
<h2 id="heading-the-power-of-context">The Power of Context</h2>
<p>One of OpenCode’s biggest strengths is how it handles context. Traditional chatbots lose track of what you’re working on after a few turns. OpenCode doesn’t. </p>
<p>OpenCode remembers your codebase, understands imports, and keeps track of related files. This allows it to work more like a real developer assistant.</p>
<p>Let’s say you tell it: <em>“Add authentication to my Express.js app.”</em></p>
<p>OpenCode will scan your project, identify where routes are defined, create middleware for login, and even suggest where to store tokens securely. It’s this blend of contextual awareness and natural language understanding that makes OpenCode feel more like a teammate than a tool.</p>
<h2 id="heading-privacy-and-control">Privacy and Control</h2>
<p>A major reason developers love OpenCode is control. Unlike cloud-based assistants, OpenCode doesn’t send your code to remote servers by default. </p>
<p>You choose the model provider and what data gets shared. If you run a local model, your entire workflow stays private.</p>
<p>This is especially important for companies with strict data rules. With OpenCode, teams can integrate AI safely into their workflows without breaking compliance or risking leaks.</p>
<p>The tool also integrates with version control systems like Git. Every change the AI suggests can be previewed before committing. You can accept, reject, or modify them just like a pull request. This ensures transparency and keeps human developers in charge.</p>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<p>Developers are using OpenCode in many creative ways. Backend engineers use it to generate API routes. Frontend teams use it to fix TypeScript errors. DevOps engineers rely on it to generate Terraform scripts and Dockerfiles.</p>
<p>Even researchers and students find it useful for exploring new codebases. By simply asking questions like “What does this repository do?” or “Where is the entry point?”, they can get clear, AI-driven summaries of complex projects.</p>
<p>The flexibility of OpenCode means it can fit almost any workflow. It doesn’t replace your tools , it enhances them. Whether you’re using Vim, VS Code, or JetBrains IDEs, OpenCode works alongside your setup.</p>
<h2 id="heading-community-and-ecosystem">Community and Ecosystem</h2>
<p>OpenCode is not just a tool, it’s a growing community. The project’s GitHub discussions and Discord are full of contributors sharing workflows, plugins, and even model configuration tips.</p>
<p>The maintainers, part of the SST team, are known for building tools that make cloud and AI development simpler. They continue to release frequent updates and listen closely to community feedback.</p>
<p>Recent updates have added features like persistent sessions, better error recovery, and support for local models. The roadmap includes plans for even deeper IDE integration and team collaboration features.</p>
<h2 id="heading-the-future-of-ai-powered-development">The Future of AI-Powered Development</h2>
<p>As AI coding agents mature, the line between writing code and describing what you want will continue to blur. Tools like OpenCode show us what that future might look like , one where developers spend less time fighting syntax and more time building ideas.</p>
<p>Imagine a day when you start a new project by typing: <em>“Create a REST API for a todo app with user authentication and SQLite support.”</em></p>
<p>And within seconds, your project structure, database, and routes are ready and reviewed by your AI assistant, tested, and documented.</p>
<p>That’s the vision OpenCode is moving toward: AI tools that don’t just generate code, but understand context, handle complexity, and let humans stay in control.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>OpenCode represents a turning point in how developers interact with AI. It’s open-source, private, and deeply integrated into the terminal, making it both powerful and flexible. While other assistants are built around specific IDEs or cloud services, OpenCode keeps developers at the center.</p>
<p>With its growing community, smart architecture, and commitment to privacy, OpenCode isn’t just another coding assistant. It’s a glimpse into the future of AI-driven software development, a future where your terminal becomes the smartest part of your workflow.</p>
<p><em>Hope you enjoyed this article. Signup for my free AI newsletter</em> <a target="_blank" href="https://www.turingtalks.ai/"><strong><em>TuringTalks.ai</em></strong></a> <em>for more hands-on tutorials on AI. You can also find</em> <a target="_blank" href="https://manishshivanandhan.com/"><strong><em>visit my website</em></strong></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is the GitHub CLI? How to Use GitHub from the Command Line ]]>
                </title>
                <description>
                    <![CDATA[ The GitHub CLI (Command Line Interface) is a powerful tool developed by GitHub that allows developers to interact with GitHub directly from the terminal. It provides a simple way to perform many GitHub tasks without leaving the command line interface... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-github-from-the-command-line/</link>
                <guid isPermaLink="false">68d6c4873324dabb31fd7214</guid>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ AYUSH MISHRA ]]>
                </dc:creator>
                <pubDate>Fri, 26 Sep 2025 16:51:19 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758905411969/b1506cff-650a-4098-bd70-e8bb3b0bcb9a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The GitHub CLI (Command Line Interface) is a powerful tool developed by GitHub that allows developers to interact with GitHub directly from the terminal. It provides a simple way to perform many GitHub tasks without leaving the command line interface, such as managing repositories, handling pull requests and issues, working with GitHub Actions, and more.</p>
<p>In this tutorial, you’ll to learn what the GitHub CLI is, how to install and set it up, and how to use it for everyday tasks such as creating repositories, managing issues and pull requests, working with GitHub Actions, and automating tasks using custom aliases. You’ll learn how to replace some functionalities on GitHub’s web interface with quick commands in your terminal.</p>
<h2 id="heading-heres-what-well-cover"><strong>Here’s what we’ll cover:</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-overview-of-github-cli">Overview of GitHub CLI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-features-of-github-cli">Key Features</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-using-github-cli">Benefits of Using GitHub CLI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-installation-and-setup">Installation and Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#authenticating-with-a-github-account">Authenticating with a GitHub Account</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-navigating-the-github-cli">Navigating the GitHub CLI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-repositories-with-the-github-cli">Managing Repositories</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-managing-branches-and-pull-requests">Working with Pull Requests and Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pushing-and-pulling-changes">Pushing and Pulling Changes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-working-with-github-actions">Working with GitHub Actions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-gists-with-the-github-cli">Managing Gists</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-interacting-with-releases-and-tags">Releases and Tags</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-extend-the-github-cli-with-custom-scripts-and-aliases">Custom Scripts and Aliases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-troubleshooting-common-issues">Troubleshooting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-overview-of-github-cli">Overview of GitHub CLI</h2>
<p>You can use the GitHub CLI to bridge the gap between GitHub's web interface and your local environment. You can perform various tasks such as creating issues, managing repositories, or even checking the status of your GitHub Actions workflows using the CLI. Using the CLI, you can perform almost all the tasks that you might complete on the GitHub website.</p>
<h3 id="heading-key-features-of-github-cli">Key Features of GitHub CLI</h3>
<ul>
<li><p><strong>Repository management:</strong> Easily create, clone, view, and manage repositories.</p>
</li>
<li><p><strong>Pull requests and issues:</strong> Manage pull requests and issues directly from the terminal, including creating, merging, and listing them.</p>
</li>
<li><p><strong>GitHub Actions:</strong> Interact with workflows and manage workflow runs.</p>
</li>
<li><p><strong>Authentication:</strong> Provides a secure way to authenticate with your GitHub account, supporting SSH keys, tokens, and OAuth.</p>
</li>
<li><p><strong>Custom scripting:</strong> Lets you create custom scripts and aliases to automate repetitive tasks and streamline development processes.</p>
</li>
</ul>
<h3 id="heading-benefits-of-using-github-cli">Benefits of Using GitHub CLI</h3>
<p>Suppose you’re working on a project, and you need to create a new issue on GitHub. Normally, you would switch to your browser, log in to GitHub, navigate to the repository, click on the “Issues” tab, and then click “New Issue.” With GitHub CLI, you can do all of this by typing a single command, without ever leaving your terminal. This makes your workflow faster and saves time.</p>
<h2 id="heading-installation-and-setup">Installation and Setup</h2>
<p>To install GitHub CLI on Windows, you can use the winget package manager. Winget is a command-line tool that allows you to install software easily.</p>
<h3 id="heading-installing-github-cli-on-windows-macos-and-linux"><strong>Installing GitHub CLI on Windows, macOS, and Linux</strong></h3>
<h3 id="heading-windows"><strong>Windows:</strong></h3>
<p>Run the command given below:</p>
<pre><code class="lang-plaintext">winget install --id GitHub.cli
</code></pre>
<ul>
<li><p><code>winget install</code><strong>:</strong> Tells Windows to install a new software package.</p>
</li>
<li><p><code>--id GitHub.cli</code><strong>:</strong> Specifies the exact package ID for GitHub CLI.</p>
</li>
</ul>
<p>After running this command, GitHub CLI will be installed on your Windows system.</p>
<h3 id="heading-macos">macOS:</h3>
<p>You can use Homebrew to install GitHub CLI on macOS. Open your terminal and run:</p>
<pre><code class="lang-plaintext">brew install gh
</code></pre>
<h3 id="heading-linux">Linux:</h3>
<p>On Linux, you can use your package manager. For example, on Ubuntu, you can run:</p>
<pre><code class="lang-plaintext">sudo apt install gh
</code></pre>
<h3 id="heading-authenticating-with-a-github-account">Authenticating with a GitHub Account</h3>
<p>After installing GitHub CLI, the next step is to authenticate it with your GitHub account.</p>
<h4 id="heading-run-authentication-command">Run Authentication Command:</h4>
<p>Type <code>gh auth login</code> in the terminal and press Enter.</p>
<pre><code class="lang-plaintext">gh auth login
</code></pre>
<p>You’ll then be prompted to select an authentication method. The recommended option is to authenticate via a web browser.</p>
<p>If you select the browser method, GitHub CLI will open a link in your default browser, where you can log in to GitHub.</p>
<h4 id="heading-complete-authentication">Complete Authentication:</h4>
<p>After logging in, the browser will confirm that the GitHub CLI is connected to your account.</p>
<p>You can verify the authentication status by running:</p>
<pre><code class="lang-plaintext">gh auth status
</code></pre>
<h2 id="heading-navigating-the-github-cli">Navigating the GitHub CLI</h2>
<p>The GitHub CLI is easy to navigate, and its command structure is intuitive.</p>
<h3 id="heading-command-structure-and-syntax">Command Structure and Syntax</h3>
<p>GitHub CLI commands follow a simple and straightforward pattern:</p>
<pre><code class="lang-plaintext">gh [command] [subcommand] [flags]
</code></pre>
<ul>
<li><p><strong>Command:</strong> The main action you want to perform (for example, repo, issue, pr).</p>
</li>
<li><p><strong>Subcommand:</strong> A specific task within the command (for example, create, list, view).</p>
</li>
<li><p><strong>Flags:</strong> Optional parameters that modify the command's behavior (for example, --title, --body).</p>
</li>
</ul>
<h3 id="heading-commonly-used-commands-and-flags">Commonly Used Commands and Flags</h3>
<p>Here are some common GitHub CLI commands:</p>
<ul>
<li><p><strong>Creating a repository:</strong> <code>gh repo create</code></p>
</li>
<li><p><strong>Listing issues:</strong> <code>gh issue list</code></p>
</li>
<li><p><strong>Creating a pull request:</strong> <code>gh pr create</code></p>
</li>
<li><p><strong>Viewing a repository's details:</strong> <code>gh repo view</code></p>
</li>
</ul>
<p>To see all available commands and options, you can always run:</p>
<pre><code class="lang-plaintext">gh help
</code></pre>
<h2 id="heading-how-to-manage-repositories-with-the-github-cli">How to Manage Repositories with the GitHub CLI</h2>
<p>Let’s go through examples of some of the commands you’ll use the most often.</p>
<h3 id="heading-creating-and-cloning-repositories">Creating and Cloning Repositories</h3>
<p>To create a new GitHub repository directly from the terminal, just use the following command:</p>
<pre><code class="lang-plaintext">gh repo create my-repo-name
</code></pre>
<p>To clone an existing repository, use the following command:</p>
<pre><code class="lang-plaintext">gh repo clone owner/repo-name
</code></pre>
<h3 id="heading-managing-branches-and-pull-requests">Managing Branches and Pull Requests</h3>
<p>GitHub CLI allows you to handle issues and pull requests (PRs) without leaving the terminal.</p>
<p>Switching branches or creating pull requests is simple. To create a new branch:</p>
<pre><code class="lang-plaintext">git checkout -b new-branch-name
</code></pre>
<p>Then, to create a pull request:</p>
<pre><code class="lang-plaintext">gh pr create --title "Your PR Title" --body "Description of your PR"
</code></pre>
<h3 id="heading-pushing-and-pulling-changes">Pushing and Pulling Changes</h3>
<p>Push your changes to GitHub with this command:</p>
<pre><code class="lang-plaintext">git push origin branch-name
</code></pre>
<p>And pull the latest changes with:</p>
<pre><code class="lang-plaintext">git pull
</code></pre>
<h3 id="heading-working-with-github-actions">Working with GitHub Actions</h3>
<p>GitHub CLI also supports GitHub Actions, allowing you to manage workflows directly from your terminal.</p>
<p>You can manually trigger workflows using the following:</p>
<pre><code class="lang-plaintext">gh workflow run workflow-name
</code></pre>
<p>And you can monitor the status of workflows with:</p>
<pre><code class="lang-plaintext">gh run list
</code></pre>
<p>To see detailed logs of a workflow, run this:</p>
<pre><code class="lang-plaintext">gh run view run-id --log
</code></pre>
<h3 id="heading-cloning-and-forking-repositories">Cloning and Forking Repositories</h3>
<p>Cloning and forking are essential tasks when working on projects from other repositories.</p>
<p>To clone a repository, use this command:</p>
<pre><code class="lang-plaintext">gh repo clone &lt;repository-name&gt;
</code></pre>
<p>To fork a repository, do this:</p>
<pre><code class="lang-plaintext">gh repo fork &lt;repository-url&gt;
</code></pre>
<h4 id="heading-example"><strong>Example:</strong></h4>
<p>Here’s what it would look like:</p>
<pre><code class="lang-plaintext">gh repo clone example-repo
</code></pre>
<pre><code class="lang-plaintext">gh repo fork https://github.com/username/repository-name
</code></pre>
<h3 id="heading-how-to-work-with-github-actions">How to Work with GitHub Actions</h3>
<p>Using the GitHub CLI, you can also manage GitHub Actions, which are automated tasks you can run in response to certain events in your repository.</p>
<h4 id="heading-triggering-and-monitoring-workflows">Triggering and Monitoring Workflows</h4>
<p>You can trigger a workflow manually like this:</p>
<pre><code class="lang-plaintext">gh workflow run &lt;workflow-name&gt;
</code></pre>
<p>And you can monitor workflow runs with this:</p>
<pre><code class="lang-plaintext">gh run list
</code></pre>
<h4 id="heading-managing-workflow-runs-and-logs">Managing Workflow Runs and Logs</h4>
<p>If you want to check the details of a specific workflow run, you can view logs directly from the CLI:</p>
<pre><code class="lang-plaintext">gh run view &lt;run-id&gt; --log
</code></pre>
<p>You can also use GitHub CLI commands to enhance your Continuous Integration/Continuous Deployment (CI/CD) pipelines, ensuring smooth automation and better control over our workflows.</p>
<h3 id="heading-how-to-update-the-github-cli">How to Update the GitHub CLI</h3>
<p>To make sure that you’re using the latest version of GitHub CLI with all the latest features and fixes, you can update it using winget.</p>
<pre><code class="lang-plaintext">winget upgrade --id GitHub.cli
</code></pre>
<ul>
<li><p><strong>winget upgrade:</strong> Checks for updates for the specified package.</p>
</li>
<li><p><strong>--id GitHub.cli:</strong> Identifies the GitHub CLI package for the upgrade.</p>
</li>
</ul>
<h2 id="heading-advanced-github-cli-features-and-integrations">Advanced GitHub CLI Features and Integrations</h2>
<p>The GitHub CLI is not only useful for performing basic tasks. You can also perform some advanced operations with its help.</p>
<h3 id="heading-how-to-manage-gists-with-the-github-cli">How to Manage Gists with the GitHub CLI</h3>
<p>Gists are a simple way to share snippets of code. You can create, list, and manage your Gists right from the CLI. Here’s how you can create a gist:</p>
<pre><code class="lang-plaintext">gh gist create my-code-snippet.py
</code></pre>
<p>To list your gists:</p>
<pre><code class="lang-plaintext">gh gist list
</code></pre>
<h3 id="heading-interacting-with-releases-and-tags">Interacting with Releases and Tags</h3>
<p>To manage releases and tags, GitHub CLI provides commands to create, list, and delete releases. Here’s an example of creating a release:</p>
<pre><code class="lang-plaintext">gh release create v1.0.0
</code></pre>
<h3 id="heading-how-to-extend-the-github-cli-with-custom-scripts-and-aliases">How to Extend the GitHub CLI with Custom Scripts and Aliases</h3>
<p>You can write your own scripts and integrate them into GitHub CLI, or create aliases for commands you use frequently to save time. Aliases let you create shortcuts for commands that you use often. For example, the command given below creates an alias <code>prlist</code> that will show all pull requests, regardless of their state:</p>
<pre><code class="lang-plaintext">gh alias set prlist "pr list --state all"
</code></pre>
<p>In the same manner, you can create a shortcut <code>co</code> to quickly check out a pull request branch without typing the full command each time. The command is given below:</p>
<pre><code class="lang-plaintext">gh alias set co "pr checkout"
</code></pre>
<h3 id="heading-troubleshooting-common-issues">Troubleshooting Common Issues</h3>
<p>If you face any issues, you can troubleshoot by checking the command syntax, ensuring your GitHub CLI is up to date, or consulting the documentation using the command:</p>
<pre><code class="lang-plaintext">gh help &lt;command&gt;
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>GitHub CLI is an excellent tool that helps developers work directly from the terminal. It lets you manage repositories, handle pull requests and issues, trigger and monitor GitHub Actions, and even work with Gists.</p>
<p>You can save time and improve productivity as developers using this powerful tool. Keep exploring its new features and stay updated with the latest version.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Essential CLI/TUI Tools for Developers ]]>
                </title>
                <description>
                    <![CDATA[ As developers, we spend a lot of time in our terminals. And there are tons of great CLI/TUI tools that can boost our productivity (as well as some that are just fun to use). From managing Git repositories and navigating file systems to monitoring sys... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/essential-cli-tui-tools-for-developers/</link>
                <guid isPermaLink="false">6798fd7b4666e531b7dd7586</guid>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cli ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Pliutau ]]>
                </dc:creator>
                <pubDate>Tue, 28 Jan 2025 15:53:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738077620615/22e3c744-d609-4469-ae10-ef8ad4b515a1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As developers, we spend a lot of time in our terminals. And there are tons of great CLI/TUI tools that can boost our productivity (as well as some that are just fun to use). From managing Git repositories and navigating file systems to monitoring system performance and even playing retro games, the command line offers a powerful and versatile environment.</p>
<p>In this article, we’ll go through a collection of CLI / TUI tools that have been widely adopted in the developer community, spanning various categories such as version control, system utilities, text editors, and more. I wanted to give you a diverse selection that caters to different needs and workflows.</p>
<p>For each tool, I’ll include an overview, highlighting its key features and use cases, along with clear and concise installation instructions for various operating systems, ensuring you can quickly get up and running with these valuable command-line companions.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-kubernetes-tools">Kubernetes Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-container-tools">Container Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-file-and-text-tools">File and Text Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-git-tools">Git Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-development-tools">Development Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-networking-tools">Networking Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-workstation-tools">Workstation Tools</a></p>
</li>
</ul>
<h2 id="heading-kubernetes-tools"><strong>Kubernetes Tools</strong></h2>
<h3 id="heading-k9shttpsgithubcomderailedk9s-kubernetes-cli-to-manage-your-clusters-in-style"><a target="_blank" href="https://github.com/derailed/k9s"><strong>k9s</strong></a> — Kubernetes CLI To Manage Your Clusters In Style</h3>
<p>K9s is a must-have tool for anyone working with Kubernetes. Its intuitive terminal-based UI, real-time monitoring capabilities, and powerful command options make it a standout in the world of Kubernetes management tools.</p>
<p>The K9s project is designed to continually watch Kubernetes cluster for changes and offer subsequent commands to interact with observed resources. This makes it easier to manage applications, especially in a complex, multi-cluster environment. The project’s aim is to make Kubernetes management more accessible and less daunting, especially for those who are not Kubernetes experts.</p>
<p>Just launch k9s in your terminal and start exploring the Kubernetes resources with ease.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*tkfwKS01NCnUBE-N.png" alt="K9s interface" width="700" height="367" loading="lazy"></p>
<p>To install K9s:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install derailed/k9s/k9s

<span class="hljs-comment"># via snap for Linux</span>
snap install k9s --devmode

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install k9s

<span class="hljs-comment"># via go install</span>
go install github.com/derailed/k9s@latest
</code></pre>
<h3 id="heading-kubectxhttpsgithubcomahmetbkubectx-switch-between-contexts-clusters-on-kubectl-faster"><a target="_blank" href="https://github.com/ahmetb/kubectx"><strong>kubectx</strong></a> — switch between contexts (clusters) on kubectl faster.</h3>
<p>Kubectx is the most popular tool for switching Kubernetes contexts, but it has the fewest features! It displays all the contexts in your Kubernetes config as a selectable list and lets you pick one. That’s it!</p>
<p>This project comes with 2 tools:</p>
<ul>
<li><p><strong>kubectx</strong> is a tool that helps you switch between contexts (clusters) on kubectl faster.</p>
</li>
<li><p><strong>kubens</strong> is a tool to switch between Kubernetes namespaces (and configure them for kubectl) easily.</p>
</li>
</ul>
<p>These tools make it very easy to switch between Kubernetes clusters and namespaces if you work with many of them daily. Here you can see it in action:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*g442WF-cXW-z1dKQ.gif" alt="0*g442WF-cXW-z1dKQ" width="1367" height="472" loading="lazy"></p>
<p>To install kubectx:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install kubectx

<span class="hljs-comment"># via apt for Debian</span>
sudo apt install kubectx

<span class="hljs-comment"># via pacman for Arch Linux</span>
sudo pacman -S kubectx

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install kubens kubectx
</code></pre>
<h3 id="heading-kubescapehttpsgithubcomkubescapekubescape-kubernetes-security-platform-for-your-ide-cicd-pipelines-and-clusters"><a target="_blank" href="https://github.com/kubescape/kubescape"><strong>kubescape</strong></a> — Kubernetes security platform for your IDE, CI/CD pipelines, and clusters.</h3>
<p>I hope you take the security of your Kubernetes clusters seriously. If so, <strong>kubescape</strong> is really great for testing if your Kubernetes cluster is deployed securely according to multiple frameworks.</p>
<p>Kubescape can scan clusters, YAML files, and Helm charts and detects the misconfigurations according to multiple sources.</p>
<p>I usually use it in my CI/CD to scan for vulnerabilities automatically when changing Kubernetes manifests or Helm templates.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*Ft2r01ij9Rxj2-V0.png" alt="kubescape scan" width="700" height="556" loading="lazy"></p>
<p>To install kubescape:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install kubescape

<span class="hljs-comment"># via apt for Debian</span>
sudo add-apt-repository ppa:kubescape/kubescape
sudo apt update
sudo apt install kubescape

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install kubescape
</code></pre>
<h2 id="heading-container-tools"><strong>Container Tools</strong></h2>
<h3 id="heading-ctophttpsgithubcombcicenctop-a-top-like-interface-for-container-metrics"><a target="_blank" href="https://github.com/bcicen/ctop"><strong>ctop</strong></a> — A top-like interface for container metrics.</h3>
<p><strong>ctop</strong> is basically a better version of <code>docker stats</code>. It provides a concise and condensed overview of real-time metrics for multiple containers. It comes with built-in support for Docker and runC, and connectors for other container and cluster systems are planned for future releases.</p>
<p>Using ctop is simple. Once you have the tool open, you’ll see all of your currently active containers listed.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*EJ5kdlEs5M5QxDBy.gif" alt="ctop in action" width="1195" height="414" loading="lazy"></p>
<p>To install ctop:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install ctop

<span class="hljs-comment"># via pacman for Arch Linux</span>
sudo pacman -S ctop

<span class="hljs-comment"># via scoop for Windows</span>
scoop install ctop
</code></pre>
<h3 id="heading-lazydockerhttpsgithubcomjesseduffieldlazydocker-a-simple-terminal-ui-for-both-docker-and-docker-compose"><a target="_blank" href="https://github.com/jesseduffield/lazydocker"><strong>lazydocker</strong></a> — A simple terminal UI for both docker and docker-compose.</h3>
<p>While Docker's command-line interface is powerful, sometimes you might want a more visual approach without the overhead of a full GUI. This is especially true when managing Docker containers on a headless Linux server where installing a web-based GUI might be undesirable.</p>
<p>Lazydocker was created by <a target="_blank" href="https://github.com/jesseduffield">Jesse Duffield</a> to help make <a target="_blank" href="https://github.com/jesseduffield"></a>managing docker containers a bit easier. Simply put, Lazydocker is a terminal UI (written in Golang) for the docker and docker-compose commands.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*Cbmx4ShRSO7ccVy2.gif" alt="lazydocker in action" width="1456" height="819" loading="lazy"></p>
<p>To install lazydocker:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install lazydocker

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install lazydocker

<span class="hljs-comment"># via go install</span>
go install github.com/jesseduffield/lazydocker@latest
</code></pre>
<h3 id="heading-divehttpsgithubcomwagoodmandive-a-tool-for-exploring-each-layer-in-a-docker-image"><a target="_blank" href="https://github.com/wagoodman/dive"><strong>dive</strong></a> — A tool for exploring each layer in a Docker image.</h3>
<p>A Docker image is made up of layers, and with every layer you add on, more space will be taken up by the image. Therefore, the more layers in the image, the more space the image will require.</p>
<p>That’s where <strong>dive</strong> shines, it helps you explore your Docker image and layer contents. It can also help you find ways to shrink the size of your Docker/OCI image.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*swo_hrKJ9EV7hyMs.gif" alt="0*swo_hrKJ9EV7hyMs" width="1456" height="909" loading="lazy"></p>
<p>To install dive:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install dive

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S dive

<span class="hljs-comment"># via go install</span>
go get github.com/wagoodman/dive
</code></pre>
<h2 id="heading-file-and-text-tools"><strong>File and Text Tools</strong></h2>
<h3 id="heading-jqhttpsgithubcomjqlangjq-command-line-json-processor"><a target="_blank" href="https://github.com/jqlang/jq"><strong>jq</strong></a> — Command-line JSON processor.</h3>
<p>You may be aware of this one already as it’s well known in the developer community.</p>
<p>Unfortunately, shells such as Bash can’t interpret and work with JSON directly. That’s where you can use <strong>jq</strong> as a command-line JSON processor that’s similar to sed, awk, grep, and so on for JSON data. It’s written in portable C and doesn’t have any runtime dependencies. This lets you slice, filter, map, and transform structured data with ease.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*uwysqWprpmrLrJQP.png" alt="0*uwysqWprpmrLrJQP" width="700" height="328" loading="lazy"></p>
<p>To install jq, you can download the latest releases from the <a target="_blank" href="https://github.com/jqlang/jq/releases">GitHub release page.</a></p>
<h3 id="heading-bathttpsgithubcomsharkdpbat-a-cat1-clone-with-wings"><a target="_blank" href="https://github.com/sharkdp/bat"><strong>bat</strong></a> — A cat(1) clone with wings.</h3>
<p>This is the most used CLI on my machine currently. A few years ago it was <strong>cat</strong>, which is great but doesn’t provide syntax highlighting, or Git integration</p>
<p>Bat’s syntax highlighting supports many programming and markup languages, helping you make your code more readable directly in the terminal. Git integration lets you see modifications in relation to the index, highlighting the lines you’ve added or changed.</p>
<p>Simply run <code>bat filename</code> and enjoy its output.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:656/0*L02HhsqDcq2_G_z4.png" alt="Bat example" width="656" height="450" loading="lazy"></p>
<p>To install bat:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install bat

<span class="hljs-comment"># via apt for Debian</span>
sudo apt install bat

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S bat

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install bat
</code></pre>
<h3 id="heading-ripgrephttpsgithubcomburntsushiripgrep-recursively-search-directories-for-a-regex-pattern-while-respecting-your-gitignore"><a target="_blank" href="https://github.com/BurntSushi/ripgrep"><strong>ripgrep</strong></a> — Recursively search directories for a regex pattern while respecting your gitignore.</h3>
<p><strong>ripgrep</strong> is definitely becoming a popular alternative (if not the most popular) to the <strong>grep</strong> command. Even some editors like <a target="_blank" href="https://code.visualstudio.com/updates/v1_11">Visual Studio Code</a> are using ripgrep to power their search offerings.</p>
<p>The major selling point is its default behavior for recursive search and speed.</p>
<p>I now rarely use grep on my personal machine, as ripgrep is much faster.</p>
<p>To install ripgrep:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install ripgrep

<span class="hljs-comment"># via apt for Debian</span>
sudo apt-get install ripgrep

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S ripgrep

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install ripgrep
</code></pre>
<h2 id="heading-git-tools"><strong>Git Tools</strong></h2>
<h3 id="heading-lazygithttpsgithubcomjesseduffieldlazygit-simple-terminal-ui-for-git-commands"><a target="_blank" href="https://github.com/jesseduffield/lazygit"><strong>lazygit</strong></a> — Simple terminal UI for git commands.</h3>
<p><strong>lazygit</strong> is another great terminal UI for Git commands developed by <a target="_blank" href="https://github.com/jesseduffield"><strong>Jesse Duffield</strong></a> using Go.</p>
<p>I don’t mind using the Git CLI directly for simple things, but it is famously verbose for more advanced use cases. I am just too lazy to memorize longer commands.</p>
<p>And lazigit has made me a more productive Git user than ever.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*ykEtn2HQ9QgU40jx.png" alt="lazygit interface" width="700" height="381" loading="lazy"></p>
<p>To install lazygit:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install jesseduffield/lazygit/lazygit

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S lazygit

<span class="hljs-comment"># via scoop for Windows</span>
scoop install lazygit
</code></pre>
<h2 id="heading-development-tools"><strong>Development Tools</strong></h2>
<h3 id="heading-atachttpsgithubcomjulien-cpsnatac-a-simple-api-client-postman-like-in-your-terminal"><a target="_blank" href="https://github.com/Julien-cpsn/ATAC"><strong>ATAC</strong></a> — A simple API client (Postman-like) in your terminal.</h3>
<p>ATAC stands for Arguably a Terminal API Client. It’s based on popular clients like Postman, Insomnia, and Bruno, but it runs inside your terminal without needing any particular graphical environment.</p>
<p>It works best for developers who need an offline, cross-platform API client right at their fingertips (terminal).</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*NoOMeMxkELNFI9RS.png" alt="ATAC" width="700" height="376" loading="lazy"></p>
<p>To install ATAC:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew tap julien-cpsn/atac
brew install atac

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S atac
</code></pre>
<h3 id="heading-k6httpsgithubcomgrafanak6-a-modern-load-testing-tool-using-go-and-javascript"><a target="_blank" href="https://github.com/grafana/k6"><strong>k6</strong></a> — A modern load testing tool, using Go and JavaScript.</h3>
<p>I’ve used many load-testing tools in my career, such as <a target="_blank" href="https://github.com/tsenart/vegeta">vegeta</a> or even <a target="_blank" href="https://httpd.apache.org/docs/2.4/programs/ab.html">ab</a> in the past. But now I mostly use <strong>k6s</strong> as it has everything I need and has a great GUI and TUI.</p>
<p>Why it works well for me:</p>
<ul>
<li><p>k6 has really good <a target="_blank" href="https://k6.io/docs/">documentation</a></p>
</li>
<li><p>Many integrations available: Swagger, JMeter scripts, and so on.</p>
</li>
<li><p>Results reporting is quite good</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737552000859/df5af273-3706-4d41-9dbe-717d2f2d18b7.webp" alt="K6 interface" class="image--center mx-auto" width="1698" height="1184" loading="lazy"></p>
<p>To install k6:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install k6

<span class="hljs-comment"># via apt for Debian</span>
sudo apt-get install k6

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install k6
</code></pre>
<h3 id="heading-httpiehttpsgithubcomhttpiecli-modern-user-friendly-command-line-http-client-for-the-api-era"><a target="_blank" href="https://github.com/httpie/cli"><strong>httpie</strong></a> — modern, user-friendly command-line HTTP client for the API era.</h3>
<p>Don’t get me wrong, curl is great, but not very human-friendly.</p>
<p>HTTPie has a simple and expressive syntax, supports JSON and form data, handles authentication and headers, and displays colorized and formatted output.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*Bqi3gBKgIkeEPEI_.gif" alt="0*Bqi3gBKgIkeEPEI_" width="1024" height="512" loading="lazy"></p>
<p>To install httpie:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install httpie

<span class="hljs-comment"># via apt for Debian</span>
sudo apt install httpie

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -Syu httpie

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install httpie
</code></pre>
<h3 id="heading-asciinemahttpsgithubcomasciinemaasciinema-terminal-session-recorder"><a target="_blank" href="https://github.com/asciinema/asciinema"><strong>asciinema</strong></a> — Terminal session recorder.</h3>
<p>I call it a terminal YouTube :)</p>
<p>asciinema is a great tool when you want to share your terminal sessions with someone else, instead of recording heavy videos.</p>
<p>I use it often when I develop some CLI tools and want to share the demo of how they work (on GitHub, for example).</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*Exg2XuZlIPaJJ-iB.png" alt="0*Exg2XuZlIPaJJ-iB" width="700" height="389" loading="lazy"></p>
<p>To install asciinema:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install asciinema

<span class="hljs-comment"># via apt for Debian</span>
sudo apt install asciinema

<span class="hljs-comment"># via pacman for Arch Linux</span>
sudo pacman -S asciinema
</code></pre>
<h2 id="heading-networking"><strong>Networking</strong></h2>
<h3 id="heading-doggohttpsgithubcommr-karandoggo-a-command-line-dns-client"><a target="_blank" href="https://github.com/mr-karan/doggo">doggo</a> — A command-line DNS client.</h3>
<p>It's totally inspired by <strong>dog</strong> which is written in Rust.</p>
<p>In the past I would use <strong>dig</strong> to inspect the DNS, but its output is often verbose and difficult to parse visually.</p>
<p><strong>doggo</strong> addresses these shortcomings by offering two key improvements:</p>
<ul>
<li><p>doggo provides the JSON output support for easy scripting and parsing.</p>
</li>
<li><p>doggo offers a human-readable output format that uses color-coding and a tabular layout to present DNS information clearly and concisely.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737552264803/bb902365-bc0d-4a56-9a87-6b065ee5608a.png" alt="bb902365-bc0d-4a56-9a87-6b065ee5608a" class="image--center mx-auto" width="3680" height="2572" loading="lazy"></p>
<p>To install doggo:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install doggo

<span class="hljs-comment"># via scoop for Windows</span>
scoop install doggo

<span class="hljs-comment"># via go install</span>
go install github.com/mr-karan/doggo/cmd/doggo@latest
</code></pre>
<h3 id="heading-gpinghttpsgithubcomorfgping-ping-but-with-a-graph"><a target="_blank" href="https://github.com/orf/gping"><strong>gping</strong></a> — Ping, but with a graph.</h3>
<p>The well-known <strong>ping</strong> command is not the most interesting to look at, and interpreting its output in a useful way can be difficult.</p>
<p><strong>gping</strong> gives a plot of the ping latency to a host, and the most useful feature is the ability to run concurrent pings to multiple hosts and plot all of them on the same graph.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*IPi1TOpiMnWPN1VU.gif" alt="0*IPi1TOpiMnWPN1VU" width="1411" height="757" loading="lazy"></p>
<p>To install gping:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install gping

<span class="hljs-comment"># via Chocolatey for Windows</span>
choco install gping

<span class="hljs-comment"># via apt for Debian</span>
apt install gping
</code></pre>
<h2 id="heading-workstation"><strong>Workstation</strong></h2>
<h3 id="heading-tmuxhttpsgithubcomtmuxtmuxwiki-a-terminal-multiplexer"><a target="_blank" href="https://github.com/tmux/tmux/wiki"><strong>tmux</strong></a> — A terminal multiplexer.</h3>
<p>Why is tmux such a big deal?</p>
<p>You may have run into situations where you need to view multiple terminal consoles at the same time. For example, you may have a few servers running (for example, web, database, debugger) and you might want to monitor all the output coming from these servers in real-time to validate behavior or run commands.</p>
<p>Before tmux, you might have just opened a few different tabs in the terminal and switched between them to see the output.</p>
<p>Thankfully, there’s an easier way — <strong>tmux</strong>.</p>
<p>In a nutshell, here are some of its most popular features:</p>
<ul>
<li><p>Window/Pane management</p>
</li>
<li><p>Session management with persistence</p>
</li>
<li><p>Sharable sessions with other users</p>
</li>
<li><p>Scriptable configurations</p>
</li>
</ul>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*u8o0WxutrPXxg6FG.png" alt="0*u8o0WxutrPXxg6FG" width="700" height="294" loading="lazy"></p>
<p>To install tmux:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install tmux

<span class="hljs-comment"># via apt for Debian</span>
apt install tmux

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S tmux
</code></pre>
<h3 id="heading-zellijhttpsgithubcomzellij-orgzellij-a-terminal-workspace-with-batteries-included"><a target="_blank" href="https://github.com/zellij-org/zellij"><strong>zellij</strong></a> — A terminal workspace with batteries included.</h3>
<p>Since I listed tmux here, it also makes sense to include a new competitor, <strong>Zellij</strong>, which has been gaining traction in the developer community. Both have their own unique features and purposes.</p>
<p>Compared to traditional terminal multiplexers, zellij offers a more user-friendly interface, modern design elements, built-in layout systems, and a plugin system, making it easier for newcomers to get started.</p>
<p>I still like tmux. It has a special place in my heart because it has served a great purpose for years. But zellij is another good option.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*VwAit4tO1IjxH9dp.gif" alt="0*VwAit4tO1IjxH9dp" width="825" height="435" loading="lazy"></p>
<p>To install zellij:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install zellij

<span class="hljs-comment"># via apt for Debian</span>
apt install zellij

<span class="hljs-comment"># via pacman for Arch Linux</span>
pacman -S zellij
</code></pre>
<h3 id="heading-btophttpsgithubcomaristocratosbtop-a-monitor-of-resources"><a target="_blank" href="https://github.com/aristocratos/btop"><strong>btop</strong></a> — A monitor of resources.</h3>
<p>I can’t live without btop, and it’s installed on all my machines via my personal <a target="_blank" href="https://github.com/plutov/dotfiles">dotfiles</a>. I rarely use now built-in OS GUIs to check the resource utilization on my host machine, because <strong>btop</strong> can do it much better.</p>
<p>I use to to quickly explore what uses the most memory, monitor and kill some processes, and more.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/0*HbuJrCbT6xVApLoh.png" alt="0*HbuJrCbT6xVApLoh" width="700" height="441" loading="lazy"></p>
<p>To install btop:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># via Homebrew for macOS</span>
brew install btop

<span class="hljs-comment"># via snap for Debian</span>
sudo snap install btop
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>These CLIs/TUIs should work well in any modern terminal. I personally use <a target="_blank" href="https://ghostty.org/">Ghostty</a> currently and it works great, but other popular options like <strong>iTerm2, Kitty</strong>, and the default terminal applications on macOS and Linux should also provide a seamless experience. The key is to ensure your terminal supports features like 256-color palettes and UTF-8 encoding for optimal display of these tools.</p>
<p>There’s a huge amount of CLIs/TUIs out there, and I couldn’t list them all (though I tried to list some of the best). This selection represents a starting point for exploring the rich ecosystem of command-line tools available to developers. I encourage you to explore further, discover new tools that fit your specific needs, and contribute back to the community by sharing your findings.</p>
<p><a target="_blank" href="https://packagemain.tech">Explore more articles on packagemain.tech</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Interactive Terminal Portfolio Website ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you will learn how to create an interactive terminal-based portfolio and a résumé in JavaScript. We'll use the jQuery Terminal library (and a few other tools) to create a website that looks like a real terminal. This article will sho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-an-interactive-terminal-portfolio-website/</link>
                <guid isPermaLink="false">66ba5abdf4ac8da2b2c2e865</guid>
                
                    <category>
                        <![CDATA[ portfolio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jakub T. Jankiewicz ]]>
                </dc:creator>
                <pubDate>Mon, 29 Apr 2024 14:49:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730895455049/8fefc48c-761d-4ec5-8f60-b6eb2f97a42a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you will learn how to create an interactive terminal-based portfolio and a résumé in JavaScript. We'll use the <a target="_blank" href="https://terminal.jcubic.pl/">jQuery Terminal library</a> (and a few other tools) to create a website that looks like a real terminal.</p>
<p>This article will show more advanced usage of the jQuery Terminal library. If you want something more basic, you can check this article: <a target="_blank" href="https://itnext.io/how-to-create-interactive-terminal-like-website-888bb0972288">How to create interactive terminal like website with JavaScript</a> that is written for more entry level programmers. You can also read it (or skim it) first before you begin reading this one.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-the-terminal-and-its-history">What is the terminal and its history?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-jquery-terminal">What is jQuery Terminal?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-base-html-file">Base html file</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-initialize-the-terminal">How to Initialize the Terminal</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-welcome-message">Welcome message</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-line-gaps">Line Gaps</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-colors-to-ascii-art">How to Add Colors to ASCII Art</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-terminal-formatting">Terminal Formatting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-lolcat-library">How to Use the Lolcat Library</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-rainbow-ascii-art-greetings">Rainbow ASCII Art Greetings</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-the-greeting-text-white">How to Make the Greeting Text White</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-your-first-command">How to Make Your First Command</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-default-commands">Default Commands</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-help-commands-executable">How to Make Help Commands Executable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-syntax-highlighting">Syntax Highlighting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tab-completion">Tab Completion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-shell-commands">How to Add Shell Commands</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-improve-completion">How to Improve Completion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-typing-animation-command">Typing Animation Command</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-credits-command">Credits Command</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prefilled-commands">Prefilled Commands</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sharing-link-to-terminal-session">Sharing Link to Terminal Session</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-working-terminal-portfolio-demo">Working Terminal Portfolio Demo</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-adding-executables-to-home-directory">Adding Executables to Home Directory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-next">What Next?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-share-what-youve-created">Share what you’ve created</a></p>
</li>
</ul>
<h2 id="heading-what-is-the-terminal-and-its-history">What is the terminal and its history?</h2>
<p>Terminals have a long history. It started as an upgrade from <a target="_blank" href="https://en.wikipedia.org/wiki/Punched_card">punch cards</a>. Computers back in the day used teletypes, which was just a keyboard and a printer. You'd type on the keyboard, and the keystrokes would be sent to the computer (usually mainframe) and the output got printed on a printer.</p>
<p>Later on, the teletypes were replaced with terminals. A terminal was like the dump computer we see today. It was a CRT Monitor with a keyboard. So instead of getting the output on the printer, it would be displayed on the monitor.</p>
<p>Today we still use this type of interface (the Command Line) to talk with computers.</p>
<p>The command line is a terminal emulator and is a big part of Unix systems, like GNU/Linux or MacOS. On Windows, you have PowerShell or cmd.exe file that allows you to type commands and get responses in the form of text. You can also install GNU/Linux system on Windows in the form of WSL. CLI interfaces are used mostly by power users, developers, and system administrators.</p>
<p>If you're new to the command line, you can read this article: <a target="_blank" href="https://www.freecodecamp.org/news/command-line-for-beginners/">Command Line for Beginners – How to Use the Terminal Like a Pro [Full Handbook]</a>.</p>
<h2 id="heading-what-is-jquery-terminal">What is jQuery Terminal?</h2>
<p>jQuery Terminal is a JavaScript library. It's a plugin for the <a target="_blank" href="https://en.wikipedia.org/wiki/JQuery">jQuery library</a>. jQuery Terminal is more like a framework that has jQuery as its dependency. We'll mostly use JavaScript and very little jQuery in this article.</p>
<p>Let's create our terminal-based portfolio using jQuery Terminal.</p>
<h3 id="heading-base-html-file">Base HTML file</h3>
<p>The first thing you need to do is to include jQuery and jQuery Terminal library in your project.</p>
<p>This is a basic HTML file:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/jquery.terminal/css/jquery.terminal.min.css"</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/jquery"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/jquery.terminal/js/jquery.terminal.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"my-terminal.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Then inside the <strong>my-terminal.js</strong> file, we will write our code in JavaScript.</p>
<h3 id="heading-how-to-initialize-the-terminal">How to Initialize the Terminal</h3>
<p>To create a basic terminal, you need to put in this code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commands = {};

<span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands);
</code></pre>
<p>The string <code>'body'</code> indicates the CSS selector where terminal should be created. Here we use <code>'body'</code> so the terminal will be the only thing on the page. But it doesn't have to be full screen. You can create a website where the terminal is only part of the page, like in a window that looks like part of the Operating System.</p>
<p>The first argument to the terminal method is called an interpreter. It's a way to add your commands. An object is the simplest way to create them. See <a target="_blank" href="https://github.com/jcubic/jquery.terminal/wiki/Getting-Started#creating-the-interpreter">creating the interpreter</a> to learn more.</p>
<p>If the terminal font is too small, you can make it a little bit bigger with CSS custom properties (also known as CSS variables):</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
    <span class="hljs-attribute">--size</span>: <span class="hljs-number">1.2</span>;
}
</code></pre>
<h3 id="heading-welcome-message">Welcome Message</h3>
<p>The first thing we need to do is to get rid of the default greeting message and replace it with nice-looking custom <a target="_blank" href="https://en.wikipedia.org/wiki/ASCII_art">ASCII Art</a>. We will use the <a target="_blank" href="https://en.wikipedia.org/wiki/FIGlet">Filget library</a> written in JavaScript to do this.</p>
<p>There are a few Figlet libraries on npm. We will use a package named <a target="_blank" href="https://www.npmjs.com/package/figlet">figlet</a>.</p>
<p>The first thing you should do is pick the right font. Go to <a target="_blank" href="https://patorjk.com/software/taag/">figlet playground</a> and write the text you want for your greeting. We will use "Terminal Portfolio" and click "Test All". It should display your text with all the fonts. Scroll through the list and pick the font you like.</p>
<p>I picked a font "slant" that looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Przechwycenie-obrazu-ekranu_2024-04-26_22-18-26.png" alt="Terminal Portfolio ASCII Art" width="600" height="400" loading="lazy"></p>
<p>You can copy this text and put into a string, but you will have issues like with the backslash that needs to be escaped using quote characters.</p>
<pre><code class="lang-lisp">const greetings = `  ______                    _             __   ____             __  ____      ___     
 /_  __/__  _________ ___  (<span class="hljs-name">_</span>)___  ____ _/ /  / __ \\____  _____/ /_/ __/___  / (<span class="hljs-name">_</span>)___ 
  / / / _ \\/ ___/ __ \`__ \\/ / __ \\/ __ \`/ /  / /_/ / __ \\/ ___/ __/ /_/ __ \\/ / / __ \\
 / / /  __/ /  / / / / / / / / / / /_/ / /  / ____/ /_/ / /  / /_/ __/ /_/ / / / /_/ /
/_/  \\___/_/  /_/ /_/ /_/_/_/ /_/\\__,_/_/  /_/    \\____/_/   \\__/_/  \\____/_/_/\\____/`

const term = $('body').terminal(<span class="hljs-name">commands</span>, {
    greetings
})<span class="hljs-comment">;</span>
</code></pre>
<p><strong>NOTE</strong>: The second argument to the jQuery Terminal is an object with options – we used a single option <code>greetings</code>.</p>
<p>This doesn't look good and it's hard to modify. Also, if you create the greeting by hardcoding a string, it may get distorted on smaller screens. That's why we will use the figlet library in JavaScript.</p>
<p>First, we need to include the figlet library in HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/figlet/lib/figlet.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>To initialize the library in JavaScript, we need to load the fonts:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> font = <span class="hljs-string">'Slant'</span>;

figlet.defaults({ <span class="hljs-attr">fontPath</span>: <span class="hljs-string">'https://unpkg.com/figlet/fonts/'</span> });
figlet.preloadFonts([font], ready);
</code></pre>
<p>This code will load the <code>'Slant'</code> font and call the function <code>ready</code> when the font is loaded.</p>
<p>So we need to write this function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{

}
</code></pre>
<p>Now we can do two things, we can put the initialization of jQuery Terminal inside that function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> term;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term =  $(<span class="hljs-string">'body'</span>).terminal(commands, {
      greetings
   });
}
</code></pre>
<p>With this, we can use the <code>greeting</code> option. But we can also use the <code>echo</code> method to render the greeting, and when initializing the terminal we will put <code>null</code> or <code>false</code> as a <code>greetings</code> to disable the default one:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(greetings);
}
</code></pre>
<p>This will work better because the library will initialize the terminal immediately and will not need to wait for loading the fonts.</p>
<p>Note that we still need to define the greetings using figlet. To do this we can write this function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">render</span>(<span class="hljs-params">text</span>) </span>{
    <span class="hljs-keyword">const</span> cols = term.cols();
    <span class="hljs-keyword">return</span> figlet.textSync(text, {
        <span class="hljs-attr">font</span>: font,
        <span class="hljs-attr">width</span>: cols,
        <span class="hljs-attr">whitespaceBreak</span>: <span class="hljs-literal">true</span>
    });
}
</code></pre>
<p>This function uses the <code>figlet::textSync()</code> method to return a string and use <code>terminal::cols()</code>, to get the number of characters per line. With this, we can make our text responsive.</p>
<p>This function can be used inside <code>ready</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(render(<span class="hljs-string">'Terminal Portfolio'</span>));
}
</code></pre>
<p>This will create a string and pass it to the <code>echo</code> method. But this will be the same as with:</p>
<pre><code class="lang-javascript">term.echo(greeting);
</code></pre>
<p>And our hard-coded greetings. So if you resize the terminal, the greetings can still get distorted. To make the text responsive, you need to <code>echo</code> a function. This function will be called on each re-render of the terminal, which will happen when you resize the page.</p>
<p>We can use the arrow function for this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(<span class="hljs-function">() =&gt;</span> render(<span class="hljs-string">'Terminal Portfolio'</span>));
}
</code></pre>
<p>If you want to add some text below the ASCII art, you can do this by concatenating the string after render:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> ascii = render(<span class="hljs-string">'Terminal Portfolio'</span>);
     <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${ascii}</span>\nWelcome to my Terminal Portfolio\n`</span>;
   });
}
</code></pre>
<p><strong>NOTE</strong>: If you run this code, you will notice that there is an empty line after the ASCII art. This is because the figlet library adds some spaces after the text.</p>
<p>To get rid of this, you can use <code>string::replace()</code> with a regular expression that will remove all spaces and newlines from the end.</p>
<p>We can't use <code>string::trim()</code>, because we don't want to remove the leading lines:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">render</span>(<span class="hljs-params">text</span>) </span>{
    <span class="hljs-keyword">const</span> cols = term.cols();
    <span class="hljs-keyword">return</span> trim(figlet.textSync(text, {
        <span class="hljs-attr">font</span>: font,
        <span class="hljs-attr">width</span>: cols,
        <span class="hljs-attr">whitespaceBreak</span>: <span class="hljs-literal">true</span>
    }));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">trim</span>(<span class="hljs-params">str</span>) </span>{
    <span class="hljs-keyword">return</span> str.replace(<span class="hljs-regexp">/[\n\s]+$/</span>, <span class="hljs-string">''</span>);
}
</code></pre>
<p>You can also pause the terminal when it loads the fonts:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>
});

term.pause();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(<span class="hljs-function">() =&gt;</span> render(<span class="hljs-string">'Terminal Portfolio'</span>)).resume();
}
</code></pre>
<p>You can can chain terminal methods, the same as with jQuery.</p>
<h3 id="heading-line-gaps">Line Gaps</h3>
<p>If the font you pick creates gaps between the lines, like in this image with font ANSI Shadow:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Przechwycenie-obrazu-ekranu_2024-05-08_14-06-41.png" alt="Image: ASCII Art with line gaps" width="600" height="400" loading="lazy"></p>
<p>You can remove the gaps by adding the <code>ansi</code> option set to <code>true</code>. The option was added specifically to fix an issue with displaying <a target="_blank" href="https://en.wikipedia.org/wiki/ANSI_art">ANSI Art</a>.</p>
<pre><code class="lang-javascript">term.echo(<span class="hljs-function">() =&gt;</span> render(<span class="hljs-string">'Terminal Portfolio'</span>), { <span class="hljs-attr">ansi</span>: <span class="hljs-literal">true</span> });
</code></pre>
<p>The above ASCII Art will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Przechwycenie-obrazu-ekranu_2024-05-08_14-57-16.png" alt="Image: ASCII Art with gaps removed" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-colors-to-ascii-art">How to Add Colors to ASCII Art</h2>
<p>You can spice up your ASCII Art by using a library called lolcat. lolcat is a Linux command that can style text in the terminal with rainbow colors. There is also a library called <a target="_blank" href="https://www.npmjs.com/package/isomorphic-lolcat">isomorphic-lolcat</a>, that you can use in JavaScript to make your ASCII Art in rainbow colors.</p>
<h3 id="heading-terminal-formatting">Terminal Formatting</h3>
<p>To use the lolcat library, you first need to know how to change the colors of the terminal.</p>
<p>You can do this using low-level formatting that looks like this:</p>
<pre><code class="lang-lisp">[[b<span class="hljs-comment">;red;]some text]</span>
</code></pre>
<p>The whole text is wrapped in brackets and the formatting of the text is in additional brackets, where each argument is separated by a semicolon. To learn more about the syntax, you can read the Wiki Article: <a target="_blank" href="https://github.com/jcubic/jquery.terminal/wiki/Formatting-and-Syntax-Highlighting">Formatting and Syntax Highlighting</a>.</p>
<p>Here, we'll only use a basic change of color. Instead of red, you can use CSS color names, hex color, or <code>rgb()</code>.</p>
<h3 id="heading-how-to-use-the-lolcat-library">How to Use the Lolcat Library</h3>
<p>To use the library, we first need to include it in HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/isomorphic-lolcat"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>To format the string with colors, we can use this function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rainbow</span>(<span class="hljs-params">string</span>) </span>{
    <span class="hljs-keyword">return</span> lolcat.rainbow(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">char, color</span>) </span>{
        char = $.terminal.escape_brackets(char);
        <span class="hljs-keyword">return</span> <span class="hljs-string">`[[;<span class="hljs-subst">${hex(color)}</span>;]<span class="hljs-subst">${char}</span>]`</span>;
    }, string).join(<span class="hljs-string">'\n'</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hex</span>(<span class="hljs-params">color</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">'#'</span> + [color.red, color.green, color.blue].map(<span class="hljs-function"><span class="hljs-params">n</span> =&gt;</span> {
        <span class="hljs-keyword">return</span> n.toString(<span class="hljs-number">16</span>).padStart(<span class="hljs-number">2</span>, <span class="hljs-string">'0'</span>);
    }).join(<span class="hljs-string">''</span>);
}
</code></pre>
<p>The <code>lolcat.rainbow</code> will call a function in every character from the input string, and pass color as an object with RGB values and the character.</p>
<h3 id="heading-rainbow-ascii-art-greetings">Rainbow ASCII Art Greetings</h3>
<p>To use this code, you need to wrap the call to render with <code>rainbow</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> ascii = rainbow(render(<span class="hljs-string">'Terminal Portfolio'</span>));
     <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${ascii}</span>\nWelcome to my Terminal Portfolio\n`</span>;
   }).resume();
}
</code></pre>
<p>You can also use two calls to echo, since only the Figlet message needs to be executed inside the function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   term.echo(<span class="hljs-function">() =&gt;</span> rainbow(render(<span class="hljs-string">'Terminal Portfolio'</span>)))
       .echo(<span class="hljs-string">'Welcome to my Terminal Portfolio\n'</span>).resume();
}
</code></pre>
<p>You'll notice that when you resize the window, the rainbow changes randomly. This is the default behavior of lolcat. To change it, you need to set the <a target="_blank" href="https://en.wikipedia.org/wiki/Random_seed">random seed</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rand</span>(<span class="hljs-params">max</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * (max + <span class="hljs-number">1</span>));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ready</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> seed = rand(<span class="hljs-number">256</span>);
   term.echo(<span class="hljs-function">() =&gt;</span> rainbow(render(<span class="hljs-string">'Terminal Portfolio'</span>), seed))
       .echo(<span class="hljs-string">'Welcome to my Terminal Portfolio\n'</span>).resume();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rainbow</span>(<span class="hljs-params">string, seed</span>) </span>{
    <span class="hljs-keyword">return</span> lolcat.rainbow(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">char, color</span>) </span>{
        char = $.terminal.escape_brackets(char);
        <span class="hljs-keyword">return</span> <span class="hljs-string">`[[;<span class="hljs-subst">${hex(color)}</span>;]<span class="hljs-subst">${char}</span>]`</span>;
    }, string, seed).join(<span class="hljs-string">'\n'</span>);
}
</code></pre>
<p>The <code>rand</code> function returns a pseudo-random number from 0 to max value. Here we created a random value from 0 to 256.</p>
<h3 id="heading-how-to-make-the-greeting-text-white">How to Make the Greeting Text White</h3>
<p>As we showed previously, you can make the text white with terminal formatting. You can use:</p>
<ul>
<li><p><code>[[;white;]Welcome to my Terminal Portfolio]</code></p>
</li>
<li><p><code>[[;#fff;]Welcome to my Terminal Portfolio]</code></p>
</li>
<li><p><code>[[;rgb(255,255,255);]Welcome to my Terminal Portfolio]</code></p>
</li>
</ul>
<p>Moreover, if you include additional file XML formatting, you can use XML-like syntax. That makes formatting much easier.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/jquery.terminal/js/xml_formatting.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>After including the above file in HTML, you can use CSS named colors as XML tags:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">white</span>&gt;</span>Welcome to my Terminal Portfolio<span class="hljs-tag">&lt;/<span class="hljs-name">white</span>&gt;</span>
</code></pre>
<p>The XML formatting supports more tags like links and images. See <a target="_blank" href="https://github.com/jcubic/jquery.terminal/wiki/Formatting-and-Syntax-Highlighting#extension-xml-formatter">Extension XML Formatter</a> for more info.</p>
<p><strong>NOTE</strong>: XML formatter is a function added to <code>$.terminal.defaults.formatters</code>, which transforms the input XML-like text into terminal formatting. You can add the same to your own formatters.</p>
<h2 id="heading-how-to-make-your-first-command">How to Make Your First Command</h2>
<p>After the greeting, we can write our first command. It will be helpful and will work with any commands we add later.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commanns = {
    help() {

    }
};
</code></pre>
<p>This will be our help command where we'll add a list of commands available to our terminal portfolio. We will use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat">Intl.ListFormat</a>, which creates a list of elements with and before the last element.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> formatter = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.ListFormat(<span class="hljs-string">'en'</span>, {
  <span class="hljs-attr">style</span>: <span class="hljs-string">'long'</span>,
  <span class="hljs-attr">type</span>: <span class="hljs-string">'conjunction'</span>,
});
</code></pre>
<p>To create a list, we need to use <code>formatter.format()</code> and pass an array of commands. To get that array we can use <code>Object.keys()</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commands = {
    help() {
        term.echo(<span class="hljs-string">`List of available commands: <span class="hljs-subst">${help}</span>`</span>);
    }
};

<span class="hljs-keyword">const</span> command_list = <span class="hljs-built_in">Object</span>.keys(commands);
<span class="hljs-keyword">const</span> help = formatter.format(command_list);
</code></pre>
<p>When you type help you should see:</p>
<pre><code class="lang-lisp">List of available commands: help
</code></pre>
<p>You also need to add the <code>echo</code> command:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commands = {
    help() {
        term.echo(<span class="hljs-string">`List of available commands: <span class="hljs-subst">${help}</span>`</span>);
    },
    echo(...args) {
        term.echo(args.join(<span class="hljs-string">' '</span>));
    }
};
</code></pre>
<p>Now the help command works:</p>
<pre><code class="lang-lisp">List of available commands: help and echo
</code></pre>
<p>But if you try to execute 'echo hello' you will get an error:</p>
<pre><code class="lang-lisp">[Arity] Wrong number of arguments. The function 'echo' expects <span class="hljs-number">0</span> got <span class="hljs-number">1</span>!
</code></pre>
<p>By default, jQuery Terminal checks the number of arguments and the number of parameters the function accepts. The problem is that the <code>rest</code> operator makes all arguments optional and the length function property is 0. To fix the issue we need to disable the <code>Arity</code> check with an option:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">checkArity</span>: <span class="hljs-literal">false</span>
});
</code></pre>
<p>Now the echo commands should work.</p>
<h2 id="heading-default-commands">Default Commands</h2>
<p>By default, the jQuery Terminal has two default commands:</p>
<ul>
<li><p><code>clear</code>: this command clears everything on the terminal.</p>
</li>
<li><p><code>exit</code>: this command exits from nested interpreters.</p>
</li>
</ul>
<p>You can disable them by passing the name to the option and setting it to false. Since we won't use nested interpreters, we can disable <code>exit</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">checkArity</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">exit</span>: <span class="hljs-literal">false</span>
});
</code></pre>
<p>But <code>clear</code> can be useful. So we can add it to the list of commands:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> command_list = [<span class="hljs-string">'clear'</span>].concat(<span class="hljs-built_in">Object</span>.keys(commands));
</code></pre>
<h2 id="heading-how-to-make-help-commands-executable">How to Make Help Commands Executable</h2>
<p>We can make the UX better to allow clicking on the command and execute it just like when the user types it.</p>
<p>We will need a few things to do this. First, we need to add formatting to each command and add an HTML class attribute. We can also make the command white so it's more visible.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> command_list = <span class="hljs-built_in">Object</span>.keys(commands);
<span class="hljs-keyword">const</span> formatted_list = command_list.map(<span class="hljs-function"><span class="hljs-params">cmd</span> =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;white class="command"&gt;<span class="hljs-subst">${cmd}</span>&lt;/white&gt;`</span>;
});
<span class="hljs-keyword">const</span> help = formatter.format(formatted_list);
</code></pre>
<p>Next is to add <a target="_blank" href="https://en.wikipedia.org/wiki/Affordance">affordance</a>. To indicate that the user can click the command, we need to change the cursor in CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.command</span> {
    <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>The last step is to execute the command when the user clicks the command. We need to add an event handler with jQuery (jQuery Terminal dependency) or we can use the native browser <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener">addEventListener</a>. Here we use jQuery:</p>
<pre><code class="lang-javascript">term.on(<span class="hljs-string">'click'</span>, <span class="hljs-string">'.command'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> command = $(<span class="hljs-built_in">this</span>).text();
   term.exec(command);
});
</code></pre>
<p><code>terminal::exec()</code> is a way to execute a command programmatically, just like user would type it and press enter.</p>
<p>You can test it by typing <code>help</code> and clicking <code>help</code> again.</p>
<p>Clicking <code>echo</code> will print an empty line. We can fix it by checking if the array of arguments is not empty, before executing <code>terminal::echo()</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commands = {
    echo(...args) {
        <span class="hljs-keyword">if</span> (args.length &gt; <span class="hljs-number">0</span>) {
            term.echo(args.join(<span class="hljs-string">' '</span>));
        }
    }
};
</code></pre>
<p>Now clicking on <code>echo</code> will only show the executed command.</p>
<p><strong>NOTE</strong>: If for any reason you don't want to show the prompt and the command that has been executed, you can silence the <code>exec</code> by passing <code>true</code> as the second argument.</p>
<pre><code class="lang-javascript">term.exec(<span class="hljs-string">'help'</span>, <span class="hljs-literal">true</span>);
</code></pre>
<h2 id="heading-syntax-highlighting">Syntax Highlighting</h2>
<p>As we discussed earlier, we can use custom syntax highlighting of our shell by pushing a function into <code>$.terminal.defaults.formatters</code>.We can also use the <code>$.terminal.new_formatter</code> helper function.</p>
<p>Let's make our commands white as we type them. The formatter can be an array (of regex and replacement), or a function. We have a fixed number of commands and we only want to make those that are on the list white. We can do this by adding a regular expression:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> any_command_re = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">`^\s*(<span class="hljs-subst">${command_list.join(<span class="hljs-string">'|'</span>)}</span>)`</span>);
</code></pre>
<p>This regular expression will check if, at the beginning of the string, there is an optional whitespace and one of the commands. Right now the regex will look like this: <code>/^\s*(help|echo)/</code>. This is how to create new formatter:</p>
<pre><code class="lang-javascript">$.terminal.new_formatter([any_command_re, <span class="hljs-string">'&lt;white&gt;$1&lt;/white&gt;'</span>]);
</code></pre>
<p>If you would like to make command arguments in different colors, you'll need a function, where you will use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">String::replace()</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> re = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">`^\s*(<span class="hljs-subst">${command_list.join(<span class="hljs-string">'|'</span>)}</span>) (.*)`</span>);

$.terminal.new_formatter(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">string</span>) </span>{
    <span class="hljs-keyword">return</span> string.replace(re, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_, command, args</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;white&gt;<span class="hljs-subst">${command}</span>&lt;/white&gt; &lt;aqua&gt;<span class="hljs-subst">${args}</span>&lt;/aqua&gt;`</span>;
    });
});
</code></pre>
<p>This is just an example of using <code>String::replace</code>. If you have just one replacement, you can use an array. This will be the same:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> re = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">`^\s*(<span class="hljs-subst">${command_list.join(<span class="hljs-string">'|'</span>)}</span>)(\s?.*)`</span>);

$.terminal.new_formatter([re, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_, command, args</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;white&gt;<span class="hljs-subst">${command}</span>&lt;/white&gt;&lt;aqua&gt;<span class="hljs-subst">${args}</span>&lt;/aqua&gt;`</span>;
}]);
</code></pre>
<p><strong>NOTE</strong>: If you add the class <code>&lt;white class="command"&gt;</code> to the formatter, you will be able to click on the typed command to execute it again.</p>
<h2 id="heading-tab-completion">Tab Completion</h2>
<p>Another feature we can add is to complete the command when you press the tab key. This is super easy – we only need to add the completion option set to true:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">checkArity</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">exit</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">completion</span>: <span class="hljs-literal">true</span>
});
</code></pre>
<p>Now when you type <code>h</code> and press tab, it will complete the command <code>help</code> for you.</p>
<h2 id="heading-how-to-add-shell-commands">How to Add Shell Commands</h2>
<p>Now we can add the most important commands that allow us to navigate through the portfolio. We will implement directories as the main entry point so the user will need to type the <code>ls</code> command to see a list of things, <code>cd</code> into that directory, and <code>ls</code> again to see the contents.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> directories = {
    <span class="hljs-attr">education</span>: [
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'&lt;white&gt;education&lt;/white&gt;'</span>,

        <span class="hljs-string">'* &lt;a href="https://en.wikipedia.org/wiki/Kielce_University_of_Technology"&gt;Kielce University of Technology&lt;/a&gt; &lt;yellow&gt;"Computer Science"&lt;/yellow&gt; 2002-2007 / 2011-2014'</span>,
        <span class="hljs-string">'* &lt;a href="https://pl.wikipedia.org/wiki/Szko%C5%82a_policealna"&gt;Post-secondary&lt;/a&gt; Electronic School &lt;yellow&gt;"Computer Systems"&lt;/yellow&gt; 2000-2002'</span>,
        <span class="hljs-string">'* Electronic &lt;a href="https://en.wikipedia.org/wiki/Technikum_(Polish_education)"&gt;Technikum&lt;/a&gt; with major &lt;yellow&gt;"RTV"&lt;/yellow&gt; 1995-2000'</span>,
        <span class="hljs-string">''</span>
    ],
    <span class="hljs-attr">projects</span>: [
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'&lt;white&gt;Open Source projects&lt;/white&gt;'</span>,
        [
            [<span class="hljs-string">'jQuery Terminal'</span>,
             <span class="hljs-string">'https://terminal.jcubic.pl'</span>,
             <span class="hljs-string">'library that adds terminal interface to websites'</span>
            ],
            [<span class="hljs-string">'LIPS Scheme'</span>,
             <span class="hljs-string">'https://lips.js.org'</span>,
             <span class="hljs-string">'Scheme implementation in JavaScript'</span>
            ],
            [<span class="hljs-string">'Sysend.js'</span>,
             <span class="hljs-string">'https://jcu.bi/sysend'</span>,
             <span class="hljs-string">'Communication between open tabs'</span>
            ],
            [<span class="hljs-string">'Wayne'</span>,
             <span class="hljs-string">'https://jcu.bi/wayne'</span>,
             <span class="hljs-string">'Pure in browser HTTP requests'</span>
            ],
        ].map(<span class="hljs-function">(<span class="hljs-params">[name, url, description = <span class="hljs-string">''</span>]</span>) =&gt;</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-string">`* &lt;a href="<span class="hljs-subst">${url}</span>"&gt;<span class="hljs-subst">${name}</span>&lt;/a&gt; &amp;mdash; &lt;white&gt;<span class="hljs-subst">${description}</span>&lt;/white&gt;`</span>;
        }),
        <span class="hljs-string">''</span>
    ].flat(),
    <span class="hljs-attr">skills</span>: [
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'&lt;white&gt;languages&lt;/white&gt;'</span>,

        [
            <span class="hljs-string">'JavaScript'</span>,
            <span class="hljs-string">'TypeScript'</span>,
            <span class="hljs-string">'Python'</span>,
            <span class="hljs-string">'SQL'</span>,
            <span class="hljs-string">'PHP'</span>,
            <span class="hljs-string">'Bash'</span>
        ].map(<span class="hljs-function"><span class="hljs-params">lang</span> =&gt;</span> <span class="hljs-string">`* &lt;yellow&gt;<span class="hljs-subst">${lang}</span>&lt;/yellow&gt;`</span>),
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'&lt;white&gt;libraries&lt;/white&gt;'</span>,
        [
            <span class="hljs-string">'React.js'</span>,
            <span class="hljs-string">'Redux'</span>,
            <span class="hljs-string">'Jest'</span>,
        ].map(<span class="hljs-function"><span class="hljs-params">lib</span> =&gt;</span> <span class="hljs-string">`* &lt;green&gt;<span class="hljs-subst">${lib}</span>&lt;/green&gt;`</span>),
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'&lt;white&gt;tools&lt;/white&gt;'</span>,
        [
            <span class="hljs-string">'Docker'</span>,
            <span class="hljs-string">'git'</span>,
            <span class="hljs-string">'GNU/Linux'</span>
        ].map(<span class="hljs-function"><span class="hljs-params">lib</span> =&gt;</span> <span class="hljs-string">`* &lt;blue&gt;<span class="hljs-subst">${lib}</span>&lt;/blue&gt;`</span>),
        <span class="hljs-string">''</span>
    ].flat()
};
</code></pre>
<p>This is our basic structure. You can edit it and add your own information. First, we will add a <code>cd</code> command that changes the directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> root = <span class="hljs-string">'~'</span>;
<span class="hljs-keyword">let</span> cwd = root;

<span class="hljs-keyword">const</span> commands = {
    cd(dir = <span class="hljs-literal">null</span>) {
        <span class="hljs-keyword">if</span> (dir === <span class="hljs-literal">null</span> || (dir === <span class="hljs-string">'..'</span> &amp;&amp; cwd !== root)) {
            cwd = root;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dir.startsWith(<span class="hljs-string">'~/'</span>) &amp;&amp; dirs.includes(dir.substring(<span class="hljs-number">2</span>))) {
            cwd = dir;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dir.startsWith(<span class="hljs-string">'../'</span>) &amp;&amp; cwd !== root &amp;&amp;
                   dirs.includes(dir.substring(<span class="hljs-number">3</span>))) {
            cwd = root + <span class="hljs-string">'/'</span> + dir.substring(<span class="hljs-number">3</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dirs.includes(dir)) {
            cwd = root + <span class="hljs-string">'/'</span> + dir;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">this</span>.error(<span class="hljs-string">'Wrong directory'</span>);
        }
    }
};
</code></pre>
<p>This will handle all the cases of changing the directory. Next is to add a prompt.</p>
<p>To see what directory we are in, we need to add a custom <code>prompt</code>. We can create a function as a <code>prompt</code> option:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> user = <span class="hljs-string">'guest'</span>;
<span class="hljs-keyword">const</span> server = <span class="hljs-string">'freecodecamp.org'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">prompt</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;green&gt;<span class="hljs-subst">${user}</span>@<span class="hljs-subst">${server}</span>&lt;/green&gt;:&lt;blue&gt;<span class="hljs-subst">${cwd}</span>&lt;/blue&gt;$ `</span>;
}
</code></pre>
<p>And use it as an option:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">checkArity</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">completion</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">exit</span>: <span class="hljs-literal">false</span>,
    prompt
});
</code></pre>
<p>The green color don't look very good, so we can use a color from Ubuntu to make the terminal look more real. We can overwrite the default XML color tags like this:</p>
<pre><code class="lang-javascript">$.terminal.xml_formatter.tags.green = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`[[;#44D544;]`</span>;
};
</code></pre>
<p>Next is the <code>ls</code> command.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">print_home</span>(<span class="hljs-params"></span>) </span>{
     term.echo(dirs.map(<span class="hljs-function"><span class="hljs-params">dir</span> =&gt;</span> {
         <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;blue class="directory"&gt;<span class="hljs-subst">${dir}</span>&lt;/blue&gt;`</span>;
     }).join(<span class="hljs-string">'\n'</span>));
}

<span class="hljs-keyword">const</span> commands = {
    ls(dir = <span class="hljs-literal">null</span>) {
        <span class="hljs-keyword">if</span> (dir) {
            <span class="hljs-keyword">if</span> (dir.match(<span class="hljs-regexp">/^~\/?$/</span>)) {
                <span class="hljs-comment">// ls ~ or ls ~/</span>
                print_home();
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dir.startsWith(<span class="hljs-string">'~/'</span>)) {
                <span class="hljs-keyword">const</span> path = dir.substring(<span class="hljs-number">2</span>);
                <span class="hljs-keyword">const</span> dirs = path.split(<span class="hljs-string">'/'</span>);
                <span class="hljs-keyword">if</span> (dirs.length &gt; <span class="hljs-number">1</span>) {
                    <span class="hljs-built_in">this</span>.error(<span class="hljs-string">'Invalid directory'</span>);
                } <span class="hljs-keyword">else</span> {
                    <span class="hljs-keyword">const</span> dir = dirs[<span class="hljs-number">0</span>];
                    <span class="hljs-built_in">this</span>.echo(directories[dir].join(<span class="hljs-string">'\n'</span>));
                }
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cwd === root) {
                <span class="hljs-keyword">if</span> (dir <span class="hljs-keyword">in</span> directories) {
                    <span class="hljs-built_in">this</span>.echo(directories[dir].join(<span class="hljs-string">'\n'</span>));
                } <span class="hljs-keyword">else</span> {
                    <span class="hljs-built_in">this</span>.error(<span class="hljs-string">'Invalid directory'</span>);
                }
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dir === <span class="hljs-string">'..'</span>) {
                print_home();
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-built_in">this</span>.error(<span class="hljs-string">'Invalid directory'</span>);
            }
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cwd === root) {
            print_home();
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">const</span> dir = cwd.substring(<span class="hljs-number">2</span>);
            <span class="hljs-built_in">this</span>.echo(directories[dir].join(<span class="hljs-string">'\n'</span>));
        }
    }
};
</code></pre>
<p>Similar to the green we had before, the blue color is not that great. So we can use the color from Ubuntu again. To do this, we need to use the same custom XML tags for the color blue:</p>
<pre><code class="lang-javascript">$.terminal.xml_formatter.tags.blue = <span class="hljs-function">(<span class="hljs-params">attrs</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`[[;#55F;;<span class="hljs-subst">${attrs.<span class="hljs-keyword">class</span>}</span>]`</span>;
};
</code></pre>
<p>We added the HTML class for a reason. Let's change directory when the user clicks the directory. Just like we did with commands, we can invoke the <code>cd</code> command the same way as as a user would type it.</p>
<pre><code class="lang-javascript">term.on(<span class="hljs-string">'click'</span>, <span class="hljs-string">'.directory'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> dir = $(<span class="hljs-built_in">this</span>).text();
    term.exec(<span class="hljs-string">`cd ~/<span class="hljs-subst">${dir}</span>`</span>);
});
</code></pre>
<p><strong>NOTE</strong>: if you have long command and want to get the text for that command, it's better to use: <code>$(this).data('text')</code>. When the single formatting is wrapped (when text is longer than the width of the terminal) the <code>.text()</code> will no longer have full text, but the full text is always in the <code>data-text</code> HTML attribute.</p>
<p>We also need to update our CSS to change the cursor:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.command</span>, <span class="hljs-selector-class">.directory</span> {
    <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<h2 id="heading-how-to-improve-completion">How to Improve Completion</h2>
<p>Our completion is not perfect as it only completes the commands. If you'd like to have completion that also handles directories, you need to use a function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-attr">greetings</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">checkArity</span>: <span class="hljs-literal">false</span>,
    completion(string) {
        <span class="hljs-comment">// in every function we can use `this` to reference term object</span>
        <span class="hljs-keyword">const</span> cmd = <span class="hljs-built_in">this</span>.get_command();
        <span class="hljs-comment">// we process the command to extract the command name</span>
        <span class="hljs-comment">// and the rest of the command (the arguments as one string)</span>
        <span class="hljs-keyword">const</span> { name, rest } = $.terminal.parse_command(cmd);
        <span class="hljs-keyword">if</span> ([<span class="hljs-string">'cd'</span>, <span class="hljs-string">'ls'</span>].includes(name)) {
            <span class="hljs-keyword">if</span> (rest.startsWith(<span class="hljs-string">'~/'</span>)) {
                <span class="hljs-keyword">return</span> dirs.map(<span class="hljs-function"><span class="hljs-params">dir</span> =&gt;</span> <span class="hljs-string">`~/<span class="hljs-subst">${dir}</span>`</span>);
            }
            <span class="hljs-keyword">if</span> (rest.startsWith(<span class="hljs-string">'../'</span>) &amp;&amp; cwd != root) {
                <span class="hljs-keyword">return</span> dirs.map(<span class="hljs-function"><span class="hljs-params">dir</span> =&gt;</span> <span class="hljs-string">`../<span class="hljs-subst">${dir}</span>`</span>);
            }
            <span class="hljs-keyword">if</span> (cwd === root) {
                <span class="hljs-keyword">return</span> dirs;
            }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(commands);
    },
    prompt
});
</code></pre>
<p><strong>NOTE</strong>: The string argument was left as documentation. It can be used if you only want to complete a single word.</p>
<h2 id="heading-typing-animation-command">Typing Animation Command</h2>
<p>Another command that we will add is an animated joke. We will print random jokes using an API that looks like the user typing.</p>
<p>We will use the <a target="_blank" href="https://jokeapi.dev/">Joke API</a> for this purpose.</p>
<p>The API returns JSON with two types of responses: <code>twopart</code> and a <code>single</code>. This is the code that prints the text on the terminal:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// we use programming jokes so it fit better</span>
<span class="hljs-comment">// developer portfolio</span>
<span class="hljs-keyword">const</span> url = <span class="hljs-string">'https://v2.jokeapi.dev/joke/Programming'</span>;
<span class="hljs-keyword">const</span> commands = {
    <span class="hljs-keyword">async</span> joke() {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(url);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">if</span> (data.type == <span class="hljs-string">'twopart'</span>) {
            <span class="hljs-comment">// as said before in every function, passed directly</span>
            <span class="hljs-comment">// to the terminal, you can use `this` object</span>
            <span class="hljs-comment">// to reference terminal instance</span>
            <span class="hljs-built_in">this</span>.echo(<span class="hljs-string">`Q: <span class="hljs-subst">${data.setup}</span>`</span>);
            <span class="hljs-built_in">this</span>.echo(<span class="hljs-string">`A: <span class="hljs-subst">${data.delivery}</span>`</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (data.type === <span class="hljs-string">'single'</span>) {
            <span class="hljs-built_in">this</span>.echo(data.joke);
        }
    },
}
</code></pre>
<p>To add typing animation, you need to add an option to the <code>echo</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">this</span>.echo(data.joke, { <span class="hljs-attr">delay</span>: <span class="hljs-number">50</span>, <span class="hljs-attr">typing</span>: <span class="hljs-literal">true</span> });
</code></pre>
<p>There is one caveat: if you have a sequence of typing animations, you need to await for the previous one to finish (the echo will return a promise when animating). When creating such animation you can wrap your code with <code>animation</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// we use programming jokes so it fits better</span>
<span class="hljs-comment">// developer portfolio</span>
<span class="hljs-keyword">const</span> url = <span class="hljs-string">'https://v2.jokeapi.dev/joke/Programming'</span>;
<span class="hljs-keyword">const</span> commands = {
    <span class="hljs-keyword">async</span> joke() {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(url);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">if</span> (data.type == <span class="hljs-string">'twopart'</span>) {
            <span class="hljs-comment">// this method allow to create sequence of animations</span>
            <span class="hljs-built_in">this</span>.animation(<span class="hljs-keyword">async</span> () =&gt; {
                <span class="hljs-comment">// as said before in every function, passed </span>
                <span class="hljs-comment">// directly to terminal, you can use `this` object</span>
                <span class="hljs-comment">// to reference terminal instance</span>
                <span class="hljs-comment">// and since we use arrow function we reference</span>
                <span class="hljs-comment">// this from joke function/command</span>
                <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.echo(<span class="hljs-string">`Q: <span class="hljs-subst">${data.setup}</span>`</span>, {
                    <span class="hljs-attr">delay</span>: <span class="hljs-number">50</span>,
                    <span class="hljs-attr">typing</span>: <span class="hljs-literal">true</span>
                });
                <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.echo(<span class="hljs-string">`A: <span class="hljs-subst">${data.delivery}</span>`</span>, {
                    <span class="hljs-attr">delay</span>: <span class="hljs-number">50</span>,
                    <span class="hljs-attr">typing</span>: <span class="hljs-literal">true</span>
                });
            });
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (data.type === <span class="hljs-string">'single'</span>) {
            <span class="hljs-built_in">this</span>.echo(data.joke, {
                <span class="hljs-attr">delay</span>: <span class="hljs-number">50</span>,
                <span class="hljs-attr">typing</span>: <span class="hljs-literal">true</span>
            });
        }
    }
};
</code></pre>
<p>You can read more about typing animation in this article: <a target="_blank" href="https://github.com/jcubic/jquery.terminal/wiki/Typing-Animation">Typing Animation</a><a target="_blank" href="https://github.com/jcubic/jquery.terminal/wiki/Typing-Animation#sequence-of-animations">.</a></p>
<h2 id="heading-credits-command">Credits Command</h2>
<p>The last command we will add is a credits command where we will list the JavaScript libraries we used:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> commands = {
    credits() {
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">''</span>,
            <span class="hljs-string">'&lt;white&gt;Used libraries:&lt;/white&gt;'</span>,
            <span class="hljs-string">'* &lt;a href="https://terminal.jcubic.pl"&gt;jQuery Terminal&lt;/a&gt;'</span>,
            <span class="hljs-string">'* &lt;a href="https://github.com/patorjk/figlet.js/"&gt;Figlet.js&lt;/a&gt;'</span>,
            <span class="hljs-string">'* &lt;a href="https://github.com/jcubic/isomorphic-lolcat"&gt;Isomorphic Lolcat&lt;/a&gt;'</span>,
            <span class="hljs-string">'* &lt;a href="https://jokeapi.dev/"&gt;Joke API&lt;/a&gt;'</span>,
            <span class="hljs-string">''</span>
        ].join(<span class="hljs-string">'\n'</span>);
    }
};
</code></pre>
<p>This is an example of another way to print something on the terminal – if you return something from a function it will be printed. You can also return a <a target="_blank" href="https://www.freecodecamp.org/news/javascript-promises-explained/">Promise</a>, so you can send an <a target="_blank" href="https://en.wikipedia.org/wiki/Ajax_\(programming\)">AJAX</a> request to the server and print the results.</p>
<h2 id="heading-prefilled-commands">Prefilled Commands</h2>
<p>You can make it easier for users to know what to do with the terminal, especially if they are not that familiar with Unix. You can do this by executing example commands:</p>
<pre><code class="lang-javascript">term.exec(command)
</code></pre>
<p>You can also use animation with <code>exec</code>:</p>
<pre><code class="lang-javascript">term.exec(command, { <span class="hljs-attr">typing</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">delay</span>: <span class="hljs-number">50</span> });
</code></pre>
<h2 id="heading-sharing-link-to-terminal-session">Sharing Link to Terminal Session</h2>
<p>Another cool thing that I will show you is recording commands in the URL. You can create whole terminal session and save it in a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/URL/hash">URL hash</a>. To start recoding a session you need to execute the following:</p>
<pre><code class="lang-javascript">term.history_state(<span class="hljs-literal">true</span>);
</code></pre>
<p>When you execute the command <code>echo x</code>, it should create a URL hash that looks like this: <code>#[[0,1,"echo%20x"]]</code>.</p>
<p>To stop recording, you can use:</p>
<pre><code class="lang-javascript">term.history_state(<span class="hljs-literal">false</span>);
</code></pre>
<p>You can write this into a command <code>record start | stop</code>, so it will be easier to record sessions.</p>
<p>The last thing to do to restore the session is to use the option <code>execHash: true</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-comment">/* rest of the options */</span>
    <span class="hljs-attr">execHash</span>: <span class="hljs-literal">true</span>
});
</code></pre>
<p>When you do this and refresh the page, while having the URL hash with the session, it should replay the session and you should see same output as you did when you recorded it.</p>
<p>If you want the <code>exec</code> to be animated you can use this option:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> term = $(<span class="hljs-string">'body'</span>).terminal(commands, {
    <span class="hljs-comment">/* rest of the options */</span>
    <span class="hljs-attr">execHash</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">execAnimation</span>: <span class="hljs-literal">true</span>
});
</code></pre>
<p>To share the link, it’s better to use a URL shortener like <a target="_blank" href="https://tinyurl.com/"><strong>TinyURL</strong></a><strong>.</strong> Make sure you test the shortened URL to see if it works.</p>
<h2 id="heading-how-to-add-executables-to-the-home-directory">How to Add Executables to the Home Directory</h2>
<p>Another thing you can do to improve the portfolio is to help your visitor learn what commands they can use, by introducing executable when running ls. They will look like binaries on the Linux system.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// not every command needs to be binary</span>
<span class="hljs-comment">// we picked those three that works more like real programs</span>
<span class="hljs-keyword">const</span> files = [
    <span class="hljs-string">'joke'</span>,
    <span class="hljs-string">'credits'</span>,
    <span class="hljs-string">'record'</span>
];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">print_home</span>(<span class="hljs-params"></span>) </span>{
     term.echo(dirs.map(<span class="hljs-function"><span class="hljs-params">dir</span> =&gt;</span> {
         <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;blue class="directory"&gt;<span class="hljs-subst">${dir}</span>&lt;/blue&gt;`</span>;
     }).join(<span class="hljs-string">'\n'</span>));
     term.echo(files.map(<span class="hljs-function"><span class="hljs-params">file</span> =&gt;</span> {
         <span class="hljs-keyword">return</span> <span class="hljs-string">`&lt;green class="command"&gt;<span class="hljs-subst">${file}</span>&lt;/green&gt;`</span>;
     }).join(<span class="hljs-string">'\n'</span>));
}
</code></pre>
<p>With this, you will be able to click the command and execute it. So your visitors will know that they can run <code>joke</code> command without the need to type <code>help</code> command. For this to work, we need one last change, adding class to the green XML tag:</p>
<pre><code class="lang-javascript">$.terminal.xml_formatter.tags.green = <span class="hljs-function">(<span class="hljs-params">attrs</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`[[;#44D544;;<span class="hljs-subst">${attrs.<span class="hljs-keyword">class</span>}</span>]`</span>;
};
</code></pre>
<h2 id="heading-working-terminal-portfolio-demo">Working Terminal Portfolio Demo</h2>
<p>Here is a fully working Demo of our <a target="_blank" href="https://codepen.io/jcubic/full/ZEZPWRY">Interactive Terminal Portfolio Website</a>.</p>
<h2 id="heading-what-next">What Next?</h2>
<p>You can add a lot of commands to this portfolio. The only limitation is your imagination.</p>
<p>You can check these examples for inspiration:</p>
<ul>
<li><p>CodePen Collection with <a target="_blank" href="https://codepen.io/collection/LPjoaW">jQuery Terminal Demos</a>.</p>
</li>
<li><p><a target="_blank" href="https://codepen.io/jcubic/pen/BwBYOZ">Retro (Vintage) Terminal CodePen Demo</a>.</p>
</li>
<li><p><a target="_blank" href="https://terminal.jcubic.pl/examples.php">jQuery Terminal Examples Page</a>.</p>
</li>
<li><p><a target="_blank" href="https://terminal.jcubic.pl/404">Terminal 404 Error Page</a>.</p>
</li>
<li><p><a target="_blank" href="https://fake.terminal.jcubic.pl/">Fake GNU/Linux Terminal</a>.</p>
</li>
</ul>
<p>If you have an idea that is not listed here, you can ask on <a target="_blank" href="https://stackoverflow.com/questions/tagged/jquery-terminal">StackOverflow with jquery-terminal tag</a>. If you have something more time consuming, you can also ask for <a target="_blank" href="https://support.jcubic.pl/">paid support</a>.</p>
<h2 id="heading-share-what-youve-created">Share what you’ve created</h2>
<p>If you create a cool terminal portfolio, you can <a target="_blank" href="http://twitter.com/jcubic">share it and tag me on Twitter</a>. I would love to take a look. Especially if you create something more than what’s included in the tutorial. You can also share on a <a target="_blank" href="https://jcu.bi/chat">terminal chat on my website</a> (it’s a similar terminal portfolio, but with chat).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Piping and Redirection in the Linux Terminal ]]>
                </title>
                <description>
                    <![CDATA[ The command line interface in Linux provides a powerful way of perfoming a range of tasks on your system. Because of its roots, Linux has many features baked into the terminal. Two of these powerful features are piping and redirection. These features... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/linux-terminal-piping-and-redirection-guide/</link>
                <guid isPermaLink="false">66c4c469bd556981b1bdc44b</guid>
                
                    <category>
                        <![CDATA[ Bash ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alvin ]]>
                </dc:creator>
                <pubDate>Fri, 26 Apr 2024 23:15:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/piping-redirection-linux.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The command line interface in Linux provides a powerful way of perfoming a range of tasks on your system. Because of its roots, Linux has many features baked into the terminal.</p>
<p>Two of these powerful features are piping and redirection. These features enable you to redirect the output and input of commands to and from other commands and files.</p>
<p>In this article, you'll learn what piping and redirection in Linux mean, followed by a deep dive into how to use these features yourself.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To fully understand this guide, you'll need to at least have:</p>
<ul>
<li>Basic <a target="_blank" href="https://www.freecodecamp.org/news/learn-the-basics-of-the-linux-operating-system">understanding of the Linux operating system</a>.</li>
<li>Basic experience working with the Linux command line. </li>
<li>Access to a Linux command line to try out the commands.</li>
</ul>
<p>Take a look at this <a target="_blank" href="https://www.freecodecamp.org/news/linux-command-line-tutorial/">Linux command line tutorial</a> if you're new or need a refresher. </p>
<h2 id="heading-what-is-piping-in-linux">What is Piping in Linux?</h2>
<p>Before we dive into the how, what does piping even mean? Piping is the act of directing the output of one Linux command as an input to another command. You can direct the standard output or standard error from one command to another using piping.</p>
<p>A simple example of piping is when you take the output of one command and use it as an input to another command. The pipe (|) metacharacter is used to achieve this.</p>
<p>If you're new to the concept of metacharacters, this is just a fancy name for characters with special meaning in the command line. There are other metacharacters in Linux aside from pipe (|). Common examples include less than (&lt;), greater than (&gt;), and ampersand (&amp;), to name a few.</p>
<h3 id="heading-the-basics-of-piping">The Basics of Piping</h3>
<p>The basic syntax of using the <code>pipe</code> command is as follows:</p>
<pre><code>command1 | command2 | command3 | ... | commandN
</code></pre><p>In the syntax above, the terminal will execute the commands from left to right. It will start with <code>command1</code>, and then the output will be input to <code>command2</code>. Outputs of <code>command2</code> will then be used as inputs of <code>command3</code> and so on. The good thing about piping is that you can chain as many commands as you'd like.</p>
<h3 id="heading-piping-examples">Piping Examples</h3>
<p>Below are several examples of using the <code>pipe</code> command to perform various tasks.</p>
<h4 id="heading-1-counting-the-number-of-files-and-directories">1. Counting the number of files and directories</h4>
<pre><code class="lang-bash">ls -l | wc -l
</code></pre>
<p>In the example above, the first section lists all the files and directories in the current directory using the <code>ls</code> command. The additional <code>-l</code> option tells the <code>ls</code> command to list the contents in a long list format. </p>
<p>The output of the <code>ls -l</code> command is then piped to the second section. The <code>wc -l</code> command counts the number of lines from the output of the <code>ls -l</code> command in the first section and prints the result to the terminal.</p>
<h4 id="heading-2-sorting-a-list-of-files-and-directories">2. Sorting a list of files and directories</h4>
<pre><code class="lang-bash">ls | sort
</code></pre>
<p>In the command above, the <code>ls</code> command will output the lists of the files and directories in the current directory. The list is then piped to the <code>sort</code> command, which sorts them alphabetically and prints the result to the terminal.</p>
<h4 id="heading-3-sort-and-display-unique-words-from-a-file">3. Sort and display unique words from a file</h4>
<pre><code class="lang-bash">cat words.txt | sort -r | uniq
</code></pre>
<p>The third example includes three separate commands connected by two pipes. The first command outputs the contents of the <code>words.txt</code> file, which contains a list of words. </p>
<p>The output is piped to the <code>sort -r</code> command, which sorts the words in reverse alphabetical order. Finally, the sorted words are piped to the <code>uniq</code> command, which removes duplicates and outputs the unique sorted words.</p>
<h3 id="heading-why-and-when-should-you-apply-command-piping-linux">Why and When Should You Apply Command Piping Linux?</h3>
<p>Piping takes more than just knowing the syntax. The syntax is pretty simple. To effectively use piping, you should understand its essence. </p>
<p>The purpose of piping is to help you chain commands, using the output of one as the input of another.</p>
<p>Piping is not meant to be a way to chain unrelated commands that you want to be executed sequentially. If you need to do that, write your commands in the terminal and separate them with semicolon (;) using the following syntax:</p>
<pre><code>command1 ; command2 ; ... ; commandN
</code></pre><h2 id="heading-what-is-redirection-in-linux">What Is Redirection in Linux?</h2>
<p>Redirection is the act of dictating where the inputs or outputs of your commands go. By default, commands receive data from standard input and then output the results in standard output.</p>
<p>One of the main areas where redirection proves useful is when working with commands and files. You can, for example, redirect the output of a command to a file instead of printing the output in the terminal. Alternatively, you can declare a certain file as an input to a command.</p>
<p>Like piping, Linux provides special characters to perform redirection. Here are important file-redirection characters in Linux and what they do:</p>
<ul>
<li><code>&gt;</code> – directs the output of a command to a given file.</li>
<li><code>&lt;</code> – directs the contents of a given file to a command.</li>
<li><code>&gt;&gt;</code> – directs the output of a command to a given file. Appends the output if the file exists and has content.</li>
<li><code>2&gt;</code> – directs error messages from a command to a given file.</li>
<li><code>2&gt;&gt;</code> – directs an error message from a command to a given file. Appends the error message if the file exists and has content.</li>
<li><code>&amp;&gt;</code> – directs standard output and error to a given file.</li>
<li><code>&amp;&gt;&gt;</code> – directs standard output and error to a given file. Appends to the file if it exists and has contents.</li>
</ul>
<p>Let's look at each file-redirection character in-depth.</p>
<h3 id="heading-1-output-redirection-with-gt">1. Output Redirection With <code>&gt;</code></h3>
<p>The <code>&gt;</code> symbol enables you to redirect the output of a command to a certain file. Using the symbol, you can redirect the output to any existing file. If it doesn't exist, the output redirection character will automatically create a new one. </p>
<p>However, you should be careful when writing to an existing file because its contents will be overwritten without a warning.</p>
<p>You can perform output redirection using the following syntax:</p>
<pre><code>command &gt; file
</code></pre><p>The output of running <code>command</code> will be written to the <code>file</code> instead of the standard output (or, in other words, printed to the terminal). Here's an example of how you can do output redirection:</p>
<pre><code class="lang-bash">ls -a &gt; contents.txt
</code></pre>
<p>In the command above, the list of items in the current directory (including dotfiles, directories, and files) will be written to the <code>contents.txt</code> file. You won't see any output in the terminal due to the redirection.</p>
<h3 id="heading-2-output-redirection-with-gtgt">2. Output Redirection With <code>&gt;&gt;</code></h3>
<p><code>&gt;&gt;</code> lets you redirect the output of a command to a file. But, unlike using a single greater than character (<code>&gt;</code>), <code>&gt;&gt;</code> will append the output if you try to write to an existing file (instead of overwriting its contents). If the file doesn't exist, it will create a new one.</p>
<p>The syntax is as follows:</p>
<pre><code>command &gt;&gt; file
</code></pre><p>Here's an example of using output redirection with <code>&gt;&gt;</code> to perform the same action as before:</p>
<pre><code class="lang-bash">ls -a &gt;&gt; contents.txt
</code></pre>
<h3 id="heading-3-input-redirection-with-lt">3. Input Redirection With <code>&lt;</code></h3>
<p>The <code>&lt;</code> character in the command line lets you redirect the input to a command from a file instead of the keyboard. The syntax of input redirection using <code>&lt;</code> is as follows:</p>
<pre><code>command &lt; file
</code></pre><p>Here's an example of using input redirection:</p>
<pre><code class="lang-bash">wc -w &lt; files.txt
</code></pre>
<p>In the example above, we're passing <code>files.txt</code> as the input to the <code>wc -w</code> command, which counts the number of words in the file. But you don't need to use the input redirection character in many scenarios because it's the default behavior. For instance, the command above is similar to the following:</p>
<pre><code class="lang-bash">wc -w files.txt
</code></pre>
<h3 id="heading-4-error-redirection-with-2gt-and-2gtgt">4. Error Redirection With <code>2&gt;</code> and <code>2&gt;&gt;</code></h3>
<p>When working on the command line, you may run into errors. For instance, if you want to execute a file without appropriate permissions. Instead of letting the terminal throw an error by printing it, you can use the error redirection character to dictate where the error message should go.</p>
<p>A good place to redirect errors is a file dedicated to storing errors. Here's a simple example of a command trying to access the list of files in a directory that doesn't exist:</p>
<pre><code class="lang-bash">ls nonexistent 2&gt; error.txt
</code></pre>
<p>In the example above, the terminal will throw an error since there's no file named <code>nonexistent</code>. But instead of printing it to the console, it will be stored in the <code>error.txt</code> file due to the error redirection character. However, the file will have nothing if there's no error.</p>
<p>If you must append an error to an existing file instead of overwriting its contents, use <code>2&gt;&gt;</code> instead of <code>2&gt;</code>.</p>
<h3 id="heading-5-output-and-error-redirection-with-ampgt-and-ampgtgt">5. Output and Error Redirection With <code>&amp;&gt;</code> and <code>&amp;&gt;&gt;</code></h3>
<p>Instead of choosing whether to redirect standard output or standard errors to a file, <code>&amp;&gt;</code> allows you to redirect both simultaneously. You can think of <code>&amp;&gt;</code> as a shorthand for combining the output redirection (&gt;) and error redirection (2&gt;) characters.</p>
<p>The syntax of using <code>&amp;&gt;</code> is as follows:</p>
<pre><code>command &amp;&gt; output.txt
</code></pre><p>The error or output of the <code>command</code> is written to the <code>output.txt</code> file. Here's an example:</p>
<pre><code class="lang-bash">ls sample &amp;&gt; output.txt
</code></pre>
<p>In the command above, if the <code>sample</code> directory is not available or is available but you don't have read permissions, an appropriate error will be written in the <code>output.txt</code> file. But if it exists and you have read permissions, its contents will be output in the <code>output.txt</code> file.</p>
<p>Using <code>&amp;&gt;&gt;</code> allows you to append the output to the file if it exists and has contents.</p>
<h2 id="heading-how-to-combine-piping-and-redirection-to-unleash-the-power-of-the-command-line">How to Combine Piping and Redirection to Unleash the Power of the Command Line</h2>
<p>Using piping and redirection in combination can let you perform complex operations without heavy lifting. By learning how to combine the two, you can create complex commands to perform various actions with less typing. </p>
<p>Take the following command as an example:</p>
<pre><code class="lang-bash">ls | grep <span class="hljs-string">".txt"</span> &gt; text_files.txt
</code></pre>
<p>The <code>ls</code> command lists the contents of the current directory. The output is piped to the <code>grep</code> command to filter text files. Finally, the output of the <code>grep</code> command is redirected to the <code>text_files.txt</code> file. </p>
<p>This simple yet powerful example shows that when it comes to piping and redirection, the only limit is your mind.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned the basics of piping and redirection in Linux. We covered the basics together with examples of how you can use the two. </p>
<p>The two features in isolation can be powerful, but you can go further by combining them in your commands, as shown in the last section.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Aliases to Terminal Commands in Linux and Mac ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll explore a simple trick that can save you hours of typing repetitive commands in the terminal. As developers, we spend a substantial amount of time executing commands on the terminal. Whether it's navigating through directories,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-aliases-to-terminal-commands/</link>
                <guid isPermaLink="false">66bd9096dc6141cf21aaadb6</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mac ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kaushal Joshi ]]>
                </dc:creator>
                <pubDate>Mon, 15 Apr 2024 15:37:42 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/terminal-alias.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll explore a simple trick that can save you hours of typing repetitive commands in the terminal.</p>
<p>As developers, we spend a substantial amount of time executing commands on the terminal. Whether it's navigating through directories, running scripts, changing Node.js versions, or version control commands, manually typing every command is a time consuming task. </p>
<p>For those who struggle to remember commands or their associated flags, this can become even more tedious.</p>
<p>Worry not! There's a simple yet powerful solution to this problem. It's called terminal aliases.</p>
<h2 id="heading-the-alias-command">The <code>alias</code> Command</h2>
<p>The <code>alias</code> command allows you to create shortcuts for existing commands, making them easier to remember and quicker to execute. When you define an alias, you are creating a new label for an existing command.</p>
<h3 id="heading-syntax-of-alias-command">Syntax of <code>alias</code> Command</h3>
<p>The syntax is straightforward: you can assign a command to a label like you'd assign a value to a variable in most programming languages.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">alias</span> alias_name=<span class="hljs-string">'long command'</span>
</code></pre>
<p>Let's dissect this command to understand it better:</p>
<ul>
<li><code>alias</code>: The terminal command that enables defining an alias.</li>
<li><code>alias_name</code>: This is the name or the label you are assigning to the command. Basically, you will type this in the terminal instead of the full command.</li>
<li><code>'long command'</code>: This is the command that you want to add an alias to. Make sure that you are wrapping the command with single quotes (<code>'</code>) as almost all commands contain spaces or special characters. </li>
</ul>
<h2 id="heading-predefined-aliases">Predefined Aliases</h2>
<p>There are some predefined aliases already set within terminals. And there is a high chance that you were using them without even knowing.</p>
<p>Such aliases are defined within the system (<code>/etc/bash.bashrc</code>) or user specific (<code>~/.bsahrc</code>) shell configuration files. </p>
<p>You can find a list of all predefined aliases by executing the <code>alias</code> command without any options or flags.</p>
<pre><code>alias
</code></pre><h2 id="heading-how-to-create-an-alias-that-persists-across-sessions">How to Create an Alias that Persists Across Sessions</h2>
<p>By default, aliases only persist in the current session. That means, if you close the terminal, the alias will be erased and you cannot use it afterwards.</p>
<p>To tackle this, you must define the alias in the shell's configuration file. Shell is an interpreter that resides inside a terminal and establishes an interface between you and the operating system. Hence, accessing the correct shell as well as modifying the correct configuration file is very important.</p>
<p>Here are the configuration files for the three most commonly used shell applications:</p>
<ol>
<li><strong>Bash</strong>: <code>~/.bashrc</code></li>
<li><strong>Zsh</strong>: <code>~/.zshrc</code></li>
<li><strong>Fish</strong>: <code>~/.config/fish/config.fish</code></li>
</ol>
<p>Let's try adding a new alias to Bash.</p>
<pre><code>echo <span class="hljs-string">"alias nrd='npm run dev'"</span> &gt;&gt; ~/.bashrc
</code></pre><p>Let's dissect this command:</p>
<ul>
<li><code>echo</code>: A terminal command that lets you write content within the terminal command.</li>
<li><code>"alias ..."</code>: This is the content we talked about in the previous point. It's an alias command that adds <code>nrd</code> as an alias for the <code>npm run dev</code> command. </li>
<li><code>&gt;&gt;</code>: Tells the terminal to append the content on the left (alias command) to the file on the right. In our case, we are storing it in the bash configuration file.</li>
<li><code>~/.bashrc</code>: This is the file to which the content from the echo command will be added.</li>
</ul>
<p>Don't forget to replace <code>~/.bashrc</code> with your shell's configuration file.</p>
<h2 id="heading-how-to-create-a-dynamic-alias">How to Create a Dynamic Alias</h2>
<p>Oftentimes, you need to use repetitive commands but with some little changes based on what you want. The best example of this is Git commands. In this case, you can add a substitute to your command which would be replaced by the dynamic option/parameter while executing it in the terminal.</p>
<pre><code>alias gpll=<span class="hljs-string">'git pull --rebase origin ${branch}'</span>
</code></pre><p>While executing the command, you need to replace <code>${branch}</code> with the branch you want to pull changes from. This is how you would do it to pull changes from the <code>main</code> branch:</p>
<pre><code>gpll main
</code></pre><p>You can also add multiple substitutes to your alias. Just make sure you are writing the alias with the correct order of actual values:</p>
<pre><code>alias gpll=<span class="hljs-string">'git pull --rebase ${remote} ${branch}</span>
</code></pre><p>While executing the command, you need to replace <code>${remote}</code> and <code>${branch}</code> with appropriate values, like the following:</p>
<pre><code>gpll origin main
</code></pre><h2 id="heading-how-to-create-an-alias-for-multiple-commands">How to Create an Alias for Multiple Commands</h2>
<p>There are cases where you need to use multiple commands sequentially. You can create an alias for that as well. Separate each command by <code>&amp;&amp;</code> which executes the command on the right after the command on the left is executed.</p>
<pre><code>gpsh=<span class="hljs-string">'git pull --rebase &amp;&amp; git push'</span>
</code></pre><h2 id="heading-how-to-delete-an-alias">How to Delete an Alias</h2>
<p>If you want to delete an alias from the current session, you can use the <code>unalias</code> command. This command takes only one argument — the alias name.</p>
<pre><code>unalias my-alias-name
</code></pre><p>However, if you want to delete an alias saved in the configuration file, you need to delete it from the file itself. You can use a simple text editor like <a target="_blank" href="https://help.ubuntu.com/community/Nano">Nano</a> to do this.</p>
<pre><code>nano ~/.bashrc
</code></pre><p>Scroll down to the bottom to find all of your aliases and delete the ones you don't want anymore.</p>
<p>When you're done, you can exit the editor after saving. This is the place where I can introduce a meme about not being able to exit terminal-based text editors. But with Nano, it's very simple:</p>
<ol>
<li>Press <code>ctrl</code>+<code>x</code> if you are on Linux and <code>^</code>+<code>x</code> if you are on Mac.</li>
<li>Press <code>Y</code> to confirm changes</li>
<li>Hit Enter or return based on your operating system to save the file.</li>
</ol>
<p>See? Nothing difficult :)</p>
<h2 id="heading-caveats">Caveats</h2>
<p>There are two important things that you must remember while creating an alias.</p>
<h3 id="heading-aliases-are-shell-restricted">Aliases are shell-restricted</h3>
<p>Aliases are specific to the shell you are using. An alias created in one shell won't work in another shell.</p>
<p>You must create a new alias if you want to use it in a different session. There is no workaround to this caveat. One trick you can do is to manually save the alias to the config files of all the shells you use.</p>
<h3 id="heading-aliases-are-session-bound-by-default">Aliases are session bound by default</h3>
<p>Aliases are only available in the current session. If you open a new terminal window or log out, the alias will not be available.</p>
<p>Hence, it's recommended to always save an alias to a configuration file so you use it anytime you want.</p>
<h2 id="heading-tldr">TL;DR</h2>
<ul>
<li><code>alias</code> command adds <em>shortcuts</em> to a command or series of commands. <code>alias shortcut='existing valid command</code>.</li>
<li>Save an alias to the shell's config file so it is persisted across sessions. Every shell has a unique config file. <code>echo "nrd='npm run dev'" &gt;&gt; ~/.bashrc</code>.</li>
<li>Create a dynamic alias by substituting the dynamic value with a placeholder. The placeholder must be wrapped by <code>${}</code>. <code>alias gp='git pull origin ${branch}</code> should be executed as <code>gp main</code> in the terminal.</li>
<li>Add multiple commands to an alias by joining them with <code>&amp;&amp;</code>.</li>
<li>Delete an alias by manually erasing it from the config file. </li>
</ul>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>I hope this blog helps you optimize your time and boosts your developer productivity. If it did, don't forget to share this with your peers so they can improve their efficiency as well.</p>
<p>What other techniques do you use to work efficiently? I would love to know more about it. I am most active on <a target="_blank" href="https://twitter.com/clumsy_coder">Twitter</a> and <a target="_blank" href="https://peerlist.io/kaushal">Peerlist</a>, if you want to say hi!</p>
<p>Until then, happy scripting! 👨‍💻</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Do Zsh Configuration Files Work? ]]>
                </title>
                <description>
                    <![CDATA[ Beginners often get confused when configuring Zsh shell on a Mac. Zsh shell offers four configuration files with no discernible differences. Particularly, ~/.zshrc and ~/.zprofile appear to be identical, leaving us wondering which one to use.  In thi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-do-zsh-configuration-files-work/</link>
                <guid isPermaLink="false">66ba15ffad32b828c4c5be04</guid>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ shell ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ zsh ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Kehoe ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jan 2024 20:37:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/pexels-mike-468229-1181772.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Beginners often get confused when configuring Zsh shell on a Mac.</p>
<p>Zsh shell offers four configuration files with no discernible differences. Particularly, <code>~/.zshrc</code> and <code>~/.zprofile</code> appear to be identical, leaving us wondering which one to use. </p>
<p>In this article, you'll learn the difference and a simple guideline for your shell configuration.</p>
<h2 id="heading-why-do-you-need-configuration">Why Do you Need Configuration?</h2>
<p>For programming on a Mac, the Terminal application is an essential tool in your development environment. The Terminal is a command-line interface (CLI) that allows you to interact with the operating system and run commands. </p>
<p>The Terminal or console gives you access to the Unix command line, or shell. </p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Z_shell">Zsh</a>, also known as Z shell, is a program that runs in the Terminal, interprets Unix commands, and interacts with the operating system. Zsh is the default shell program on MacOS.</p>
<p>Before you get started with programming on the Mac, you'll need to configure the shell. There are optional and convenient settings, such as aliases for hard-to-remember commands and a custom prompt that can display the directory you're in, among other things. </p>
<p>There are also some critical environment variables that make programs available or alter shell behavior. The <code>EDITOR</code> environment variable, for example, can set your preferred text editor. Oftentimes, when installing a programming language or software utilities, you need to set the <code>PATH</code> environment variable..</p>
<h2 id="heading-where-to-start">Where to Start</h2>
<p>Zsh configuration files are kept in the user's home directory and are named with a dot as the first character to keep them hidden by default. </p>
<p>Zsh recognizes four different configuration files in the user's home directory: <code>~/.zshenv</code>, <code>~/.zprofile</code>, <code>~/.zshrc</code>, and <code>~/.zlogin</code>. </p>
<p>This is where Zsh configuration becomes puzzling, even for experienced developers. Tutorials rarely explain the differences, especially between the <code>zprofile</code> and <code>zshrc</code> files, leaving curious developers scratching their heads and blindly following instructions.</p>
<h3 id="heading-how-is-the-shell-used">How is the Shell Used?</h3>
<p>To understand the differences among Zsh configuration files, consider various shell uses, which can be classified as interactive or non-interactive, login or non-login sessions.</p>
<ol>
<li>On macOS, each new terminal session is treated as a login shell, so opening any terminal window starts an interactive login session. Also, a system administrator who connects to a remote server via SSH initiates an interactive login session.</li>
<li>If a terminal window is already open and you run the command <code>zsh</code> to start a subshell, it will be interactive and non-login. Beginners rarely use subshells.</li>
<li>Automated shell scripts run without login or any user prompting. These are non-interactive and non-login.</li>
<li>Few people ever encounter a non-interactive login shell session. It requires starting a script with a special flag or piping output of a command into an SSH connection.</li>
</ol>
<h3 id="heading-how-do-the-configuration-files-work">How do the Configuration Files Work?</h3>
<p>These use cases necessitate different shell configurations, which explains why Zsh supports four different configuration files. Here's how the configuration files are used:</p>
<ul>
<li><code>~/.zshenv</code>: This is loaded universally for all types of shell sessions (interactive or non-interactive, login or non-login). It is the only configuration file that gets loaded for non-interactive and non-login scripts like cron jobs. However, macOS overrides this for <code>PATH</code> settings for interactive shells.</li>
<li><code>~/.zprofile</code>: Loaded for login shells (both interactive and the rare non-interactive sessions). MacOS uses this to set up the shell for any new terminal window. Subshells that start within the terminal window inherit settings but don't load <code>~/.zprofile</code> again.</li>
<li><code>~/.zshrc</code>: Loaded only for interactive shell sessions. It is loaded whenever you open a new terminal window or launch a subshell from a terminal window.</li>
<li><code>~/.zlogin</code>: Only used for login shell configurations, loaded after <code>.zprofile</code>. This is loaded whenever you open a new terminal window.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/zsh-diagram.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-use-each-file">How to Use Each File</h2>
<p>With that in mind, let's consider which configuration files you should use.</p>
<ul>
<li><code>~/.zshenv</code>: It is universally loaded, so you could use it to configure the shell for automated processes like cron jobs. However, it is best to explicitly set up environmental variables for automated processes in scripts and leave nothing to chance. As a beginner, you will not use this configuration file. In fact, few experienced macOS developers use it.</li>
<li><code>~/.zprofile</code>: Homebrew recommends setting the <code>PATH</code> variable here. There's a reason <code>PATH</code> should be set in  <code>~/.zprofile</code> and not the universal <code>~/.zshenv</code>file: the macOS runs a utility <code>path_helper</code> (from <code>/etc/zprofile</code>) that sets the <code>PATH</code> order before <code>~/.zprofile</code> is loaded.</li>
<li><code>~/.zshrc</code>: This is the configuration file that most developers use. Use it to set aliases and a custom prompt for the terminal window. You can also use it to set the <code>PATH</code> (which many people do) but <code>~/.zprofile</code> is preferred.</li>
<li><code>~/.zlogin</code>: This is rarely used. Only important in managing the order of initialization tasks for login shells in complex environments. It can be used to display messages or system data.</li>
</ul>
<h2 id="heading-how-to-avoid-complications">How to Avoid Complications</h2>
<p>These configurations may appear complicated. It made sense in the early days of computing to start time-consuming processes at login and not have them repeat when a new terminal was launched.</p>
<p>MacOS now launches any new terminal window as a login shell, loading both  <code>~/.zprofile</code> and <code>~/.zshrc</code> files without concern for the shell startup time. So why not use one Zsh configuration file? A bow to history, plus configuration customization for the experts.</p>
<p>The key advantage of the <code>~/.zprofile</code> file (versus  <code>~/.zshenv</code>) is that it sets environment variables such as <code>PATH</code> without override from macOS. The  <code>~/.zshrc</code> file could be used for the same but, by convention and design, is intended for customizing the look and feel of the interactive terminal.</p>
<h2 id="heading-keep-it-simple">Keep It Simple</h2>
<p>If you're looking for simple guidelines, here's the current best practice.</p>
<ul>
<li>Use <code>~/.zprofile</code> to set the <code>PATH</code> and <code>EDITOR</code> environment variables.</li>
<li>Use <code>~/.zshrc</code> for aliases and a custom prompt, tweaking the appearance and behavior of the terminal.</li>
<li>If you write automated shell scripts, check and set environment variables in the script.</li>
</ul>
<h2 id="heading-more-information">More Information</h2>
<p>I've written other guides that go into detail about the following:</p>
<ul>
<li><a target="_blank" href="https://mac.install.guide/terminal/index.html">Mac Terminal</a></li>
<li><a target="_blank" href="https://mac.install.guide/terminal/configuration.html">Shell Configuration</a></li>
<li><a target="_blank" href="https://mac.install.guide/terminal/path.html">Mac PATH</a>.</li>
</ul>
<p>If you're just getting started, you'll need to know <a target="_blank" href="https://mac.install.guide/terminal/open.html">How to Open Mac Terminal</a> and <a target="_blank" href="https://mac.install.guide/commandlinetools/index.html">Install Xcode Command Line Tools</a>.</p>
<p>Configuring the Zsh shell is a critical step in preparing your Mac development environment. With your development environment set up, you'll be prepared for any tutorial you'll find on freeCodeCamp.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Python End Program – How to Exit a Python Program in the Terminal ]]>
                </title>
                <description>
                    <![CDATA[ You can execute Python code in a terminal just like you would in an IDE like VS Code, Atom, and so on. You can do this in both Windows and Unix operating systems like Linux and macOS.  In this article, you'll learn how to exit a Python program in ]]>
                </description>
                <link>https://www.freecodecamp.org/news/python-end-program-how-to-exit-a-python-program-in-terminal/</link>
                <guid isPermaLink="false">66b0a340d7edba94d20b3bd0</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ihechikara Abba ]]>
                </dc:creator>
                <pubDate>Tue, 16 May 2023 16:48:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/jake-walker-MPKQiDpMyqU-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can execute Python code in a terminal just like you would in an IDE like VS Code, Atom, and so on. You can do this in both Windows and Unix operating systems like Linux and macOS. </p>
<p>In this article, you'll learn how to exit a Python program in the terminal using the following methods:</p>
<ul>
<li>The <code>exit()</code> and <code>quit()</code> functions in Windows and macOS (and other Unix-based systems – we'll use macOS to represent them). </li>
<li>The <code>Ctrl + Z</code> command in Windows. </li>
<li>The <code>Ctrl + D</code> command in macOS. </li>
</ul>
<h2 id="heading-how-to-run-a-python-program-in-the-terminal">How to Run a Python Program in the Terminal</h2>
<p>To run Python in the terminal, you have to open your terminal and run the <code>python</code> command. </p>
<p>Note that the <code>Python</code> command will only work in your terminal if you have Python installed on your computer. </p>
<p>After running the command, you should have something like this in the terminal:</p>
<pre><code class="lang-bash">C:\Users\USER&gt;python
Python 3.10.8 (main, Nov  6 2022, 23:27:16)  [GCC 12.2.0 64 bit (AMD64)] on win32
Type <span class="hljs-string">"help"</span>, <span class="hljs-string">"copyright"</span>, <span class="hljs-string">"credits"</span> or <span class="hljs-string">"license"</span> <span class="hljs-keyword">for</span> more information.
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/py-in-terminal.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Python command in the terminal</em></p>
<p>I am using Command Prompt for Windows but this should work the same way if you're using macOS or Linux.</p>
<p>Now you can run Python code in the terminal: </p>
<pre><code class="lang-bash">&gt;&gt;&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Welcome to Py in the terminal!"</span>)
Welcome to Py <span class="hljs-keyword">in</span> the terminal!
</code></pre>
<h2 id="heading-how-to-exit-a-python-program-in-the-terminal-using-the-exit-and-quit-functions">How to Exit a Python Program in the Terminal Using the <code>exit()</code> and <code>quit()</code> Functions</h2>
<p>You can use the <code>exit()</code> and <code>quit()</code> functions to exit a Python program in Windows and macOS. </p>
<pre><code class="lang-bash">&gt;&gt;&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Welcome to Py in the terminal!"</span>)
Welcome to Py <span class="hljs-keyword">in</span> the terminal!
&gt;&gt;&gt; <span class="hljs-built_in">exit</span>()

C:\Users\USER&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/py-in-terminal-exit.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>exit() command in Python terminal</em></p>
<p>In the example above, we printed "Welcome to Py in the terminal!" before exiting the terminal using the  <code>exit()</code> function. </p>
<p>After the function is executed, you'll be able to use the terminal the regular way (with the Python environment). </p>
<p>The process is the same for the <code>quit()</code> function:</p>
<pre><code class="lang-bash">&gt;&gt;&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Welcome to Py in the terminal!"</span>)
Welcome to Py <span class="hljs-keyword">in</span> the terminal!
&gt;&gt;&gt; quit()

C:\Users\USER&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/py-in-terminal-quit.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>exit() command in Python terminal</em></p>
<h2 id="heading-how-to-exit-a-python-program-in-the-terminal-using-the-ctrl-command">How to Exit a Python Program in the Terminal Using the <code>Ctrl +</code> Command</h2>
<p>You can exit a Python program running in a Windows terminal using the <code>Ctrl + Z</code> command: </p>
<pre><code class="lang-bash">&gt;&gt;&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Welcome to Py in the terminal!"</span>)
Welcome to Py <span class="hljs-keyword">in</span> the terminal!
&gt;&gt;&gt; ^Z


C:\Users\USER&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/py-in-terminal-ctrl-z.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>ctrl + z command to exit Python terminal in Windows</em></p>
<p>Similarly, you can use the <code>Ctrl + D</code> command in macOS. </p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we talked about running a Python program in the terminal. </p>
<p>We saw how to run Python in the terminal using the <code>Python</code> command. </p>
<p>We also saw how to exit a Python program in the terminal using a couple different methods. </p>
<p>The <code>exit()</code> and <code>quit()</code> functions can exit a Python program in the terminal for both Windows and macOS. </p>
<p>Alternatively, you can use the <code>Ctrl + Z</code> command to exit a Python program in the terminal in Windows and <code>Ctrl + D</code> in macOS. </p>
<p>Happy coding! You can learn more about Python on <a target="_blank" href="https://ihechikara.com/">my blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Print Methods in Java – How to Print to the Terminal ]]>
                </title>
                <description>
                    <![CDATA[ If you're learning Java, you probably started your coding journey by printing the "Hello World" program in the console. And that's a great way to begin – but after that, you need to learn how print methods and functions actually work. Well, this arti... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/print-methods-in-java/</link>
                <guid isPermaLink="false">66b9030e53c4132f77b5c2e9</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Md. Fahim Bin Amin ]]>
                </dc:creator>
                <pubDate>Wed, 19 Apr 2023 14:28:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/tracy-adams-TEemXOpR3cQ-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're learning Java, you probably started your coding journey by printing the "Hello World" program in the console. And that's a great way to begin – but after that, you need to learn how print methods and functions actually work.</p>
<p>Well, this article will show you how those print functions/methods actually work. You'll also learn the differences between the <strong><code>println</code></strong> and the <strong><code>print</code></strong> methods.</p>
<p>In Java, methods work like functions in other programming languages. But since Java developers typically prefer the term "Function", I am going to use that terminology as well for all of my Java-related articles. </p>
<p>If you want to print something in the terminal, you need to use one of the print methods. There are actually three different print methods in Java. They are the <strong><code>print</code></strong>, <strong><code>printf</code>,</strong> and <strong><code>println</code></strong> methods. We'll see how each of them works now.</p>
<h2 id="heading-how-to-use-the-print-method-in-java">How to Use the <code>print</code> Method in Java</h2>
<p>This is the most generic print method in Java, but developers only use it if they do not want to get any new line characters after printing the statement inside it. For example:</p>
<pre><code class="lang-java">System.out.print(<span class="hljs-string">"Fahim"</span>);
System.out.print(<span class="hljs-string">"Bin Amin"</span>);
</code></pre>
<p>The output would be like below:</p>
<pre><code>FahimBin Amin
</code></pre><p>I have not specified any newline character explicitly here, so it will not generate any new line explicitly. So, we will not get any new lines after printing the first statement. </p>
<p>If you do not know what escape sequences are and how they actually work, I have prepared this video for you. Make sure to watch it if you need a refresher.</p>
<h3 id="heading-video-tutorial">🎥 Video Tutorial</h3>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QqtYTnNxkoM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>If you want to add any spaces between the two statements even though you want to print them on the same line, then you can simply add a trailing space in the first statement or a leading space in the second statement.</p>
<pre><code class="lang-java">System.out.print(<span class="hljs-string">"Fahim "</span>);
System.out.print(<span class="hljs-string">"Bin Amin"</span>);
</code></pre>
<p>The output will be:</p>
<pre><code>Fahim Bin Amin
</code></pre><p>So, the <strong>print</strong> method is the most basic print method that doesn't add any specific thing other than simply printing the statement inside the method.</p>
<h2 id="heading-how-to-use-the-printf-method-in-java">How to Use the <code>printf</code> Method in Java</h2>
<p>You use the <code>printf</code> method to organize a statement differently. For example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> value = <span class="hljs-number">5.984</span>;
System.out.println(value);
System.out.printf(<span class="hljs-string">"%.2f"</span> , value);
</code></pre>
<p>The output is <code>5.98</code> because we have specified that we want to print exactly 2 digits after the radix (.) point. In those cases, we use the <code>printf</code> method. </p>
<h2 id="heading-how-to-use-the-println-method-in-java">How to Use the <code>println</code> Method in Java</h2>
<p>This method is the most widely used print method in Java. Whenever we want to print a newline after printing the statement inside of the method, we use this <strong><code>println</code></strong> method. </p>
<p>If you are using the "Extensions for Java" extension in the Visual Studio Code or if you are using the well known IntelliJ IDEA IDE, then you can get the full <code>println</code> method ( <code>System.out.println("")</code> ) in the editor by simply using the shortcut "sout".</p>
<p>Now, it is time for an example:</p>
<pre><code class="lang-java">System.out.println(<span class="hljs-string">"Fahim"</span>);
System.out.println(<span class="hljs-string">"Bin Amin"</span>);
</code></pre>
<p>The output is:</p>
<pre><code>Fahim
Bin Amin
</code></pre><p>As I used the <code>println</code> methods in both statements, each statement provides a newline character after printing the statement inside of it. So, after printing <code>Fahim</code>, I am getting a new line – in that new line, I am getting <code>Bin Amin</code>.</p>
<h3 id="heading-video-tutorial-1">🎥 Video Tutorial</h3>
<p>You can watch the video I made for you to help you understand these print methods better:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/_jfnI7yyaPo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Thanks for reading this entire article. I hope this helps you get started on your Java programming journey.</p>
<p>You can follow me on:</p>
<ul>
<li>GitHub: <a target="_blank" href="https://github.com/FahimFBA">FahimFBA</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/fahimfba/">fahimfba</a></li>
<li>Twitter: <a target="_blank" href="https://twitter.com/Fahim_FBA">Fahim_FBA</a></li>
<li>YouTube: <a target="_blank" href="https://www.youtube.com/@FahimAmin?sub_confirmation=1">Code With FahimFBA</a></li>
<li>Website: <a target="_blank" href="https://fahimbinamin.com/">https://fahimbinamin.com/</a></li>
</ul>
<p>If you want to support me, then <a target="_blank" href="https://www.buymeacoffee.com/fahimbinamin">you can also buy me a coffee!</a></p>
<p>Cover: Photo by <a target="_blank" href="https://unsplash.com/@tracycodes?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Tracy Adams</a> on <a target="_blank" href="https://unsplash.com/s/photos/java?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Spell Check on your Linux Terminal ]]>
                </title>
                <description>
                    <![CDATA[ Did you know you can use the terminal to check the spelling of a passage you've written?  The terminal has a lot of utility commands, but most people are unaware of many of them.  I've seen people using Microsoft Word or Google to check the spelling ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spell-check-on-your-linux-terminal/</link>
                <guid isPermaLink="false">66ba10f9f602a81788fe2195</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Fri, 20 Jan 2023 16:17:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/BB---Spell-Check-in-Linux-Terminal.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Did you know you can use the terminal to check the spelling of a passage you've written? </p>
<p>The terminal has a lot of utility commands, but most people are unaware of many of them. </p>
<p>I've seen people using Microsoft Word or Google to check the spelling of a word. But this utility command is a handy alternative tool for developers to check their spelling. The fact that it comes pre-installed with the terminal is an added advantage. </p>
<h2 id="heading-how-to-use-the-linux-spell-check-command">How to Use the Linux Spell Check Command</h2>
<p><code>ispell</code> and <code>aspell</code> are the 2 commands you can use to check the spelling of a word. Out of these 2, <code>ispell</code> is the old spellchecker from GNU which has a limited capability to read different kinds of encoded files. </p>
<p><code>aspell</code> is an interactive spell checker which checks the spelling via standard input or by reading through the file. It checks spelling on UTF-8 encoded files. It can read and check the spelling on markdown files, too. </p>
<p><code>aspell</code> has a lot of options. Running <code>--help</code> with the command shows the list of all the available options. </p>
<pre><code class="lang-bash">aspell --<span class="hljs-built_in">help</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-146.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>aspell --help</code> command output</em></p>
<p>If you encounter errors while running the above command, it means that you don't have it installed. Run the following command to install <code>aspell</code> in your machine:</p>
<pre><code class="lang-bash">sudo apt install aspell
</code></pre>
<h2 id="heading-how-to-check-the-spelling-of-words-one-by-one-interactively">How to Check the Spelling of Words One-by-one Interactively?</h2>
<p>Pass the <code>-a</code> flag with the <code>aspell</code> command to open it in interactive mode. </p>
<pre><code class="lang-bash">aspell -a
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-147.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>aspell -a</code> command to open <code>aspell</code> in interactive mode</em></p>
<p>In this mode, you can enter the words with possible incorrect spelling one by one and you will get a list of words with the correct spelling that are the closest to the entered word. </p>
<p>Here's an example screenshot: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>Correct word suggestions from <code>aspell</code> command</em></p>
<p>From the above screenshot, you can see that <code>aspell</code> suggests multiple words for each incorrectly-spelled word I entered. </p>
<p>The close alternatives for the word <code>sampee</code> are <code>sample</code>, <code>simper</code>, <code>sampler</code>. Similarly, you can see the suggestions for other words too (waier, calendrr, moble, bqttle). </p>
<p>This can be quite handy for developers since they can quickly switch to the terminal and find the correct spelling of a word during their development. The fact that it does not require the internet is an added advantage. </p>
<h2 id="heading-how-to-check-the-spelling-of-words-from-a-file">How to Check the Spelling of Words from a File</h2>
<p>Using the terminal to check the spelling of words from a file is the best alternative approach if you don't have internet access. Grammarly and Google Docs will best assist you with a good internet connection. </p>
<p>You can write the passage in a text file and pass the file path as an argument to the <code>-c</code> flag in the <code>aspell</code> command. This accepts an HTML or Markdown file too. </p>
<pre><code class="lang-bash">aspell -c &lt;filename&gt;
</code></pre>
<p>I've created a file named <code>computer.txt</code> and added the below content:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-157.png" alt="Image" width="600" height="400" loading="lazy">
<em>Content of <code>computer.txt</code> file</em></p>
<p>I've made some spelling mistakes in the middle. You might be able to spot them easily. Some of them are macine instead of machine, intrenet instead of internet, etc. </p>
<p>Let's ask <code>aspell</code> to find the spelling mistakes in this passage. </p>
<pre><code class="lang-bash">aspell -c computer.txt
</code></pre>
<p>Once you run the above command, you'll be shown a screen similar to the following screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-158.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>aspell</code> command to find spelling mistakes in a file</em></p>
<p>This means that <code>aspell</code> has figured out some spelling mistakes in our passage. It will highlight the misspelled words one-by-one with the appropriate alternative correctly spelled words at the bottom. </p>
<p>There will be 10 options shown with a row number. You can choose the correctly spelled word by entering the corresponding row number. </p>
<p>For example, in the above screenshot, the word "macine" is highlighted and the right replacement for this misspelled word is "machine", which is the 1st option. So, I press 1. </p>
<p>Immediately after I press 1, the correction was made and aspell moves to the next misspelled word. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-159.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>aspell</code> command corrects and moves to the next misspelled word in the file</em></p>
<p>In addition to the 10 options, <code>aspell</code> shows 8 different options. You can choose one of the them if you did not find the right word from the above 10 alternate options. </p>
<p>Let's understand each option you can use with <code>aspell</code>:</p>
<table><tbody><tr><td><strong>Character</strong></td><td><strong>Action</strong></td><td><strong>Description</strong></td></tr><tr><td>i</td><td>Ignore</td><td>Ignore this occurrence and move on to next misspelled word</td></tr><tr><td>r</td><td>Replace</td><td>Replace this word by manually entering a new word</td></tr><tr><td>a</td><td>Add</td><td>Add this word to the dictionary</td></tr><tr><td>b</td><td>Abort</td><td>Abort this operation (The changes you applied will not be saved)</td></tr><tr><td>I</td><td>Ignore all</td><td>Ignore all occurrences of this word</td></tr><tr><td>R</td><td>Replace all</td><td>Replace all occurrences of this word by manually entering a new word</td></tr><tr><td>l</td><td>Add Lower</td><td>Add the word to the dictionary</td></tr><tr><td>x</td><td>Exit</td><td>Exit the operation (The changes you applied will be saved)</td></tr></tbody></table>

<p>The above table describes the action for each character in the <code>aspell check</code> command. </p>
<p>Once you're done with correcting the spelling of all the misspelled words, the file will be automatically saved by <code>aspell</code>. </p>
<p>In addition to that, a new file will be created with the name <strong>.bak</strong>, which is a backup of the same file without applying spell check. </p>
<h2 id="heading-how-to-ignore-creating-a-new-file-while-correcting-spelling-in-a-file">How to Ignore Creating a New File While Correcting Spelling in a File</h2>
<p>This is quite simple and can be easily achieved by passing a flag with the <code>aspell</code> command. The flag is <code>--dont-backup</code>. </p>
<p>Let's look at an example command:</p>
<pre><code class="lang-bash">aspell check --dont-backup computer.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-160.png" alt="Image" width="600" height="400" loading="lazy">
<em>Ignore creating a backup file by passing <code>--dont-backup</code> flag</em></p>
<p>From the above screenshot, you can see that I've removed the existing <code>computer.txt.bak</code> file and run the spell check by passing the <code>--dont-backup</code> flag. No more <code>.bak</code> file has been created after I complete the spell check. </p>
<p>You may also notice one more change from the previous example and the above command. That is <code>check</code> and <code>-c</code>. In my previous command, I used <code>-c</code>, but in the above command, I used <code>check</code> to pass the file name. </p>
<p>You can either use <code>-c</code> or <code>check</code> to pass the file name. Both of them do the same job. </p>
<h2 id="heading-can-you-check-the-spelling-on-other-files">Can You Check the Spelling on Other Files?</h2>
<p>Absolutely yes. <code>aspell</code> checks for spelling by reading Markdown and HTML files, too. You have to pass the mode of the file as a separate argument ( <code>--mode</code> ). </p>
<p>Here's the syntax, </p>
<pre><code class="lang-bash">aspell check --mode=&lt;mode_type&gt; file_name
</code></pre>
<p>The supported modes are <code>none</code>, <code>url</code>, <code>email</code>, <code>markdown</code>, <code>html</code>, <code>tex</code>, <code>texinfo</code>, and <code>nroff</code>. </p>
<p>Let's see a quick example of fixing the spelling mistakes on a markdown file. </p>
<pre><code class="lang-bash">aspell check --dont-backup --mode=markdown spellcheck.md
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-161.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running <code>aspell</code> with the markdown file</em></p>
<p>It opened a similar interface, but it understood the markdown format and highlighted only the misspelled word. </p>
<p>I want to bring one important item to your attention. You can find a misspelled word (blok) in the middle of the backtick (<code>...</code>) block. The content inside this block will not be evaluated by the aspell command. So, you'll not be able to spot and correct the misspelled words inside the block. </p>
<p>Similarly, you can evaluate the spelling in the HTML files by changing the mode to html. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you have learned to check spelling using your Linux Terminal. I hope you enjoy reading it. </p>
<p>Subscribe to my newsletter by visiting my <a target="_blank" href="https://5minslearn.gogosoon.com/?ref=fcc_spell_check">site</a> and also have a look at the consolidated list of all my blogs. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Your Linux Terminal as a Calculator – Mathematical Expression Solver ]]>
                </title>
                <description>
                    <![CDATA[ Can you solve the below math expression on your own without using any device? Take as much time as you need – but no tools allowed: ( ( 11 + 97 ) + ( 2 * 63 ) - ( 7 / 93 ) * ( 8 - 25 ) ]]>
                </description>
                <link>https://www.freecodecamp.org/news/solve-your-math-equation-on-terminal/</link>
                <guid isPermaLink="false">66ba10f67282cc17abcf0c6a</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Thu, 15 Dec 2022 17:40:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/FreeCodeCamp---Evaluate-expression-on-Terminal.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Can you solve the below math expression on your own without using any device? Take as much time as you need – but no tools allowed:</p>
<pre><code class="lang-bash">( ( 11 + 97 ) + ( 2 * 63 ) - ( 7 / 93 ) * ( 8 - 25 ) / ( 9 * 64 ) ) * ( ( 64 / 34 ) + ( 94 - 20 ) - ( 23 + 98 ) * ( 199 * 928 ) / ( 92 * 26 ) ) * ( ( ( 2 * 1 ) / 2 ) - 1 )
</code></pre>
<p>Kudos to you if you solved it on your own. I'm sure you'll be angry with me, though, after discovering that the result of this long expression just evaluated to zero. </p>
<p>So what if you used your browser to find the answer? How long would that take?</p>
<p>Searching this expression on Google took less than a second to get the answer (using a 500MBPS connection) along with 5,21,00,000 results. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search results by Google for the given expression</em></p>
<p>Yahoo gave us the answer in less than 500 ms along with 1,480,000,000 search results. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search results by Yahoo for the given expression</em></p>
<p>Bing didn't even return anything.</p>
<p>But my terminal and system calculator were almost instant in finding the answer (took &lt; 10 ms). </p>
<p>Using the terminal is one of the quickest ways to evaluate a mathematical expression. But many developers are unaware that you can solve mathematical expressions using your terminal. </p>
<p>In this article, you'll learn how to solve math problems in the Linux terminal. </p>
<h2 id="heading-how-to-evaluate-a-mathematical-expression-in-the-linux-terminal">How to Evaluate a Mathematical Expression in the Linux Terminal</h2>
<p>You can use the <code>expr</code> command to evaluate mathematical expression in your terminal. Basic mathematical operations such as addition, subtraction, multiplication, division and modulus all work using the <code>expr</code> command. </p>
<p>Let's have a quick look at each of these operations:</p>
<pre><code class="lang-bash">expr 12 + 8   <span class="hljs-comment"># Addition</span>

expr 20 - 10  <span class="hljs-comment"># Subtraction</span>

expr 5 \* 2   <span class="hljs-comment"># Multiplication</span>

expr 8 \/ 4   <span class="hljs-comment"># Division</span>

expr 5 \% 3   <span class="hljs-comment"># Modulus</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-64.png" alt="Image" width="600" height="400" loading="lazy">
<em>Using the <code>expr</code> terminal command to find answers to arithmetic operations</em></p>
<p>Running each of those commands in the terminal evaluates and returns the answer of that expression (as you can verify in the attached screenshot). </p>
<p>You might be thinking, "Why is there a backward slash () for the last 3 operations (Multiplication, Division, and Modulus)?"</p>
<p>A backward slash in programming is basically used to escape characters. Let's take the example of the Multiplication symbol (<em>). "</em>" is used in regular expressions which basically means to include all files and folders. </p>
<p>Here's a quick example:</p>
<pre><code class="lang-bash">cp ./* ../backup/
</code></pre>
<p>Running the above command will copy all the files and folders in the current directory to the backup directory. </p>
<p>Similarly, each symbol has their own meaning. Using a backward slash () will escape its regular usage pattern. This is the reason that most symbols are prefixed with a backward slash. </p>
<p>But, you may wonder, is this all this command can do? </p>
<p>The answer is no. I've shared a sample of the expressions, but we could use any others and get the results in a fraction of a second. </p>
<h2 id="heading-how-to-evaluate-a-logical-expression-in-the-terminal">How to Evaluate a Logical Expression in the Terminal</h2>
<p>In addition to finding the results of a mathematical expression, you can use this command to evaluate a logical expression. </p>
<p>Logical expressions containing &lt;, &lt;=, &gt;, &gt;=, =, != can be evaluated with this command. </p>
<p>Let's have a quick look at how it works:</p>
<pre><code class="lang-bash">expr 2 \&lt; 1

expr 29320 \&gt; 23820

expr 29320 \&gt;= 29320

expr 29320 \&lt; 29320

expr 29320 \&lt;= 29320

expr 293202 \= 293203

expr 293202 \!= 293203
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-65.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evaluate logical expressions with <code>expr</code> command</em></p>
<p>The command returns "1" if the expression evaluates to true and "0" if it evaluates to false. </p>
<p>From the above commands you can notice that all the logical operators are escaped with a backward slash (). </p>
<h2 id="heading-what-do-the-special-logical-operators-do">What Do the Special Logical Operators Do?</h2>
<p>I read your mind. You're thinking, "I know about logical operators. What are the special logical operators?". </p>
<p>Well, the special logical operators are:</p>
<ul>
<li>AND (&amp;)</li>
<li>OR (|)</li>
</ul>
<p>From a programming perspective, the AND operator evaluates to true if both sides of the operator evaluates to true. The OR operator evaluates to true if either of the sides evaluates to true. </p>
<p>Here's the table for your reference. Some people may be familiar with <code>1</code> and <code>0</code>. For those people, replace FALSE with <code>0</code> and TRUE with <code>1</code>. </p>
<table>
    <tbody><tr>
        <td>X</td>
        <td>Y</td>
        <td>X OR Y</td>
        <td>X AND Y</td>
    </tr>
    <tr>
        <td>FALSE</td>
        <td>FALSE</td>
        <td>FALSE</td>
        <td>FALSE</td>
    </tr>
    <tr>
        <td>FALSE</td>
        <td>TRUE</td>
        <td>TRUE</td>
        <td>FALSE</td>
    </tr>
    <tr>
        <td>TRUE</td>
        <td>FALSE</td>
        <td>TRUE</td>
        <td>FALSE</td>
    </tr>
    <tr>
        <td>TRUE</td>
        <td>TRUE</td>
        <td>TRUE</td>
        <td>TRUE</td>
    </tr>
</tbody></table>

<p>But they have a completely different usage with the <code>expr</code> command. Let's have a quick look at it. </p>
<p>The <code>expr</code> command works similar to the above table. But there's an exception for a particular case. This command will never return <code>1</code> if an expression evaluates to true – instead it returns an argument. </p>
<p>Evaluating <code>expr ARG1 | ARG2</code> returns ARG1 if ARG1 is neither <code>null</code> nor <code>0</code>, otherwise it'll return ARG2. On the other hand, evaluating <code>expr ARG1 &amp; ARG2</code> returns ARG1 if neither of the arguments are <code>null</code> or <code>0</code> . It returns <code>0</code> otherwise. </p>
<p>Let's examine few examples with the logical OR operator:</p>
<pre><code class="lang-bash">expr 1 \| 2     <span class="hljs-comment"># Returns first argument (1)</span>

expr 0 \| 2     <span class="hljs-comment"># Returns second argument (2) as first argument is 0</span>

expr <span class="hljs-string">""</span> \| 2    <span class="hljs-comment"># Returns second argument (2) as first argument is null </span>
                  (Empty string [<span class="hljs-string">""</span>] is considered as null <span class="hljs-keyword">in</span> terminal)

expr 100 \| 78    <span class="hljs-comment"># Returns first argument 100</span>

expr <span class="hljs-string">""</span> \| <span class="hljs-string">""</span>   <span class="hljs-comment"># Returns 0 as both arguments are null ("")</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-68.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evaluating logical OR expressions with <code>expr</code> command</em></p>
<p>The above screenshot represents operations with logical OR operator (|). Reading that you may still have a couple of questions:</p>
<h3 id="heading-whats-the-purpose-of-using-empty-double-quotes-in-the-expression">What's the purpose of using empty double quotes ("") in the expression?</h3>
<p>Empty double quotes represent a <code>null</code> value in bash. So, as said earlier, if the first argument is null, the second argument is returned. </p>
<h3 id="heading-what-if-both-the-arguments-are-null">What if both the arguments are null?</h3>
<p>When evaluating both arguments with null values, both the Logical OR and AND operators return <code>0</code>. </p>
<p>Let's examine a few examples with the logical AND operator:</p>
<pre><code class="lang-bash">expr 1 \&amp; 2     <span class="hljs-comment"># Returns first argument (1)</span>

expr 1 \&amp; 0     <span class="hljs-comment"># Returns 0 as one (second) argument is 0</span>

expr 0 \&amp; 1     <span class="hljs-comment"># Returns 0 as one (first) argument is 0</span>

expr <span class="hljs-string">""</span> \&amp; 1    <span class="hljs-comment"># Returns 0 as one (first) argument is null ("")</span>

expr 1 \&amp; <span class="hljs-string">""</span>    <span class="hljs-comment"># Returns 0 as one (second) argument is null ("")</span>

expr <span class="hljs-string">""</span> \| <span class="hljs-string">""</span>   <span class="hljs-comment"># Returns 0 as both arguments are null ("")</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-69.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evaluating logical AND expressions with <code>expr</code> command</em></p>
<h2 id="heading-how-to-perform-string-operations-with-the-expr-command">How to Perform String Operations with the <code>expr</code> Command</h2>
<p>The <code>expr</code> command is not limited to mathematical and logical operations. It can perform string operations, too. </p>
<h3 id="heading-pattern-matching-with-regex">Pattern Matching with Regex</h3>
<p>The <code>expr</code> command can verify if a text matches with a regex pattern. It returns the matched pattern of the text if it exists or else returns an empty line. </p>
<p>The syntax to verify the regex is:</p>
<pre><code class="lang-bash">expr STRING : REGEXP

or

expr match STRING REGEXP
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-71.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>expr</code> command evaluates regex pattern match with the given text</em></p>
<p>You can achieve this either by using the <code>match</code> keyword or by using a semicolon (<code>:</code>) between the string and the regex pattern. </p>
<p>Alternatively, you can use the semicolon to find the number of characters matching between the two texts. </p>
<p>Here's an example:</p>
<pre><code class="lang-bash">expr Remember : Remo    <span class="hljs-comment"># Returns 0</span>

expr Remember : Rem     <span class="hljs-comment"># Returns 3</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-75.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>expr</code> command to find the number of characters matching the given text</em></p>
<h3 id="heading-find-the-length-of-a-text">Find the length of a text</h3>
<p>You can use the <code>expr length</code> command to find the length of the given text. </p>
<pre><code class="lang-bash">expr length Linux

expr length <span class="hljs-string">"Learning Linux is fun"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-72.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>expr length</code> command showing the number of characters in the given text</em></p>
<p>You can enter the text directly after the <code>expr length</code> command if it does not have any spaces. If the text has spaces, enclose them within double quotes (""), or else you'll get an error. </p>
<h3 id="heading-find-a-character-in-a-text">Find a character in a text</h3>
<p>You can find a particular character from a given text using the <code>expr index</code> command. It returns the place where the character exists. </p>
<pre><code class="lang-bash">expr index STRING CHAR
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-74.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>expr index</code> to find a character from a text</em></p>
<p>Remember that the <code>expr index</code> command performs a case-sensitive search and returns the first matching index of a character from the text. </p>
<h3 id="heading-extract-a-substring-from-a-string">Extract a substring from a string</h3>
<p>Extracting a substring from a string is simple using <code>expr</code> command. Entering the string, start index, and number of characters to be clipped after the start index will return the expected substring. </p>
<pre><code class="lang-bash">expr substr Carpenter 4 3      <span class="hljs-comment"># Returns pen</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/image-76.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>expr substr</code> command to find a substring from a string</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you have learnt the use cases of the <code>expr</code> command.</p>
<p>If you enjoyed my tutorial, you can subscribe to my newsletter on my <a target="_blank" href="https://5minslearn.gogosoon.com/">personal site</a> to receive more such insightful articles straight to your inbox. You'll also find a consolidated list of all my blog posts. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Linux Date Command – How to Query the Terminal to Get Dates ]]>
                </title>
                <description>
                    <![CDATA[ Linux has many utility tools that help you quickly find the answer to your questions. But many devs aren't aware of them. In this article, you will learn a command that has exceptional benefits.  For example, say you want to take a look at your calen... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-query-the-terminal-to-get-dates-linux/</link>
                <guid isPermaLink="false">66ba10d0a1a94b68c6ae94b4</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Sat, 19 Nov 2022 19:06:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/10.-Date-Command---Brief-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Linux has many utility tools that help you quickly find the answer to your questions. But many devs aren't aware of them.</p>
<p>In this article, you will learn a command that has exceptional benefits. </p>
<p>For example, say you want to take a look at your calendar to plan a vacation. What are a few ways you can open the calendar? Well, there's Google/Outlook, your system desktop calendar, your mobile phone calendar, and more.</p>
<p>But did you know that you can get a calendar just by typing three letters? In this article, I'll teach you this helpful three-letter command and share some fun experiences of using <code>date</code> with my team. </p>
<h2 id="heading-how-to-query-your-terminal-for-the-date">How to Query Your Terminal for the Date</h2>
<p>I remember I was busy working one day. I asked one of my colleagues sitting next to me, "Do you know the date of next week Friday?" Then I realized that he was wearing headphones and appeared to be deeply concentrating on his code. </p>
<p>I didn't want to disturb him further, and I was about to ask my other colleague sitting right opposite me. </p>
<p>"November 25", the colleague whom I thought couldn't hear me replied. </p>
<p>I was amazed – how'd he know that fast? </p>
<p>"Oh, man! I thought you were coding. How did you get the date?" I asked him, surprised. </p>
<p>"I was querying the terminal to find the answer to the question you asked me", he replied, showing his terminal window. </p>
<p>The terminal window had the following command:</p>
<pre><code class="lang-bash">dd <span class="hljs-string">"next week Friday"</span>
</code></pre>
<p>I didn't understand what he'd done, so I as. </p>
<p>"Well, Linux by default supports the date command to display today's date and to set the current date and time in our system. It also provides a way to find a date in the future and past as simply as we speak. <code>date</code> is the command to do all stuff related to date and time", he replied. </p>
<p>I was more confused about the <code>dd</code> command and I asked him to clarify how it worked.</p>
<p>"But if <code>date</code> is the command, what's <code>dd</code>? Is that part of the <code>date</code> command?" </p>
<p>He explained that <code>dd</code> is not associated with the <code>date</code> command. Rather, it was just a shortcut command (I'll be writing about this in my future tutorials) that he created. <code>dd</code> abbreviates to <code>date --date="&lt;given_date&gt;"</code>.</p>
<p>So, the actual command is this:</p>
<pre><code class="lang-bash">date --date=<span class="hljs-string">"next week Friday"</span>
</code></pre>
<p>I ran the same in my terminal and was amazed to see the output. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-69.png" alt="Image" width="600" height="400" loading="lazy">
<em>Linux terminal command to find the date of the given day</em></p>
<p>This was cool and I thanked him for his super helpful explanation. On further research, I found that this command was able to answer most of my queries. I felt like I was interacting with an AI system. </p>
<p>I'm posting a few of my queries here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Screenshot-from-2022-11-15-00-05-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Query terminal for a future or past date</em></p>
<h2 id="heading-how-to-get-specific-info-about-a-date-in-linux">How to Get Specific Info About a Date in Linux</h2>
<p>Up until now, we have been trying to find a particular day with our query. But, what if you want to find some info about a date? After a bit more research, I found that you can find the day of the week of a date using the same command. </p>
<p>The following command displays the day of the week of August 1, 2015:</p>
<pre><code class="lang-bash">date --date=<span class="hljs-string">"2015-08-01"</span>
date --date=<span class="hljs-string">"08/01/2015"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-82.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to find the day of a date</em></p>
<h2 id="heading-how-to-find-information-about-a-list-of-dates-in-linux">How to Find Information About a List of Dates in Linux</h2>
<p>My coworker had a list of dates. He needed a script that displayed each date with the day. He'd gotten stuck trying to figure it out, and asked for my help. </p>
<p>He was clear on his problem. But he has gone wrong with the steps he took to achieve it. On further discussion, I found that he searched the following items sequentially in Google.</p>
<ul>
<li>How to open a file in read mode?</li>
<li>How to read line by line? </li>
<li>How to parse the date in the file? </li>
<li>Finally, How to find the day of that date? </li>
</ul>
<p>In the middle of this discussion, I remembered that you can do this quickly with the super powerful <code>date</code> command. The fact is that the <code>date</code> command does all the above actions – our job is just to give the path of the file. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-83.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to parse dates from a file</em></p>
<p>The fact that it can read and parse the date given in any format is an added advantage. From the above screenshot, you will be able to understand how simple it is to solve my coworker's problem. </p>
<p>Remembering the quote from <a target="_blank" href="https://www.goodreads.com/work/quotes/53327688">Unfiltered: No Shame, No Regrets, Just Me</a> by Lily Collins</p>
<blockquote>
<p>Asking for help is never a sign of weakness. It's one of the bravest things you can do. And it can save your life.</p>
</blockquote>
<h2 id="heading-how-the-date-command-works-with-file-operations">How the Date Command Works with File Operations</h2>
<p>If you've read my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-learn-linux-terminal-as-a-beginner/">previous tutorial on getting started with Linux</a>, you may remember that with the <code>stat</code> command we can get some info about the file such as its size, date created, last date modified, and so on. </p>
<p>Well, did you know you can find the last modified time of a file using the <code>date</code> command? </p>
<p>Yes – by adding the <code>-r</code> flag with the <code>date</code> command and the file path, you can find the last modified time of the file. It looks like this:</p>
<pre><code class="lang-bash">date -r install_git.sh
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-84.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command showing the last modified time of a file</em></p>
<p>There is another place where this date command might be more familiar. You use it to create a file with a timestamp. For example, system administrators often use it to see system and server logs. I've also heard that people in stock trading also rely on creating files with timestamps. </p>
<p>Here's a quick example of creating a file with date and time:</p>
<pre><code class="lang-bash">vi file-$(date <span class="hljs-string">"+%Y-%m-%d_%I:%M:%S"</span>).txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-85.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to create a file with date and time</em></p>
<p>For first time users, it might be tough to understand the above command. </p>
<p>Let's break this command down to understand it better:</p>
<ul>
<li><code>vi</code> is my text editor</li>
<li><code>file-$(date "+%Y-%m-%d_%I:%M:%S").txt</code> is the name of the file</li>
</ul>
<p>Let's bisect the <code>date</code> command in the file name further:</p>
<ul>
<li><code>date "&lt;some_format&gt;"</code> prints the date in the specified format</li>
<li><code>%Y</code> is the current year</li>
<li><code>%m</code> is the current month</li>
<li><code>%d</code> is today's date</li>
<li><code>%I</code> is hours</li>
<li><code>%M</code> is minutes</li>
<li><code>%S</code> is seconds</li>
</ul>
<h2 id="heading-how-to-find-the-date-and-time-in-a-different-time-zone">How to Find the Date and Time in a Different Time Zone</h2>
<p>One of my other team members raised this interesting question. </p>
<p>It's possible to find the date and time in another time zone with the <code>date</code> command. But, it's not so user-friendly. You need to remember the full name of the timezone to get the date and time. But, it works out of the box. </p>
<p>I'm in India and we follow Indian Standard Time (IST). I can use the below command to find the time in New York. </p>
<pre><code class="lang-bash">TZ=<span class="hljs-string">'America/New_York'</span> date
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-86.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command showing New York time</em></p>
<p>The below screenshot shows you the time comparison across different time zones such as Singapore, America, and India. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-87.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command showing time across different timezone</em></p>
<h2 id="heading-what-is-the-three-letter-command-to-get-your-calendar">What is the Three-Letter Command to Get Your Calendar?</h2>
<p>Are you waiting to know the 3 letter command to view the terminal? </p>
<p>It is the <code>cal</code> command. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-94.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command to display the calendar</em></p>
<p>Here's a <strong>bonus</strong> tip for you. </p>
<p>You can view the calendar of any year by just adding the year next to the <code>cal</code> command. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-95.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command showing 2022 calendar year</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-96.png" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal command showing 2023 calendar year</em></p>
<p>If you wish to learn more about the <code>cal</code> command you can reach out to me on social media. </p>
<p>Note: <code>date</code> and <code>cal</code> come pre-installed in many Linux distributions. If you encounter the <code>date: command not found</code> error while running the <code>date</code> command, you just need to install the <code>coreutils</code> package by running the following command:</p>
<pre><code class="lang-bash">sudo apt install coreutils
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, I shared my experience of using the <code>date</code> command in Linux. I hope you enjoyed reading this article. </p>
<p>To have more insightful blogs delivered to your inbox, subscribe to my newsletter <a target="_blank" href="https://5minslearn.gogosoon.com/">here</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Learn the Linux Terminal as a Beginner – Tips and Examples ]]>
                </title>
                <description>
                    <![CDATA[ In 2017, I bought a new laptop and switched to Linux. I started off with Ubuntu (but jumped to Elementary later), as most people suggested it was beginner friendly.  People also suggested that I should get used to using the keyboard and terminal over... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-learn-linux-terminal-as-a-beginner/</link>
                <guid isPermaLink="false">66ba10c89065919bb4e84cb1</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Mon, 07 Nov 2022 21:25:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/10.-Linux-basic-commands---Brief.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In 2017, I bought a new laptop and switched to Linux. I started off with Ubuntu (but jumped to <a target="_blank" href="https://elementary.io/">Elementary</a> later), as most people suggested it was beginner friendly. </p>
<p>People also suggested that I should get used to using the keyboard and terminal over a mouse to enjoy the ultimate power of Linux. </p>
<p>So I started learning various terminal commands and keyboard shortcuts. The fact that I could type pretty fast was a cherry on the cake. </p>
<p>In this article, I'll walk you through the experiences I had learning to handle file and folder operations in Linux. </p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before starting to use terminal, you need to get familiar with two commands. They'll come in handy for whatever operations you're trying to do. </p>
<p>They are the <code>cd</code> and <code>ls</code> commands. </p>
<ul>
<li><code>**cd**</code> is a command that lets you navigate to a path or a different folder in terminal</li>
<li><code>**ls**</code> is a command that lets you list all the files and folders in a directory</li>
</ul>
<h2 id="heading-how-i-started-learning-some-basic-linux-commands">How I Started Learning Some Basic Linux Commands</h2>
<p>I love downloading and reading files and books from the internet. But I used to have a bad habit of downloading all the files into the <code>Downloads</code> folder. </p>
<p>One day I was in a hurry to search a document, because I had to give a presentation. But opening and searching through the long list of files in my <code>Downloads</code> folder was really frustrating for me as it had 1000+ files. </p>
<p>I wanted to find a shortcut to identify the file. The only clue I had was that it's a PDF document. So, I planned to copy all the PDF files to another temporary folder. </p>
<h3 id="heading-how-to-copy-only-pdf-files-from-one-folder-to-another">How to copy only PDF files from one folder to another</h3>
<p><code>cp</code> is the command to copy the files. Thankfully the Linux terminal supports <code>regex</code> almost everywhere. So, my work became quite simple. Here's the code to copy the pdf files into another folder:</p>
<pre><code class="lang-bash">cp &lt;file(s)_to_copy&gt; &lt;destination_folder&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-252.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to copy only the pdf files from one folder to another?</em></p>
<p>From the above screenshot, you may be confused about the <code>mkdir Temp_PDF_Files</code> command. You use the <code>mkdir</code> command to create a new directory.    </p>
<p>Some of you might also be confused with <code>_./_*.pdf</code> in the <code>cp</code> command. Basically, in the programming world we call this a <strong>Regex</strong>. Regex stands for <strong>Regular Expression,</strong> and we use them to filter items by matching patterns. In our case, it's the files ending with the <code>.pdf</code> extension</p>
<p>After running the command, there were fewer than 50 PDF files. I was able to find the file in couple of minutes. </p>
<p>So as you can see, it's always advisable to categorize your downloaded files. </p>
<p>Cool, I was done with my presentation. But, I wanted the file to be named properly, so that I could find it more quickly in the future. </p>
<h3 id="heading-how-to-rename-a-file-in-linux">How to rename a file in Linux</h3>
<p>I Googled to learn how to do this, but I was amazed to see the same answer everywhere, which I felt was not right. It was the <code>mv</code> command, which I ideally used to move a file/directory from one path to another. </p>
<p>After digging down further, I found that it was the same <code>mv</code> command to rename the file. </p>
<pre><code class="lang-bash">mv &lt;existing_file_name&gt; &lt;new_file_name&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-253.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to rename a file in Linux?</em></p>
<p>I finished renaming the file. But, I didn't want the temporary folder which I'd created to copy all the PDF files. </p>
<h3 id="heading-how-to-delete-a-folder-completely-in-linux-including-its-files-and-sub-folders">How to delete a folder completely in Linux (including it's files and sub-folders)</h3>
<p>Before getting into this, I copied the renamed file to a safe place which I could remember easily in the future. I was bit nervous as I was about to delete the entire folder. I usually get this feeling whenever I delete anything. </p>
<p>You can delete files and folders with <code>rm -rf</code> command which I'd used many times before. </p>
<pre><code class="lang-bash">rm -rf &lt;folder_name&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-254.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to delete a folder completely in Linux?</em></p>
<p>But be careful as it's a <strong>dangerous</strong> command. It won't ask for any confirmation before deleting the folder. Recovering a folder deleted with this command is almost impossible. </p>
<h2 id="heading-how-to-create-and-read-files-in-linux">How to Create and Read Files in Linux</h2>
<p>People usually get stressed out when they're late, and this is worse for important meetings or online classes. This happened to me – and it led me to a great experience of learning about handling file operations via the terminal. </p>
<p>It was a bright morning and my online class had already started – and I was delayed by 2 minutes. I wanted to start taking notes, but I had put my notebook and pen somewhere the night before and couldn't remember exactly where. </p>
<p>The very next thing that came to my mind was to open Google Docs. But that site would take some time to load. </p>
<p>"Why don't I create a text file on my machine and start taking notes? ", was the question that hit my mind next. </p>
<h3 id="heading-how-to-create-a-file-in-linux">How to create a file in Linux</h3>
<p>I remembered that one of my friends told me that you can use the <code>touch</code> command to create a file instantly. But, I hadn't tried that out yet. So I did:</p>
<pre><code class="lang-bash">touch notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-266.png" alt="Image" width="600" height="400" loading="lazy">
<em>touch - Linux command to create a file</em></p>
<p>But... But... But...  </p>
<p>This command creates a file and does not open this file in edit mode so you can start taking notes. This is where you can use your favorite text editor to open a file. </p>
<p><strong>vim</strong> and <strong>nano</strong> are the two well-known text editors available in Linux. </p>
<p><strong>vim</strong> is an advanced and powerful text editor you can use to perform <strong>complex file operations</strong> and it's what many Linux System Administrators use.</p>
<p><strong>nano</strong>, on the other hand, is a simple text editor which you can use to perform <strong>simple file operations</strong>.</p>
<p>I was using nano, so I ran the command <code>nano notes.txt</code>. This opens up the text file in edit mode instantly. I started taking notes from the session. </p>
<p>Finally, I reached the end of class, but I didn't know to save the file. I didn't dare try any commands before getting a backup of my notes. So, I picked up my mobile and took a snap of my notes. </p>
<p>After a quick Google search, I found that the command was "CTRL + X" to save the file (which will prompt Yes / No to save the file, and hitting "Y" and pressing "Enter" will save it). </p>
<p>After saving the file, I was curious to check if I had saved it correctly. </p>
<h3 id="heading-how-to-read-the-contents-of-a-file-in-linux">How to read the contents of a file in Linux</h3>
<p>After doing a Google search, I found that there are multiple ways to read a file. <code>cat</code>, <code>head</code>, and <code>tail</code> are a few commands you can use to read a file, and they each have their own use cases. </p>
<ul>
<li>The <code>**cat**</code> command displays the entire contents of the file</li>
<li>The <code>**head**</code> command displays the few lines at the top of the file usually used to check if you're about to open the correct file</li>
<li>And the <code>**tail**</code> command displays the bottom few lines of the file usually used to read logs from any process.</li>
</ul>
<p>Here's an example of the <code>cat</code> command:</p>
<pre><code class="lang-bash">cat notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-268.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reading contents on my notes file with <strong>cat</strong> command</em></p>
<p>And here's the output of the <code>**head**</code> and <code>**tail**</code> commands:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-269.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output of <strong>head</strong> command displaying top few lines of notes file</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-270.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output of <strong>tail</strong> command displaying last few lines of notes file</em></p>
<h3 id="heading-how-to-read-the-contents-of-a-file-with-line-numbers-in-linux">How to read the contents of a file with line numbers in Linux</h3>
<p>One day, one of my colleagues asked me, "Hey! Do you know how to display the contents of a file with their line numbers in the terminal? "</p>
<p>I hadn't came across any such commands explicitly available for this. I knew I could write a script that reads the file line by line, and then print them on the console by pre-pending line numbers for each line.</p>
<p>He wanted to explore that option.</p>
<p>We both started to work our way through this problem. Interestingly, in the middle, we found a single and straightforward command. </p>
<p>Yes – I'm talking about the <code>nl</code> command. You use it like this:</p>
<pre><code class="lang-bash">nl notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-271.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>nl</code> command shows contents of file with line numbers</em></p>
<p>That's amazing, isn't it? As you can see from the code above, the <code>nl</code> command shows the contents of the file with line numbers.</p>
<h2 id="heading-linux-commands-i-learned-from-my-team">Linux Commands I Learned from My Team</h2>
<p>My team and I used to sit together and work as a group. We would ask questions about any random technical stuff and tried to explore solutions for any issues that came up. So I wanted to quickly summarize some of the things I learned from my colleagues here. </p>
<p>Most of them revolve around a lot of file utility commands available in Linux which most people are unaware of. During our development time, we come across multiple scenarios that had to do with handling files. </p>
<p>My colleague <strong>Naras</strong> asked this question: </p>
<h3 id="heading-whats-a-command-to-find-the-properties-of-a-file">What's a command to find the properties of a file?</h3>
<p>Well, the <code>stat</code> command displays the properties of the file such as name, size, permissions, created by the user, created and updated date and time, and so on. It looks like this: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-272.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>stat</code> - Terminal command to display the properties of the file</em></p>
<h3 id="heading-is-there-a-command-to-find-number-of-words-in-a-file">Is there a command to find number of words in a file?</h3>
<p>It was an awesome question from <strong>Udhaya.</strong> </p>
<p>Yes. But, not just words – you can also count lines and bytes using the <code>wc</code> command. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-273.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>wc</code> command displays number of lines, words and bytes of a file</em></p>
<p>The above displayed file has 23 lines and 121 words. Its size is 809 bytes. </p>
<h3 id="heading-can-you-find-the-type-of-the-document-with-a-command">Can you find the type of the document with a command?</h3>
<p>Few weeks back, I encountered an extraordinary question from <strong>Kumar</strong>:</p>
<p>"Most documents are created with their extension. But recently I found that some PDF documents are not created with .pdf extension. Do we have a command to find the type of document? "</p>
<p>Yes we do. The <code>file</code> command displays the type of the document, like this:</p>
<pre><code class="lang-bash">file notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-275.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>file</code> command displaying the type of <code>notes.txt</code> file</em></p>
<p>To answer his question, here's the proof showing the type as PDF document before and after removing the extension from the file name:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-274.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>file</code> command displaying file type without the extension</em></p>
<h3 id="heading-how-can-i-find-the-occurrences-of-a-word-in-a-file">How can I find the occurrences of a word in a file?</h3>
<p>My colleague <strong>Divad</strong> asked if we could find all the lines where a particular word was available in a file.</p>
<p>And I realized that this was possible with the <code>grep</code> command.</p>
<p>So what's <code>grep</code>? </p>
<p><code>**grep**</code> stands for <strong>G</strong>lobal search for <strong>R</strong>egular <strong>E</strong>xpression and <strong>P</strong>rint out. It's basically a searching tool which matches with a Regex pattern and prints them. </p>
<pre><code class="lang-bash">grep -i <span class="hljs-string">"Linux"</span> notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-276.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>**grep**</code> command displays lines containing <strong>Linux</strong> from <strong>notes.txt</strong> file</em></p>
<p>The <code>**-i**</code> flag indicates to perform <strong>case insensitive</strong> search. To perform <strong>case sensitive</strong> search, <strong>remove</strong> the <code>-i</code> flag from the command. </p>
<h3 id="heading-what-if-i-want-to-find-all-the-lines-that-dont-contain-a-particular-word">What if I want to find all the lines that don't contain a particular word?</h3>
<p><strong>Raman</strong> raised the question, "What if I want to find all the lines that does not contain the given word?"</p>
<p>It's possible using the same <code>grep</code> command but by applying the <code>-v</code> argument, like this: </p>
<pre><code class="lang-bash">grep -v <span class="hljs-string">"Linux"</span> notes.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-277.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>**grep -v**</code> command displays lines not containing the word <strong>Linux</strong> from the <strong>notes.txt</strong> file</em></p>
<p>As you can see, by discussing our questions and working things out together, we learned a lot.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this article, I've shared my experience using Linux when I was a beginner. I hope you enjoyed reading this article. </p>
<p>You can connect with me <a target="_blank" href="https://www.linkedin.com/in/arunachalamb/">here</a>. </p>
<p>You can follow me on <a target="_blank" href="https://www.instagram.com/5minslearn/">Instagram</a>, <a target="_blank" href="https://twitter.com/5minslearn">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/5minslearn/">LinkedIn</a> and <a target="_blank" href="https://5minslearn.medium.com/">Medium</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
