Skip to content

CLI for making browser search queries

Notifications You must be signed in to change notification settings

LexBorisoff/web-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Web CLI

CLI for making browser search queries.

Installation

Install the package globally:

npm i -g @lexjs/web-cli

After installing, the web command is ready for use without any setup.

web hello world

> https://google.com/search?q=hello%20world

web Array.prototype.at --mdn

> https://developer.mozilla.org/search?q=String.prototype.at

web typescript tutorial --youtube

> https://youtube.com/results?search_query=typescript+tutorial

To get help with command options, use the --help option:

web --help

To check the installed version, use the --version option:

web --version

Usage

To perform basic web queries, provide space-separated values

web <values>

The CLI will then construct 1 or more queries based on the type of values and open them in a new browser tab.

There are 2 types of values:

  1. Keywords
  2. URLs

Keywords

When providing keywords, only 1 web query is created using the values as a search term:

web hello world

> https://google.com/search?q=hello%20world

In the absence of options, CLI uses the default search engine to construct the query and opens it in the default browser:

  • After installation, there is a set of initial search engines that you can use (default - Google).
  • The operating system's default browser is used to open the web queries.

You can change these defaults and add new engines and browsers by setting up and running a config project.

Initial search engines

Search Engine Option Value
Google google
DuckDuckGo duckduckgo duck
Github github
MDN mdn
YouTube youtube
NPM npm

The option value can be either supplied to the --engine option or used as a custom flag.

URLs

When providing a URL value, the default behavior is to open it directly:

web github.com

> https://github.com

If multiple URLs are provided, each URL creates a separate web query:

web github.com npmjs.com developer.mozilla.org

> https://github.com
> https://npmjs.com
> https://developer.mozilla.org

Keywords and URLs together

If both keywords and URLs are provided, then all values are treated as search term keywords:

web most starred repos on github.com

> https://google.com/search?q=most%20starred%20repos%20on%20github.com

Options

Options give you control over web queries by overriding the CLI's defaults.

To use an option in the command, prefix it with a double dash --

web --option

1-letter options (like an option's alias, for example) are prefixed by a single dash -

web -x

If an option requires a value (value options), provide it in one of the following ways:

web --option=value
web --option value

The assignment syntax (--option=value) is more explicit and helps avoid any confusion between what is an option's value and what is an actual keyword, especially when building larger web queries with many search term keywords.

1-letter options can be combined together with a single dash - as long as their combination is valid:

web -xyz

which is equivalent to:

web -x -y -z

⚠️ Combining 1-letter aliases of multiple value options will result in invalid queries when such combinations are followed by a value. It is recommended to combine only the flag options which can be built-in or custom. If you want to add a 1-letter value option, it must be placed at the very end of the combination. If the value option is placed in the middle, the value argument will not get assigned to it.

Value options

The following are built-in options that require a value:

Option Alias Description
browser b Browser app to open
profile p Browser profile to use
engine e Search engine (or website) to query
search s Engine's search path to use for querying
resource r Engine's resource to access
port : Port number to add to the URL

All value options work without any initial configuration but most options' usage can be enhanced by setting up the config. Refer to each option as well as engines configuration and browsers configuration for more details.

Flag options

Options that do not require a value are called flags. The following are built-in flag options:

Option Alias Description
incognito i Open in incognito / private mode
split ❌ Create a separate web query for each value argument
http ❌ Use the HTTP (non-secure) protocol
test t Display the output without opening browser tabs

⚠️ Flag options can be assigned values true and false. This is because, internally, flags are booleans. Using a flag option in the command automatically sets its value to "true" but the option will still accept a boolean value that's placed after it (even without the explicit = sign). Therefore, make sure to not accidentally assign "true" or "false" to a flag if you do not intend it. Doing so will result in your web query missing the keyword "true" or "false" from the search term.

With browsers and engines configuration set up, you can also use custom flags which are created from the keys and aliases of browsers, browser profiles, and engines from the generated config file. Custom flags simplify your web queries by being a convenient substitute for value options.

Placement

Options can be placed anywhere in the command

web --browser=firefox this is --incognito an example --engine=duckduckgo search query
web -b=firefox this is -i an example -e=duckduckgo search query

Typically, you would place the options where they make sense visually such as at the start or the end of the command. This example just shows you that their placement does not impact the constructed queries.

The above command will do the following:

  • construct a web query using
    • keywords "this is an example search query"
    • the DuckDuckGo search engine (--engine=duckduckgo)
  • open the constructed query in a new Firefox tab (--browser=firefox)
  • in incognito / private mode (--incognito)

Configuration

Creating configuration allows you to customize the usage of Web CLI and enhance many of the built-in options. Before learning about these options, it is beneficial to know how to create and generate your own custom config.

Creating a config project

Web CLI allows you to create a config by scaffolding a TypeScript project and then running it with an npm script defined in package.json. Even if you are not familiar with TypeScript, you should be able to quickly grasp and navigate around the created application.

First, run the following command in the directory where you want to create the project.

web --config

On its first run, you won't have an existing config so it will give you only 2 options:

  • Engines to show the initial engines
  • New config to create a new config project

As was mentioned earlier, you get access to a set of initial search engines after installing the package. You can see these engines by selecting the first option.

What we need, however, is to select the second option in order to create a new config directory. Once selected, the CLI will help you initialize and scaffold the project.

Editing the config project

After the scaffolding process is complete, you can navigate to the created directory and open it in your IDE. You can also push it to a remote git repository such as Github to keep your config in sync on different machines.

There are two initial files in the src folder that you can customize:

  • engines.ts
  • browsers.ts

Both of these files import a function called defineConfig from @lexjs/web-cli/config.

// src/engines.ts
import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ engine }) => ({
  google: engine("google.com", {
    search: "search?q=",
  }),
  // ... other engines
}));
// src/browsers.ts
import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ browser }) => ({
  chrome: browser(),
}));

