Introducing the terminal to developers

Published by on (last update: )

The article I wish I had read when I had to open the terminal for the first time.

Introduction

Being a developer can be quite overwhelming these days. Getting familiar with a codebase and the framework(s) and libraries it uses is not the whole story. There is also a real demand of additional skills to get your job done, such as using Git, package managers, and build tooling.

Many of these tools are to be used in the terminal, which may be new and a bit frightening. But don’t worry, we’ve all been there. This article provides an overview, along with practical examples, to get you up to speed with the terminal and some essential tooling.

Why do I need the terminal?

For certain tasks you can get away without using the terminal at all. For example, there are great GUI tools for working with Git. However, getting familiar with tools like Git from the terminal gives you more power and flexibility. In the end, a GUI is a graphical shell in front of a command-line tool. Often limited by screen estate or a minimalistic design, a GUI may feature only a subset of the underlying command-line interface. Being “closer to the metal”, it can also help you to get out of trouble in case a GUI is stuck or messed up.

Frameworks and libraries for programming languages (such as JavaScript or PHP) come and go, but knowing your way around in the terminal is a skill you can use always and everywhere.

What actually is a terminal?

A terminal is text-based, and serves as the command-line interface (CLI) you can type your commands in. A shell takes these commands, and tells the operating system to execute them.

On macOS, the default terminal application is named “Terminal”, and the default shell is Bash. You will also find a “terminal” in Linux distributions like Debian and Ubuntu. On Windows 10, you can install a Linux environment.

For the rest of this article, I’ll be assuming you are using Bash or a similar shell.

Opening a terminal

The first thing you will always get is a prompt. It’s what “prompts” you to type a command. The prompt might include information such as the computer and/or user name, and usually ends with a $. Behind the $ is the cursor, where you can type commands.

~
Terminal window
Last login: Sun Sep 17 21:20:17 on ttys000

If your terminal has a white background color, but you prefer to have a black background color instead: this article contains instructions on how to do this.

Finding your way

In an application like Finder or File Explorer you can navigate your files and folders. In the terminal we can do the same with commands like ls and cd (to list files and change directories, respectively). For example:

~/Documents
Terminal window
Last login: Sun Sep 17 21:20:17 on ttys000

The last line is the default output of ls. You can pass it extra arguments (or “options”) to change its behavior. For instance, there is -a to show all files (including hidden ones), and -l to show one file per line:

~/Documents
$ ls -a -l
total 1160
drwx------ 6 lars staff 204 Sep 12 19:52 .
drwxr-xr-x 64 lars staff 2176 Sep 12 22:29 ..
-rw-r--r-- 7 lars staff 42 Sep 12 19:52 .DS_Store
-rw-r--r-- 7 lars staff 81238 Sep 12 19:52 tutorial.pdf
-rw-r--r-- 1 lars staff 11086 Jul 5 22:35 Keynote.pdf

The arguments can also be combined into one: ls -al means the same.

Here are some essential commands to manage files and directories:

Terminal window
ls # List files

If you want more information about any of these commands, you could either use the --help argument, or perhaps google the command. Both ways are not ideal: the former is correct and complete, but often hard to read. And the latter takes more time and needs you to switch context between the terminal and a web browser. Maybe we can improve on this. We all like readable documentation, right?

Package managers

Let’s use this as a an opportunity to install a package manager, and then install a package with it. In this case, one for simplified documentation.

In a nutshell, package managers are an essential tool to install system-wide (or “global”) software, or local dependencies within a project. You may have heard of Homebrew, npm, Maven, RubyGems, or apt-get. In this article, we’ll be looking at Homebrew and npm.

Are you working with JavaScript? You need npm (the package manager for JavaScript), which comes with Node.js. You can install Node.js via many package managers. This will also make npm available on your system.

Now we can install a package named “tldr” with either one of them. Using npm:

$ npm install --global tdlr

Or, with Hombrew:

$ brew install tldr

Now you can try for instance tdlr cd to see what I mean with readable documentation:

$ tldr cd

cd

Change the current working directory.
More information: https://man.archlinux.org/man/cd.n.

- Go to the given directory:
cd path/to/directory

- Go to home directory of current user:
cd

- Go up to the parent of the current directory:
cd ..

- Go to the previously chosen directory:
cd -

We’ll dive into npm in a minute. However, if you have questions or got stuck installing a package manager, then you might want to check out one of the following links:

Git

Git is a program that many projects use for version control. Basically, it allows people to work on code together, while keeping track of changes. Everybody should not be editing the same files directly, and sometimes changes need to be reverted.

Collaborating with Git involves cloning (“downloading”) the code repository of a project, making changes to fix bugs or develop new features, and then pushing back (“uploading”) the changes. It is common to create a separate branch first, so others can review the changes before they are merged back into the master branch.

Let’s install Git (with a package manager, obviously)! Here are some options for various operating systems:

Below is a screenshot after running a few commands as an example:

