Local-first command layer
Beton CLI Docs
Beton is a local-first command-line tool for opening apps and URLs, searching the web, saving notes, running timers, reading the clipboard, inspecting the machine, and controlling selected system actions.
Everything runs on your computer. There is no account, server, API key, or cloud storage requirement for core commands. The recommended distribution path is npm install -g beton-cli; the wrapper downloads the matching official source release, creates an isolated Python runtime, and exposes the short beton command on Windows, macOS, and Linux. A direct GitHub source checkout remains available for contributors.
Installation
Install the npm wrapper with one command, then run beton doctor. A GitHub source checkout remains available as an alternative.
Quickstart
Go from zero to your first open, search, note, timer, and diagnostics command.
Command reference
Explore every command, argument, flag, resolution rule, and safety boundary.
Guides & flags
Learn browser selection, dry runs, plain output, storage, aliases, and troubleshooting.
Installation #
Beton requires Python 3.10 or later. The recommended path uses the npm wrapper, which also requires Node.js 18+ and npm. It is not distributed as a PyPI package: do not run pip install beton or pip install beton-cli. The wrapper downloads the official tagged source release and installs it locally into an isolated runtime.
Use npm for the shortest installation. It does not require Git, PowerShell activation, or a permanent execution-policy change. Beton still uses Python 3.10+ for its local backend.
Recommended npm installation #
Install the published npm wrapper from ordinary PowerShell, Command Prompt, macOS Terminal, or Linux shell. The wrapper downloads the official v0.5.0 backend release and creates an isolated runtime in the user data directory.
npm install -g beton-cli
beton doctor
beton --versionNo Activate.ps1, VS Code terminal, or permanent PowerShell execution-policy change is required. If Python is not installed, install Python 3.10+ from python.org, then rerun the npm command.
Prerequisites #
Check that Python and pip are available in the shell where you plan to install Beton.
python --version
python3 --version
pip --versionAlternative: install the published source release #
git clone --branch v0.5.0 --depth 1 https://github.com/itsjustayush/beton-cli.git
cd beton-cli
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
beton doctorpowershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\install.ps1
# Open a new VS Code / PowerShell terminal
beton doctor
beton --versiongit clone --branch v0.5.0 --depth 1 https://github.com/itsjustayush/beton-cli.git
Set-Location beton-cli
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e .
.\.venv\Scripts\beton.exe doctorThe installer uses pip only as the local build installer for the cloned source tree. It does not download Beton from PyPI. It creates a user-level beton command shim in %USERPROFILE%\bin and adds that directory to your user PATH. Open a new terminal after installation. If Git prints a nonfatal annotated-tag warning but exits successfully and switches to a commit, the shallow release checkout succeeded.
Development install #
python -m pip install -e ".[dev]"For a quick checkout without installing an editable package, run the module directly from the repository:
PYTHONPATH=src python -m beton --helpSet BETON_HOME before invoking Beton to isolate tests or keep local data in a directory of your choice.
Quickstart #
Once installed, Beton keeps the everyday workflow intentionally small: see the interface, open something, search, save a note, run a timer, and inspect the environment.
Meet the interface
Run Beton without arguments for the brand screen and examples. Use beton help for an example-driven overview, or append --help to any command for its full option reference.
beton
beton help
beton open --help
beton search --helpOpen an app, URL, file, or folder
Use aliases, direct URLs, filesystem paths, or application names. Prefix with --dry-run when you want to verify resolution before launching anything.
beton open chrome
beton open https://github.com
beton --dry-run open ~/DocumentsSearch the web
Queries are URL-encoded and opened in your configured browser. Choose a search engine or use an explicit browser for private mode.
beton search "python tutorials"
beton search "beton-cli" --engine github
beton search "private query" --browser chrome --incognitoCapture a note
Notes are appended to a local Markdown file with an ISO 8601 timestamp. Add a tag to make entries easier to scan.
beton note "finish project" --tag work
beton today
beton path --kind notesRun a focus timer
Use plain minutes or a unit suffix. The timer occupies the foreground terminal until completion; press Ctrl+C to stop it early.
beton timer 25m --label FocusAdd --dry-run to external actions to see the resolved target, URL, browser, or system action without changing external state.
beton open #
beton open is the universal launcher. Pass a URL, configured alias, filesystem path, or bare application name and Beton resolves it to the appropriate local action.
Syntax #
beton open <target> [--browser BROWSER] [--incognito]
beton --dry-run open <target>The URL, alias name, filesystem path, or application name to open.
Browser for URL targets. Supported values are default, chrome, edge, and firefox. An explicit browser is required for incognito mode.
Open a URL in a private window. It is ignored for application and filesystem targets and rejected when the browser is default.
Target resolution order #
Beton checks the input in order and stops at the first match.
| Order | Target type | Behavior |
|---|---|---|
| 1 | Direct URL | Inputs beginning with http:// or https:// open directly. |
| 2 | Named alias | Case-insensitive aliases use their configured kind and value. |
| 3 | Filesystem path | Existing paths after tilde expansion open with the OS default handler. |
| 4 | Application name | Anything else is treated as an application or executable name. |
Inputs that look like paths but do not exist are rejected rather than guessed. This prevents a typo such as ./reports from silently becoming an application launch.
Examples #
beton open https://github.com
beton open https://github.com --browser chrome
beton open https://github.com --browser firefox --incognito
beton open chrome
beton open youtube
beton open github
beton open ~/Documents
beton open ./report.pdf
beton open /etc/hosts
beton open spotify
beton open code
beton open slackBuilt-in aliases #
| Alias | Kind | Value |
|---|---|---|
chrome | app | chrome |
code | app | code |
spotify | app | spotify |
youtube | url | https://www.youtube.com |
github | url | https://github.com |
figma | url | https://www.figma.com |
beton search #
beton search constructs a properly URL-encoded search URL and opens it in a browser. Defaults come from the command's options or your local configuration.
Syntax and flags #
beton search <query> [--engine ENGINE] [--browser BROWSER] [--incognito]Text to search for. Quote multi-word queries so the shell passes them as one argument.
Search engine: google, bing, duckduckgo, youtube, github, or maps.
Browser: default, chrome, edge, or firefox.
Private browsing mode. Requires an explicit browser other than default.
Examples #
beton search "python tutorials"
beton search "async python" --engine duckduckgo
beton search "react hooks" --engine youtube
beton search "typer library" --engine github
beton search "python typer" --browser chrome
beton search "private query" --browser edge --incognito| Engine | URL pattern |
|---|---|
google | https://www.google.com/search?q={query} |
bing | https://www.bing.com/search?q={query} |
duckduckgo | https://duckduckgo.com/?q={query} |
youtube | https://www.youtube.com/results?search_query={query} |
github | https://github.com/search?q={query} |
maps | https://www.google.com/maps/search/{query} |
--browser default --incognito is rejected because a generic OS handoff cannot guarantee a private window. Name the browser explicitly.
beton note and beton today #
Notes are local, append-only Markdown entries. They are not uploaded or synced by Beton. Use beton today to review entries written on the current date.
Syntax and flags #
beton note <text> [--tag TAG]
beton todayContent to save. Quote multi-word notes. Empty note text is rejected.
A label for project, context, or any categorization scheme you prefer.
Examples and file format #
beton note "finish the project proposal"
beton note "review chapter 3" --tag study
beton note "deploy to staging" --tag work
beton note "buy groceries" --tag personal
beton todayEach entry includes an ISO 8601 timestamp with timezone offset. Tagged entries include the tag inline as a Markdown code span.
- **2024-06-14T09:32:01+05:30** `#work` — deploy to staging
- **2024-06-14T09:35:08+05:30** — finish the project proposalNotes live in notes.md inside the Beton data directory. Run beton path --kind notes to print the exact path.
beton timer #
The timer runs a foreground countdown in the current terminal. It displays progress at the start, every completed minute, and during the final five seconds before announcing completion.
beton timer <duration> [--label LABEL]A plain integer is interpreted as minutes. Suffixes include s/sec/secs, m/min/mins, and h/hr/hrs.
Label displayed during the countdown, useful for naming a Pomodoro block or focus session.
| Format | Example | Meaning |
|---|---|---|
| Plain number | 25 | 25 minutes |
| Minutes | 25m, 25min, 25mins | 25 minutes |
| Seconds | 90s, 90sec, 90secs | 90 seconds |
| Hours | 2h, 2hr, 2hrs | 2 hours |
beton timer 25
beton timer 25m --label "Focus Session"
beton timer 5m --label "Short Break"
beton timer 90s
beton timer 2h --label "Deep Work"
# Preview without waiting
beton --dry-run timer 25The timer occupies the foreground terminal until completion. Press Ctrl+C to cancel it early.
Utility commands #
Utilities inspect the local environment. They are designed to be read-only: they do not modify configuration, write notes, kill processes, or execute destructive actions.
beton clip
clipboardPrint the current text clipboard. Output is capped at 2,000 characters by default.
beton clip
beton clip --full
beton --dry-run clipLinux typically requires xclip or xsel. macOS and Windows use native mechanisms. The --full flag disables truncation.
beton path
storageShow the data directory, config file, or notes file path.
beton path
beton path --kind data
beton path --kind config
beton path --kind notesbeton apps
aliasesList configured application aliases and report whether each executable is detected on PATH. URL aliases are managed separately in configuration.
beton apps
Alias Target Status
chrome google-chrome detected
code code detected
spotify spotify not on PATHbeton find
filesystemFind files below a root directory using a glob pattern. The root defaults to your home directory and results default to 50.
beton find <pattern> [--in ROOT] [--limit N]
beton find "*.pdf"
beton find "*.md" --in ~/Documents
beton find "*.py" --in ~/projects --limit 20Filename or glob pattern. Quote it so the shell does not expand it before Beton receives it.
Directory below which the search runs.
Maximum number of matching paths to display.
beton process
process listingList running processes with optional case-insensitive name filtering. Beton reports processes but never kills or changes them.
beton process [QUERY] [--limit N]
beton process
beton process chrome
beton process python --limit 10Substring filter applied to process names.
Maximum processes to display.
beton doctor
diagnosticsInspect Python, operating system, data directory status, path opener availability, and detected browsers.
beton doctor
beton --plain doctorRun it immediately after installation and again when a feature fails. Missing optional capabilities do not prevent unrelated commands from working.
beton system #
Trigger a selected OS-level session or power action. Beton runs with the launching user's permissions and uses a confirmation prompt for disruptive actions by default.
beton system <action> [--yes]
beton --dry-run system <action>| Action | Effect | Confirmation |
|---|---|---|
lock | Lock the screen or session. | No prompt. |
sleep | Suspend the system. | Required unless --yes. |
logout | End the current user session. | Required unless --yes. |
restart | Reboot the computer. | Required unless --yes. |
shutdown | Power off the computer. | Required unless --yes. |
beton system lock
beton system sleep --yes
beton --dry-run system restart
beton system shutdown --yesUse --dry-run before disruptive actions. Beton does not elevate to administrator or root; permission errors depend on your platform configuration.
beton config #
View or update local JSON configuration. The current CLI supports top-level settings with show and set.
beton config show
beton config set <key> <value>
beton config set browser chrome
beton config set search_engine duckduckgo
beton config set plain true
beton --verbose config set browser firefoxValues of true and false are parsed as booleans. Other values remain strings. Configuration changes are written immediately to the local config file.
The CLI accepts top-level keys defined by Beton, including browser, search_engine, style, and plain. Edit the JSON directly when adding or changing alias entries.
beton help, beton version, and beton --version #
Use help and version metadata to understand the installed CLI. The read-only --version flag prints the current version; version --upgrade refreshes an npm installation through npm or safely upgrades an official source checkout.
beton help
beton --help
beton open --help
beton search --help
beton version
beton --version
# Output example: BETON 0.5.0beton help presents a compact table of core commands and examples. --help shows command-specific arguments and flags. beton version prints the installed version without changing anything. Running beton by itself shows the brand screen; beton beton is not a valid command.
beton version --upgrade #
When Beton was installed with npm, this command updates the global npm wrapper and its isolated Python runtime. When Beton was installed from the official GitHub source checkout, it updates the checkout and refreshes the active Python environment without a manual reinstall:
beton version --upgrade
beton version --upgrade --yes
beton --dry-run version --upgradebeton version --upgrade
beton version --upgrade --yes
beton --dry-run version --upgrade
# No-PATH fallback
.\.venv\Scripts\beton.exe version --upgradeFor npm installations, the upgrade uses npm install --global beton-cli@latest. For source checkouts, it is limited to the official itsjustayush/beton-cli remote on the main branch; it refuses to overwrite uncommitted changes, uses a fast-forward-only pull, asks for confirmation by default, and reinstalls the updated local source into the active Python environment. --dry-run previews the operation; --yes skips the confirmation prompt.
Settings #
Beton stores its settings locally in JSON. You can print them with beton config show and change them with beton config set.
| Key | Default | Accepted values | Purpose |
|---|---|---|---|
browser | default | default, chrome, edge, firefox | Default browser for URL actions. |
search_engine | google | google, bing, duckduckgo, youtube, github, maps | Default engine for searches. |
style | default | Style name | Controls Rich-rendered display style. |
plain | false | true, false | Disables color and decorative Rich formatting. |
beton config set browser firefox
beton config set search_engine duckduckgo
beton config set plain true
beton config showAliases #
Aliases let you assign short names to applications, URLs, and folders. Pass the alias to beton open instead of typing the full target.
| Kind | What it opens | Example value |
|---|---|---|
url | A URL in the configured browser. | https://docs.example.com |
app | An executable resolvable on PATH. | code |
path | A file or folder using the OS default handler. | /home/user/notes |
Alias entries live under the aliases key in config.json. The application aliases are listed by beton apps; URL and path aliases are managed directly in the JSON file.
{
"aliases": {
"docs": { "kind": "url", "value": "https://docs.example.com" },
"notes": { "kind": "path", "value": "/home/user/notes" },
"terminal": { "kind": "app", "value": "wt" }
}
}beton apps
beton open docs
beton open notes
beton open terminalData storage #
Beton is local-first. Its core footprint consists of a configuration file and a Markdown notes file in the platform's standard application-data directory.
| Platform | Default data directory |
|---|---|
| Linux | ~/.config/beton |
| macOS | ~/Library/Application Support/Beton |
| Windows | %APPDATA%\Beton |
| File | Contents |
|---|---|
config.json | Settings and aliases, written by config changes or direct edits. |
notes.md | Timestamped notes appended by beton note. |
beton path
beton path --kind config
beton path --kind notes
BETON_HOME=/tmp/beton-test beton note "isolated test note"
BETON_HOME=/mnt/external/beton beton pathBeton does not upload notes, configuration, or command results. Network access occurs only when you explicitly request a web action such as search or opening a URL.
Browser control #
Choose a browser per command or save a persistent default. Explicit browser selection is required when you want private browsing.
beton search "python docs" --browser chrome
beton search "python docs" --browser edge
beton search "python docs" --browser firefox
beton open https://github.com --browser firefox
beton config set browser chrome| Value | Behavior |
|---|---|
default | Delegates to the operating system's default browser. |
chrome | Directly launches Google Chrome if detected. |
edge | Directly launches Microsoft Edge if detected. |
firefox | Directly launches Mozilla Firefox if detected. |
Use --incognito only with an explicit browser, for example --browser chrome --incognito. It is intentionally unavailable with --browser default.
Dry run #
--dry-run is a global flag placed immediately after beton. It describes an action and exits without opening browsers, writing files, or sending system commands.
beton --dry-run open https://github.com
beton --dry-run search "electrostatics"
beton --dry-run system restart
beton --dry-run timer 25
beton --dry-run clipDry runs are useful for checking URL and alias resolution, verifying configured browser and search engine behavior, inspecting system commands before a restart or shutdown, and testing scripts safely.
| Command group | Dry-run behavior |
|---|---|
| External actions | open, search, system, timer, and clip report what they would do. |
| Read-only commands | today, doctor, and path already have no side effects. |
Plain mode #
Rich formatting is useful in interactive terminals, but scripts, logs, CI runners, and minimal shells often need undecorated text. Use --plain for one invocation or save plain=true permanently.
beton --plain doctor
beton --plain note "meeting notes"
beton --plain today
beton config set plain true
beton config set plain falseThe content stays the same; only panels, colors, icons, and other decorative Rich formatting are removed.
Shell scripts
Capture output without ANSI escape codes leaking into variables or downstream commands.
Log files
Write readable, artifact-free logs for later review.
CI/CD
Keep build-agent output clean and parseable.
Minimal terminals
Maintain legibility in SSH sessions and stripped-down environments.
Global flags #
Global flags appear before the subcommand and affect the invocation consistently.
beton [GLOBAL FLAGS] <command> [command args and flags]| Flag | Purpose | Example |
|---|---|---|
--dry-run | Describe external actions without performing them. | beton --dry-run system sleep |
--plain | Disable Rich formatting. | beton --plain doctor |
--verbose | Show additional execution details, including updated config output. | beton --verbose config set browser chrome |
--version | Print the current version and exit. | beton --version |
--help | Show top-level or command-specific help. | beton search --help |
beton --dry-run --plain search "test query"Global flags must come before the subcommand. For example, use beton --dry-run search "query", not beton search "query" --dry-run.
Troubleshooting #
When in doubt, start with beton doctor. It reports Python, platform, data-directory, path-opener, and browser capabilities in one place.
beton: command not found #
Beton may not be installed in the active virtual environment, or the environment’s script directory may not be on PATH. Beton is installed from the official GitHub source release, not from PyPI.
cd beton-cli
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .
python -m beton --help
# Confirm the installed source version
beton --versionOn Windows PowerShell, activate with \.\.venv\Scripts\Activate.ps1. If you are using a development checkout, replace python -m pip install -e . with python -m pip install -e ".[dev]".
Clipboard access fails #
Linux clipboard access typically needs xclip or xsel. Install one with your package manager, then rerun beton doctor.
sudo apt install xclip
# or
sudo apt install xselBrowser not detected #
Explicit browser values require Beton to locate the browser executable. Run beton doctor, ensure the executable is installed and discoverable on PATH, or use --browser default as a fallback.
--incognito is rejected #
Private mode requires a named browser. Use one of the following forms:
beton search "query" --browser chrome --incognito
beton search "query" --browser firefox --incognito
beton search "query" --browser edge --incognitoSystem action returns permission denied #
Sleep, shutdown, and restart depend on platform permissions. First inspect the command with dry run. Then review your platform's policy configuration rather than routinely running Beton as root.
beton --dry-run system sleep
beton --dry-run system shutdownDiagnostics show missing capabilities #
| Missing capability | Affected feature | Typical fix |
|---|---|---|
clipboard on Linux | beton clip | Install xclip or xsel. |
chrome, firefox, or edge | Explicit --browser | Install the browser and expose its executable on PATH. |
xdg-open on Linux | Opening files and URLs | Install xdg-utils through your package manager. |
Notes do not appear in beton today #
beton today filters by the current date. Check the data directory and timestamps, especially if BETON_HOME differs between terminal sessions.
beton path
printf '%s\n' "$BETON_HOME"beton path
$env:BETON_HOMEOlder notes remain in the Markdown file even though they are not shown by today.