Skip to content

Fig

1.0.56
Last updated – 26th March 2022

Important Fig Links

What is it?

Fig is a Mac app and adds autocomplete to the terminal. Sounds boring but it's actually really useful. It's similar to zsh-autocomplete but is much nicer on the eyes and is very easily extensible.

As a developer, you spend a lot of time in your terminal and Fig has been one of the most useful apps I've found in a while. It shows the commands, subcommands and flags with a brief description as you cycle between them. This makes getting more familiar with new tools much easier as you can discover as you type.

Here's an example of what it looks like: An example of Fig autocomplete

The icons and colours allow you to see different types of autocompletion at a glance.

How do I use it?

Once you install it and complete the setup, you're good to go.

It works on the following terminals as of writing:

  • Terminal
  • iTerm
  • Hyper
  • VS Code
  • Tabby

With more coming soon.

It also works with the following shells:

  • bash
  • zsh
  • fish

You should start to see suggestions as you type right away and it works for a huge number of CLI tools.

Extensibility

If there's something missing, because Fig is extensible it's very easy to write a plugin.

Static spec

Here's an example of the completion spec for mkdir. It's pretty straightforward.

const completionSpec: Fig.Spec = {
  name: "mkdir",
  description: "Make directories",
  args: {
    name: "directory name",
    template: "folders",
    suggestCurrentToken: true,
  },
  options: [
    {
      name: ["-m", "--mode"],
      description: "Set file mode (as in chmod), not a=rwx - umask",
      args: { name: "MODE" },
    },
    {
      name: ["-p", "--parents"],
      description: "No error if existing, make parent directories as needed",
    },
    {
      name: ["-v", "--verbose"],
      description: "Print a message for each created directory",
    },
    {
      name: ["-Z", "--context"],
      description:
        "Set the SELinux security context of each created directory to CTX",
      args: { name: "CTX" },
    },
    { name: "--help", description: "Display this help and exit" },
    {
      name: "--version",
      description: "Output version information and exit",
    },
  ],
};

export default completionSpec;

Dynamic suggestions

You're not limited to static specs where you know everything ahead of time.

const constants = {
  elixir_logo_url: "...", // Removed for brevity
};

// Mix spec
const completionSpec: Fig.Spec = {
  name: "mix",
  description: "Build tool for Elixir",
  icon: constants.elixir_logo_url,
  subcommands: [
    {
      name: "new",
      description: "Creates a new Elixir project at the given path",
      args: {
        name: "path",
      },
      options: [
        {
          name: ["-h", "--help"],
          description: "Output usage information",
        },
        {
          name: "--app",
          description: "Name the OTP application for the project",
          args: {
            name: "app",
          },
        },

        {
          name: "--modules",
          description: "Name the modules in the generated code skeleton",
          args: {
            name: "module",
          },
        },
        {
          name: "--sup",
          description:
            "Generate an OTP application skeleton including a supervision tree. Normally an app is generated without a supervisor and without the app callback",
        },
        {
          name: "--umbrella",
          description: "Generate an umbrella project",
        },
      ],
    },
    {
      name: "help",
      description:
        "Prints documentation for a given task (Lists all the tasks if no task is specified)",
      args: {
        name: "task",
        isOptional: true,
        description: "Prints documentation for a given task",
        generators: {
          cache: { ttl: 10000 },
          script: "mix help",
          postProcess: makeTaskSuggestions,
        },
      },
      options: [
        {
          name: "--search",
          description:
            "Prints all tasks and aliases that contain 'pattern' in the name",
          args: {
            name: "pattern",
          },
        },
        {
          name: "--names",
          description: "Prints all task names and aliases",
        },
      ],
    },
  ],
  args: {
    name: "task",
    description: "Invokes the task (mix run) in a project",
    isOptional: true,
    generators: {
      cache: { ttl: 10000 },
      script: "mix help",
      postProcess: makeTaskSuggestions,
    },
  },

  options: [
    {
      name: ["-h", "--help"],
      description: "Shows usage information",
    },
    {
      name: ["-v", "--version"],
      description: "Shows versioning information",
    },
  ],
};

function makeTaskSuggestions(out: string) {
  return out
    .split("\n")
    .map((task) => {
      const [name, description] = task.split("#").map((x) => x.trim());

      return {
        name: name.replace(/^mix /, ""),
        description,
      };
    }) // filter out commands which do not make sense here
    .filter((x) => !["mix", "help", "new", "iex -S mix"].includes(x.name));
}

export default completionSpec;

Notice the makeTaskSuggestions function, it calls mix help, reads the output and transforms it into an object with name and description so it can be displayed in Fig.

When do I use it?

Discoverability

One of the most useful side effects of Fig is discovering new flags and commands you didn't know about in common tools. Sure, you could take a look at the man pages or run the help command but in daily use it's much easier to just start trying to use a command and let Fig act as a helpful advisor.

Even with commands you use everyday like ls, Fig can read the directory and offer a list of directories and files directly in dropdown. This is just a useful time saver.

Learning

If you're new to programming, there terminal can be confusing. Fig helps by making it a bit more user friendly and welcoming. You still need to know roughly what you're doing but once you know the tool, Fig can offer suggestions. This simple little app makes using the terminal more approachable to modern audiences.

Future

Fig right now does one thing really well but they're looking to do a few other things in the terminal to bring it into the modern era. I think Fig is really interesting because it has the potential to become a companion to the terminal as it expands to cover more use cases. Managing terminal plugins and syncing dotfiles is coming soon, this has the potential to make Fig no-brainer when setting up your terminal and getting the best experience.