You can add more engines and browsers, as well as edit or remove them by extending the initial code.

Since this is a regular TypeScript project, you are free to organize it however you want, add more files, functions, use other libraries, etc. Just remember to:

  • call the defineConfig function that defines the engines and/or browsers, and
  • correctly generate the config file (described in the next section)

Defining config

defineConfig accepts a callback that

  • takes an object with engine and browser functions in its parameter
  • returns an object with defined engines and/or browsers
// not exact representation
type DefineConfigCallback = ({
  engine: CreateEngineFn;
  browser: CreateBrowserFn;
}) => Record<string, Engine | Browser>;

Engines Configuration

To create an engine, use the engine function from the callback's parameter and assign it to a property of the callback's return object:

defineConfig(({ engine }) => ({
  google: engine("google.com", {
    search: "search?q=",
  }),
}));

⚠️ The property's key name is important because it is used as a value for the --engine option and as a custom flag.

The engine function is of type CreateEngineFn:

// not exact representation
type CreateEngineFn = (baseUrl: string, config?: Config) => Engine;

When defining an engine, you must provide the base URL string as the first argument and, optionally, a config object as the second argument.

The optional config parameter has the following shape:

interface Config {
  search?: string | SearchObject;
  resources?: ResourceObject;
  alias?: string | string[];
  delimiter?: string;
  isDefault?: boolean;
}

interface SearchObject {
  [key: string]: string | StringObject;
  main: string;
}

interface ResourceObject {
  [key: string]: string | StringObject;
}

interface StringObject {
  [key: string]: string | StringObject;
}

All Config properties are optional. Let's examine each available option:

  1. search - defines how the search engine should be queried with keywords.

The value of this option can be one of the following:

  • a string such as search?q=, ?q=, etc. For example:
defineConfig(({ engine }) => ({
  example: engine("example.com", {
    search: "search?q=",
  }),
}));
  • an object with:
    • at least 1 property called main of the string type
    • other optional properties with string or nested object values (the most nested values must be strings). For example:
defineConfig(({ engine }) => ({
  example: engine("example.com", {
    search: {
      main: "search?q=",
      foo: {
        bar: "foobar?q=",
        baz: {
          deeply: {
            nested: "foobaz?q=",
          },
        },
      },
    },
  }),
}));

Defining the search config as an object allows you to provide its keys as values to the --search built-in option instead of typing the actual search string. For example:

web --search=main
web --search=bar
web --search=nested

⚠️ Using the keys foo, baz, and deeply is not valid because they do not point to a string value.

  1. resources - defines what routes can be accessed on the engine.