~/Projects/my-first-repository
$ mkdir my-first-repository
$ cd my-first-repository/
$ git init
Initialized empty Git repository in /Users/lars/Projects/my-first-repository/.git/
$ git checkout -b cool-feature
Switched to a new branch 'cool-feature'
$ echo "Some content" > somefile.txt
$ ls
somefile.txt
$ git add somefile.txt
$ git status
On branch cool-feature

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: somefile.txt

$ git commit -m "Add some file"
[cool-feature (root-commit) b706c43] Add some file
1 file changed, 1 insertion(+)
create mode 100644 somefile.txt
$

For more information on working with Git, here are a two excellent tutorials:

npm

npm is the package manager for JavaScript. Even though Node.js itself is a server-side application runtime, and npm was originally built for Node modules, npm proves to be a great dependency manager for JavaScript in general. Next to JavaScript modules, the npm repository contains many tools built on top of Node.js, such as Grunt, Webpack, Babel, UglifyJS, and many more.

To manage JavaScript dependencies with npm, a project has a package.json file. It contains meta data about the project, and always includes a project name and version. Here’s an example:

{
"name": "my-awesome-project",
"version": "1.2.6",
"description": "My awesome project!",
"license": "MIT",
"repository": "[email protected]:webpro/my-awesome-project.git",
"dependencies": {
"lodash": "4.17.4",
"react": "15.6.1"
},
"devDependencies": {
"mocha": "3.5.3"
}
}

Let’s clone this project with Git, and install its dependencies:

~/Projects/my-awesome-project
$ cd Projects/
$ git clone [email protected]:webpro/my-awesome-project.git
Cloning into 'my-awesome-project'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$ cd my-awesome-project/
$ ls -a
. .. .git package.json
$ npm install
added 56 packages, and audited 57 packages in 4s
[...]
$ ls node_modules/
asap fbjs js-tokens loose-envify react
balanced-match fs.realpath json3 minimatch react-is
brace-expansion glob lodash minimist safer-buffer
browser-stdout graceful-readlink lodash._baseassign mkdirp setimmediate
commander growl lodash._basecopy mocha supports-color
concat-map has-flag lodash._basecreate ms ua-parser-js
core-js he lodash._getnative node-fetch whatwg-fetch
create-react-class iconv-lite lodash._isiterateecall object-assign wrappy
debug inflight lodash.create once
diff inherits lodash.isarguments path-is-absolute
encoding is-stream lodash.isarray promise
escape-string-regexp isomorphic-fetch lodash.keys prop-types
$

The command npm install installed the dependencies lodash and react (and their dependencies) locally in the node_modules directory.

Note that this installs the dependencies locally to the project. This is very different from installing packages globally, as we did with the tldr package (using the --global or -g argument). In general, local packages are dependencies for a single project and global packages are used from the command line.

If you want to learn more, I can recommend this article about npm dependencies and scripts: Using npm dependencies in npm scripts.

Tips & tricks

In this section I’d like to present a few tips and tricks to make your life in the terminal easier right away.

Change the terminal’s theme

In macOS and some Linux distributions, the default background color of the terminal application is white, and the window might be slightly transparent. Yet many people prefer a black background in the terminal (like the screenshots in this article).

Here’s you can change this for macOS: from the Terminal.app, go to Preferences (⌘,), go to Profiles, and select the desired profile (e.g. the “Pro” theme). Make sure to press the “Default” button to store this for later sessions as well. In the same screen, you can go into the “Background Color” modal and set opacity to 100% to remove the transparency.

Shortcuts & commands you should know

The ^ (caret) below represents the “Control” key:

ShortcutDescription
Show the previous command
Show the next command
^aMove the cursor to the start of the line
^eMove the cursor to the end of the line
(tab) Auto-complete commands, and directory and file names
!!Run the previous command again
^lClear the screen (or clear)
^cCancel the current process (if it hangs or becomes unusable)
^dExit the current terminal (or exit)

Aliases and functions

Over time, you will see that you are using the same commands and parameters over and over again. This is where aliases and functions come in. An alias can be used as an abbreviation for a more complex command. For example:

Terminal window
alias ll="ls -lA --color"

Now you can use ll as an alias and it will execute the ls command including the extra arguments. You can also still add extra arguments to ll. Use alias without arguments to get a list of all active aliases.

Functions can contain logic, and a main difference with aliases is that you can pass it arguments. Here’s a trivial example:

Terminal window
say_hi () {

You can invoke this function with say_hi John, and it would print Hello, John:

$ say_hi John
Hello, John

This is a very short and superficial introduction to this topic. If you are interested in learning more, please check out the following resources:

Wrapping up

After reading this article I hope you feel slightly more comfortable to use the terminal. I’ve compiled a short list of great resources to get some directions to learn more. What’s next for you?

If you feel there’s something important missing in this article, feel free to let me know (in a comment here, or via Twitter: @webprolific). Thanks for reading!

Further reading