Join us on discord @ discord.gg/mterm
mterm is a cross-platform command-line terminal that proxies the underlying command-line interpreters, such as powershell, sh or wsl. commands are executed in the background and results streamed to the foreground.
this means commands such as ls
, cd
or program commands such as node -v
or yarn install
will work out of the box as long as the host machine supports these commands. you can configure the desired interpreter below
- by no means does mterm replace your sh, or pwsh but we think abstractions such as secrets, and commands can supplement your development routines
- in other words, instead of building a utility for a dev task in a shell script for local use, use typescript
- mterm comes with tabs but also within the scope of a tab; each command is ran in the background - this means you can use your keyboard to hop around execution stacks
- output for commands do not stay in the terminal when you work on a new command. this new workflow considers the last execution while typing your next - but expects you to be in control of what you want to see (you'll have to see this to understand)
Head over to the release page to find the binary for your system type. mterm is evergreen and updates are automatically installed on your system as hey get released. Run :v
to see your current mterm version.
By default, mterm opens in command mode (you can change this in settings). A couple of notes about command mode -
- This window is always on top
- This window follows to any desktop
- The font and theme is larger to account for large size
This is a nice way to focus on execution details but it can be annoying if multiple windows are in use.
Hide mterm with the default toggle hotkey -
~ + CommandOrControl
Disable command mode and go to normal terminal window mode with -
~ + Shift + CommandOrControl
Or change the behaviour of all of this with settings.
mterm creates the mterm
folder on a host machine on first launch a the user's home directory
for windows -
C:/Users/<YOUR_NAME>/mterm
for mac -
/Users/<YOUR_NAME>/mterm
for everything else -
/home/<YOUR_NAME>/mterm
in this folder, there are a couple of important files to help configure mterm -
commands.ts
, used to attach commands to the terminal. see commandspackage.json
, an npm package declaration for use by commandssettings
, general runtime settings settings
here is an example ~/mterm/settings.json
-
{
"defaultProfile": "wsl",
"profiles": {
"powershell": {
"platform": "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -noprofile -command $ARGS",
"theme": "theme.css",
"icon": "default"
},
"wsl": {
"platform": "bash -c $ARGS",
"theme": "theme.css",
"icon": "default"
}
},
"runner": {
"shortcut": "`+CommandOrControl",
"bounds": {
"screen": "PRIMARY",
"x": "SCREEN:-.5",
"y": "SCREEN:-.5",
"w": 720,
"h": 500
},
"commanderModeShortcut": "`+Shift+CommandOrControl",
"commanderMode": true,
"commanderModeBounds": {
"screen": 0,
"x": 0,
"y": "SCREEN:-.5",
"w": "SCREEN",
"h": 500
}
}
}
- default profile: the desired platform to execute commands against
- profiles: a list of profiles in the terminal
- runner
- shortcut: the global hotkey to toggle the runner
- bounds: the location of the terminal
- screen:
PRIMARY | number
, use the primary monitor or use the desired screen # - x, y, w, h:
SCREEN:ratio | number
use a ratio of the screen size (for centering etc) or use a static number
- screen:
- commandModeShorcut: the hotkey to toggle command mode
- commandMode: should mterm start by default in command mode?
- commanderModeBounds: the location of the terminal in command mode
- screen:
PRIMARY | number
, use the primary monitor or use the desired screen # - x, y, w, h:
SCREEN:ratio | number
use a ratio of the screen size (for centering etc) or use a static number
- screen:
mterm provided a few system commands to help control the terminal and settings. mterm settings will always start with :
(a colon) unless the intention is to override a system command. for example, because clear
needs to be handled in a special way for mterm windows + tabs, it is overriden in mterm.
Command | Alias | Purpose |
---|---|---|
clear |
cls |
Clear the current terminal output |
cd |
Navigate the file tree on the host machine | |
:exit |
exit |
Exit the current tab, or mterm if only 1 tab is open |
:edit |
edit |
Open the in-terminal editor with the file provided. Hit Ctrl+S to save in the editor |
:history |
Print out terminal history for debugging in a JSON format | |
:reload |
Reload settings, the ui, and commands without restarting | |
:tab |
Open a new tab | |
:test |
Sample command that executes after 10 seconds. Helpful for debugging | |
:vault |
Open the secret management tool, the mterm vault | |
:version |
:v |
Print the current mterm version |
:workspace |
Open the mterm workspace folder on disk: ~/mterm |
|
:settings |
Open the mterm settings gui to manage ~/mterm/settings.json |
|
:settings edit |
Open the ~/mterm/settings.json in the terminal editor with hot reloading |
|
:settings reload |
Reload ~/mterm/settings.json and all ui etc associated with the settings |
|
:settings {get|set} {key} |
Set the setting key matching the path in ~/mterm/settings.json and reload |
Need your own command? MTERM includes ~/mterm/commands.ts
from your home directory - with any exported functions as available commands.
Here an example -
import * as os from 'node:os'
export function hello(name: string = os.userInfo().username): string {
return `Hi, ${name}`
}
Now run hello X
from mterm -
In this case, no argument was provided so the
os.userInfo().username
was the fallback.Hello, DR
is the result!
Try fetching data!
export async function query(): Promise<{
userId: number
id: number
title: string
completed: boolean
}> {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
return await response.json()
}
Note the return type is optional, just added above to highlight the typescript engine provided
Sometimes we need to change variables, execution results or perform an operation on strings.
MTERM helps solve this by providing transformers
as terminal operators. These transformers abstract away somewhat tedious actions in the terminal, they also provide common utilities within the scope of a prompt
For the prompt of
":snake(this is some text)"
We get the result
this_is_some_text
snake
is a mterm transformer that takes a string and converts it to snake case
Transformers can be used anywhere including from within transformers -
":upper(hmm) :lower(WOW) :snake(:lower(HMM WOW))"
Prints out -
HMM wow hmm_wow
Some transformers accept arguments. Arguments for transformers are seperated by :
colon characters
Here is the split transformer on a string -
":split(1,2,3,4:1:,)"
1,2,3,4
is the first argument, the split text1
is the index to return (a split operation is an array, so return a value from this array),
the final argument is the delimiter
one way to view this operation is
"1,2,3,4".split(',')[1]
Note you can use "
quotes to wrap transformer arguments if there is a colon within the argument
Here are the provided transformers for use -
print out the argument, proxies the argument to the
echo
on the terminal
:echo
examples -
:echo(HELLO) -> "HELLO"
:echo(:upper(hello)) -> "HELLO"
gets the argument from the vault, if not available gets the argument from the environment variables from the host machine, if not available returns the fallback
:get
examples -
# e.g: Basic find
#
# assuming:
## there is a env variable called PATH=PATH_FROM_SYSTEM
:get(PATH) -> "PATH_FROM_SYSTEM"
# e.g: Fallback keys
#
# assuming:
## there is NOT a env variable called NOT_FOUND_A
## there is NOT a env variable called NOT_FOUND_B
## there is a env variable called FOUND_C=VALUE_OF_C
:get(NOT_FOUND_A,NOT_FOUND_B,FOUND_C) -> "VALUE_OF_C"
# e.g: Fallback variable
#
# assuming:
## there is NOT a env variable called NOT_FOUND_A
## there is a env variable called FOUND_C=VALUE_OF_C
:get(NOT_FOUND_A:im the fallback) -> "im the fallback"
:get(FOUND_C:im the fallback) -> "VALUE_OF_C"
transforms the argument to lowercase
:lower
examples -
":lower(HELLO)" -> "hello"
:echo(:lower(HELLO)) -> "hello"
runs the argument against the terminal and proxies the result
:run
examples -
# e.g: Run command
#
# assuming:
# there is a `hello` function in `commands.ts`
# the `hello` function is declared as const hello = (arg = 'fallback') => `Hello, ${arg}!`
":run(hello)" -> "Hello, fallback!"
":run(hello argument)" -> "Hello, argument!"
# e.g: Run command within transformer
#
# assuming:
# there is a `hello` function in `commands.ts`
# the `hello` function is declared as const hello = (arg = 'fallback') => `Hello, ${arg}!`
":lower(:run(hello))" -> "hello, fallback!"
":lower(:run(hello)) :upper(:run(hello))" -> "hello, fallback! HELLO, FALLBACK!"
transforms the argument to snakecase
:snake
examples -
":snake(HELLO WORLD)" -> "hello_world"
transforms the argument to titlecase
:title
examples -
":title(hello world)" -> "Hello World"
":title(hello_world)" -> "Hello World"
splits the provided argument, accepts the index or uses
0
, accepts the delimiter or uses,
:split
examples -
":split(hello,world)" -> "hello"
":split(hello,world:1)" -> "world"
":split(hello@world:1:@)" -> "world"
:echo(":split(":get(xx,PATH)":0:;)") -> "FIRST_RESULT_IN_PATH"
transforms the argument to uppercase
:title
examples -
":uppercase(hello world)" -> "HELLO WORLD"
Environment variables are a bit unsafe. You set these and leave the host machine all the ability to read and share these. Wonderful for services and backends, not the safest for personal usage.
While mterm
does support reading env variables in the terminal, an alternative much safer secret mechanism is provided.
Passwords, URLS (any value really) can be stored in the vault -
Open the vault wih
:vault
or use the tray icon openVault and Secrets
The mterm vault is an AES-256
encrypted store on your local machine. During setup, you provide a password for this store.
Every time mterm
is launched, the password is required to use these values provided. You can find vault values by using this.vault.get
in commands -
export function who() {
const name = this.vault.get('NAME')
return `name: ${name}`
}
mterm provides an editor with :edit <FILE>
or edit <FILE>
commands -
hit control + s
within the file editor to save this
When you change the tab name to include $idx
- this will be replaced with the current tab index
You can install packages in the ~/mterm
folder and use them in commands.ts
see local setup for code setup info.
ensure editor has prettier settings configured for .pretierrc.yaml
or PRs will fail.
every commit must be in conventional commit format. this is how we auto generate release notes and change logs. features might be ignored if this rule is not followed.
make sure to make a pr with this format: feature/<name_or_issue_number>
.
reach out on discord for contributor role.
note: quickly install yarn on node 20+ with
corepack enable
clone -
git clone [email protected]:mterm-io/mterm.git
install deps -
yarn
run locally -
$ yarn dev
note, because these require github token during build - this will probably fail for you. adding here either way for completeness
# For windows
yarn build:win
# For macOS
yarn build:mac
# For Linux
yarn build:linux