The value of this option is an object with string or nested object values (similarly, the most nested values must be strings). For example:

defineConfig(({ engine }) => ({
  github: engine("github.com", {
    resources: {
      profile: "username",
      tabs: {
        repos: "?tab=repositories",
        projects: "?tab=projects",
        stars: "?tab=stars",
      },
      deeply: {
        nested: {
          example: "example/path/to/some/resource",
        },
      },
    },
  }),
}));

Defining the resources config allows you to provide its keys as values to the --resource built-in option. For example:

web --resource=profile
web --resource=example
web --resource=profile::tabs

⚠️ Just like in the search example above, using keys like tabs, deeply, or nested that do not point to a string value is not valid.

Note the profile::tabs syntax - it allows you to construct a route based on 2 config keys. The final URL will combine together both values of the provided property keys.

  1. alias - a string or array of strings that provides alias names for the engine.
defineConfig(({ engine }) => ({
  youtube: engine("youtube.com", {
    alias: ["y", "yt"],
  }),
  duckduckgo: engine("duckduckgo.com", {
    alias: "duck",
  }),
}));

Defining engine aliases allows you to provide them to the --engine built-in option or use them as custom flags. For example:

web --engine=duck
web --duck
web -y
  1. delimeter - defines how the search keywords should be delimited in the constructed URLs.
defineConfig(({ engine }) => ({
  duck: engine("duckduckgo.com", {
    delimiter: "+",
    search: "?q=",
  }),
}));

When the engine is used, the delimiter specified in its config will be applied to combine the keywords. You should only provide the delimiter value if it differs from the default single whitespace character " ".

  1. isDefault - defines whether the engine should be used as the default.
defineConfig(({ engine }) => ({
  duck: engine("duckduckgo.com", {
    search: "?q=",
    delimiter: "+",
    isDefault: true,
  }),
}));

When setting this option to true, Web CLI will use that engine when there is no --engine option or engine custom flag provided.

  • You should only specify 1 engine as the default
  • If multiple default engines are set, the first one will be used (although JavaScript does not guarantee it)
  • If this option is not set on any engine, the first one in the config will be used (again no guarantee)

Browsers Configuration

To create a browser, use the browser function from the callback's parameter and assign it to a property of the callback's return object:

defineConfig(({ browser }) => ({
  chrome: browser(),
}));

⚠️ The property's key name is important because it is used as a value for the --browser option and as a custom flag.

The browser function is of type CreateBrowserFn:

// not exact representation
type CreateBrowserFn = (config?: Config) => Browser;

There are no required parameters but there is an optional config of the following form:

// not exact representation
interface Config {
  alias?: string | string[];
  isDefault?: boolean;
  profiles?: {
    [key: string]: string | Profile;
  };
}

interface Profile {
  directory: string;
  alias?: string | string[];
  isDefault?: boolean;
}

All Config properties are optional. Let's examine each available option.

  1. alias - a string or array of strings that provides alias names for the browser.
defineConfig(({ browser }) => ({
  chrome: browser({
    alias: "c",
  }),
  firefox: browser({
    alias: ["f", "ff"],
  }),
}));

Defining browser aliases allows you to provide them to the --browser built-in option or use them as custom flags. For example:

web --browser=ff
web --ff
  1. isDefault - defines whether the browser should be used as a default.

Same concept and rules as described in the engines configuration.

  1. profiles - defines browser profiles that can be used.

Some browsers (such as Chrome) have the functionality to create and use multiple browser profiles. When a browser has multiple profiles, it typically keeps the data used by each profile in a directory (folder) stored somewhere on your machine. For example, Chrome stores this information in ~/AppData/Local/Google/Chrome/User Data on a Windows machine (you can google where this data is stored on your OS). Here, you can find profile directories such "Profile 1", "Profile 2", etc. These are the names that you need to assign to the profiles properties.

The value of this option can be one of the following:

  • a string value specifying the name of a profile directory described above.
  • an object value with:
    • at least 1 property called directory that points to a profile directory
    • optional alias and isDefault properties (same concept and rules as above)
defineConfig(({ browser }) => ({
  chrome: browser({
    profiles: {
      work: "Profile 1",
      dev: {
        directory: "Profile 2",
        alias: ["code", "d"],
      },
      personal: {
        directory: "Profile 3",
        alias: "p",
        isDefault: true,
      },
    },
  }),
}));

Defining browser profiles allows you to use its keys as values to the --profile built-in option and as custom flags (excluding 1-letter aliases).

⚠️ Unlike engine and browser aliases, 1-letter profile aliases (such as d in the above example) cannot be used as custom flags.

For example:

web --profile=dev
web --profile=p
web --code

Generating the config file

In order to start using the engines and browsers defined in the previous step, you must generate a config file. What Web CLI uses to customize its behavior is not the config project itself but rather the config file that gets generated based on the project.

To generate the config file, run the following command from the root directory of the project:

npm run config

You can notice that this is just a simple npm script defined in package.json which consists of two other commands that you can run individually:

npm run config:engines
npm run config:browsers

Both commands execute their respective files (src/engines.ts and src/browsers.ts) to set the config engines and browsers.

Again, you can customize or change this part of the project as long as you execute a file (or multiple files) that calls defineConfig.

Please note that only 1 config file gets generated even if you call defineConfig multiple times from different files. Each time the defineConfig function is called, new engines and browsers from its return value are appended to the generated config file.

The location of the generated file depends on your OS:

  • Windows - ~/AppData/Roaming/@lexjs/web-cli.config.json
  • Linux - ~/.config/@lexjs/web-cli.config.json
  • Darwin (MacOS) - ~/Library/Application Support/@lexjs/web-cli.config.json
  • other - ~/@lexjs/web-cli.config.json

Deleting config

To delete the config engines or browsers, you have a couple of options:

  1. Not recommended - Manually going into the generated config file and removing values from there.

  2. Using clearEngines and clearBrowsers functions:

// e.g. src/clear-config.ts
import { clearEngines, clearBrowsers } from "@lexjs/web-cli/config";

clearBrowsers();
clearEngines();

To apply the changes you need to execute the file(s) where these functions are called by employing the same technique used to generate the config file. For example:

npm run config:clear

where config:clear is npx tsx src/clear-config.ts.

Alternatively, you can simply run npx tsx src/clear-config.ts without creating a package.json script.

Built-in Options

browser

Specifies the browser app to open.

⚑ Takes a value.
βš™οΈ Allows configuration.

Options

--browser -b

Usage

web --browser=value

value is one of the following:

  1. Browser app name on your machine, e.g. chrome, firefox, brave, edge, etc.

web --browser=chrome

⚠️ The command will not prevent you from specifying a value that refers to an invalid browser or to another non-browser application on your machine. As far as the program is concerned - any value provided to the browser option is a possible browser app, so it will attempt to open it.

  1. Browser key or alias in the config. For example, chrome, firefox, c, f, or ff

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ browser }) => ({
  chrome: browser({
    alias: "c",
  }),
  firefox: browser({
    alias: ["f", "ff"],
  }),
}));
web --browser=ff

Multiple options

You can specify multiple browsers:

web --browser=value --browser=value ...

Configuration

Setting up browsers configuration allows using

  • browser aliases as the option's value
  • browser keys and aliases as custom flags

profile

Specifies what browser profile to use when opening a new browser tab. Learn more about profiles in the browsers configuration.

⚑ Takes a value.
βš™οΈ Allows configuration.

The option works only if the browser application supports profiles functionality. Otherwise, it will have no effect on the opened web query.

Options

--profile -p

Usage

This option relies on the provided browser option or generated config.

  • If the browser option is not provided, the CLI will use the config's default browser (see how it is determined in browsers configuration).
  • If the browser option is not provided and there is no browser config, the query will not be opened.
web --profile=value

value is one of the following:

  1. Profile directory name. For example Profile 1

web --profile="Profile 1"

For this scenario to work, make sure that you either provide the --browser option or create a config, for example:

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ browser }) => ({
  chrome: browser(),
}));
  1. Property key in the profiles object of the browser config. For example, dev or personal

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ browser }) => ({
  chrome: browser({
    profiles: {
      dev: "Profile 1",
      personal: {
        directory: "Profile 2",
      },
    },
  }),
}));
web --profile=personal
  1. Value of a profile's alias property. For example, d, p, or second

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ browser }) => ({
  chrome: browser({
    profiles: {
      dev: {
        directory: "Profile 1",
        alias: "d",
      },
      personal: {
        directory: "Profile 2",
        alias: ["p", "second"],
      },
    },
  }),
}));
web --profile=p

Multiple options

You can specify multiple profiles:

web --profile=value --profile=value ...

Configuration

Setting up browsers configuration allows using

  • profile keys and aliases as the option's value
  • profile keys and multi-letter aliases as custom flags

engine

Specifies what search engine or website to query.

⚑ Takes a value.
βš™οΈ Allows configuration.

Options

--engine -e

Usage

web --engine=value

value is one of the following:

  1. Engine key or alias in the config. For example, google, npm, duck, or duckduckgo

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ engine }) => ({
  google: engine("google.com", {
    search: "search?q=",
  }),
  npm: engine("npmjs.com", {
    search: "search?q=",
  }),
  duck: engine("duckduckgo.com", {
    search: "?q=",
    delimiter: "+",
    alias: ["duckduckgo"],
  }),
}));
web @lexjs/web-cli --engine=npm

> https://npmjs.com/search?q=@lexjs/web-cli

When supplying URL values to the command, this option overrides the default behavior of opening the URLs. Instead, they are treated as search term keywords for the provided engine. For example:

web github.com --engine=google

> https://google.com/search?q=github.com

  1. An arbitrary URL string like google.com/search?q= or example.com

web @lexjs/web-cli --engine=npmjs.com/search?q=

> https://npmjs.com/search?q=@lexjs/web-cli

⚠️ Non-URL values are not allowed.

When using the option with an arbitrary URL, it behaves in the same way as any other engine from the config, meaning that you can use other options such as --search, --resource, --port, --split, or --http.

Note that since a URL value is a basic string, the CLI will simply append it with whatever keywords are supplied. If the URL has no query string that ends with an equals sign (=), the values will be added after a forward-slash (/), e.g.

web --engine=example.com hello world

> https://example.com/hello%20world

Configuration

To define more engines and websites than the app defaults, use engines configuration.

search

Specifies what search path to use for querying the provided engine. This search path is a URL segment that is appended to the engine's base URL and allows to search that engine with the provided keywords. There could be multiple ways to search a single engine and this option allows to specify it.

⚑ Takes a value.
πŸ› οΈ Requires an --engine option.
πŸ› οΈ Requires keywords.
βš™οΈ Allows configuration.

Options

--search -s

Usage

This option must be used with the --engine option and keywords.

  • If the engine is not specified, validation will fail and the web query will not be performed.
  • If keywords are not provided, only the base URL will be opened (i.e. the search value is not added).
web --search=value --engine=engine <keywords>

value is one of the following:

  1. URL segment string. For example, search?q= or ?q=

web --search=?q= --engine=duckduckgo.com hello world

> https://duckduckgo.com/?q=hello%20world

  1. Search key in the engine's "search" config. For example, main, images, bar, or deep

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ engine }) => ({
  example: engine("example.com", {
    search: {
      main: "search?q=",
      images: "images?q=",
      foo: {
        bar: "foobar?q=",
        baz: {
          deep: "foobaz?q=",
        },
      },
    },
  }),
}));

⚠️ Using keys like foo and baz that do not point to a string value is not valid.

Most of the time when queying an engine, the --search option will not be provided. In these cases, it defaults to either the string value or the main property's value, depending on how the search config is set up.

Multiple options

Supplying multiple --search options will create a separate URL for each value.

Configuration

Setting up engines configuration allows using search keys as the option's value.

resource

Overrides the default behavior of querying an engine by specifying the engine's route to be accessed directly.

⚑ Takes a value.
πŸ› οΈ Requires an --engine option.
βš™οΈ Allows configuration.

Options

--resource -r

Usage

This option must be used with the --engine option.

  • If the engine is not specified, validation will fail and the web query will not be performed.
web --resource=value --engine=engine

value is one of the following:

  1. URL segment string. For example

web --resource=teapot --engine=google.com

> https://google.com/teapot

web --resource=path/to/resource --engine=example.com

> https://example.com/path/to/resource

  1. Resource key in the engine's "resources" config. For example, test, bar, baz or example

import { defineConfig } from "@lexjs/web-cli/config";

defineConfig(({ engine }) => ({
  example: engine("example.com", {
    resources: {
      test: "path/to/resource",
      foo: {
        bar: "?foo=bar",
        baz: "?foo=baz",
      },
      deeply: {
        nested: {
          example: "deeply/nested/example/resource",
        },
      },
    },
  }),
}));

⚠️ Using keys like foo, deeply, or nested that do not point to a string value is not valid.

Command values

When supplying command values, each value is used in a separate web query as a URL path segment after the provided resource.

For example, the following creates 3 distinct web queries:

web typescript react @nestjs/cli --resource=package --engine=npmjs.com

> https://npmjs.com/package/typescript
> https://npmjs.com/package/react
> https://npmjs.com/package/@nestjs/cli

Combining resources

You can combine 2 resources together to create a single web query by using the :: separator. Each resource can be either a key from the engine's resources config or an arbitrary string.

Let's examine each scenario by using the following Github engine config:

defineConfig(({ engine }) => ({
  github: engine("github.com", {
    search: "search?q=",
    resources: {
      profile: "LexBorisoff",
      tabs: {
        repos: "?tab=repositories",
        projects: "?tab=projects",
        stars: "?tab=stars",
      },
    },
  }),
}));

Combining two resource keys

You can generate a URL that accesses a profile's repositories page:

web --resource=profile::repos --engine=github

> https://github.com/LexBorisoff?tab=repositories

Combining a resource key with an arbitrary string

You can generate a URL that accesses a profile's arbitrary repository:

web --resource=profile::web-cli --engine=github

> https://github.com/LexBorisoff/web-cli

Combining an arbitrary string with a resource key

You can generate a URL that accesses a repositories page of an arbitrary profile:

web --resource=username::repos --engine=github

> https://github.com/username?tab=repositories

Combining two arbitrary strings

web --resource=LexBorisoff::web-cli --engine=github

> https://github.com/LexBorisoff/web-cli

This scenario is essentially the same as providing a single resource value with /

web --resource=LexBorisoff/web-cli --engine=github

> https://github.com/LexBorisoff/web-cli

Configuration

Setting up engines configuration allows using resource keys as the option's value.

port

Adds the provided port number to the URL.

⚑ Requires a number value.
❌ No configuration.

Options

--port -:

Usage

web --port=3000 example.com

> https://example.com:3000/

If multiple ports are supplied, each one will create a separate query:

web -: 3000 -: 5000 example.com

> https://example.com:3000/
> https://example.com:5000/

The program recognizes if an engine or a URL already includes a port and checks if it matches the option's value when building the final list of URLs:

web -: 3000 -: 5000 example.com:3000/api/users

> https://example.com:3000/api/users
> https://example.com:5000/api/users

incognito

Opens web queries in a private / incognito mode.

🚩 Flag option - no value is required.
❌ No configuration.

Options

--incognito -i

Usage

web --incognito

split

Creates a separate web query for each value argument.

🚩 Flag option - no value is required.
❌ No configuration.

Options

--split

Usage

web Object Symbol class --engine=mdn --split

> https://developer.mozilla.org/search?q=Object
> https://developer.mozilla.org/search?q=Symbol
> https://developer.mozilla.org/search?q=class

http

Uses the non-secure HTTP protocol when constructing web queries.

🚩 Flag option - no value is required.
❌ No configuration.

Options

--http

Usage

web --http https://google.com

> http://google.com/

test

Prevents opening browser tabs and only displays the output.

🚩 Flag option - no value is required.
❌ No configuration.

Options

--test

Usage

web [values] [options] --test

Custom Flags

When config is set up, certain keys and alias values automatically become flags. You can use these custom flags as substitutes for engine, browser, and profile options.

For example, the following command with value options

web --browser=chrome --profile=dev --engine=mdn

can be re-written using custom flags:

web --chrome --dev --mdn

⚠️ If a custom flag conflicts with an option or its alias, the option takes precedence.

How custom flags are created

The following config items are used to create custom flags:

keys alias values 1-letter alias values
browser βœ… βœ… βœ…
profile βœ… βœ… ❌
engine βœ… βœ… βœ