Product · Open Source · Developer Tool
Buttons
Project commands, visible and one click away
Most projects already have a command interface. It is scattered across package.json, Make targets, Composer scripts, justfile recipes, Cargo and Go commands, shell scripts, Python entry files, and the setup notes nobody rereads. Buttons makes that interface visible inside VS Code and VSCodium without replacing the files that already define it.
The extension scans a workspace, turns discovered scripts into a command catalogue, and lets the user choose which ones become persistent buttons. Every command remains readable, copyable, and explicit. The result is a practical control surface for a project rather than another task runner to maintain.
Generate deliberately, then keep choices stable
Opening a repository does not write anything. The first Generate action creates .buttons.json and seeds it with the scripts found in the workspace. After that, Rescan reconciles the existing file: included scripts and notes stay included, removed scripts are marked unavailable, commands are recomputed when their source changes, and newly discovered scripts wait for the user to opt in.
That distinction protects the file from becoming disposable generated output. Teams can review it, remove noisy scripts, add context, and commit it as an intentional map of common operations.
Custom commands use the same surface without pretending to come from a script file. A deployment check, container command, diagnostic request, or project-specific helper can be added with a note and stored verbatim. A separate ~/.buttons.json profile holds personal commands that should follow the developer between workspaces rather than enter project source control.
A scanner that understands where commands run
Buttons can scan:
package.jsonscripts;Makefiletargets;- PHP
composer.jsonscripts; justfilerecipes;- Rust
Cargo.tomland Gogo.modcommands; - shell scripts and Python entry files.
Nested packages are first-class. Package roots can be added as scan directories and made recursive, and when a script comes from apps/web/package.json, the command runs with apps/web as its working directory. Lockfiles select the appropriate Node runner, so the same script becomes pnpm dev, yarn test, bun dev, or npm run build according to the repository rather than a global preference.
Installed dependencies, VCS metadata, editor state, coverage, build output, and other generated directories are excluded. Detected virtual environments are the one exception, surfacing as their own action buttons rather than scanned scripts. The scanner is looking for the project's own command surfaces, not every manifest somewhere below the root.
One command model, two useful views
The Activity Bar view keeps Buttons close while code remains the main focus. The editor-panel view opens the same data in a wider table when a project has many commands or longer notes. Both views stay synchronized and expose the same core actions:
- run in the current or dedicated Buttons terminal;
- open a fresh named terminal;
- hand the command to the OS terminal, already typed and waiting for Enter;
- copy the exact command;
- edit a custom command or attach a note;
- remove a button without deleting its source script.
Any button can grow variants, so pnpm dev gains an args variant like pnpm dev --include app1 app2 while the source script stays untouched. The launcher can also assemble a line directly: plus appends to whatever the terminal is already on, and the newline control starts a fresh line.
The Project scripts tab is the catalogue and selection surface. The Buttons tab is the launcher. This separation keeps discovery from crowding the commands a team actually uses.
Configuration that remains inspectable
Project and global profiles are ordinary JSON. Script entries retain the source filename, script name, package directory, detected package manager, and optional note. Because they are references rather than frozen strings, a rescan can update pnpm to bun or refresh a moved package without overwriting custom commands.
The panel also supports compact and expanded text sizes, and script-source types can be enabled independently. Disabling a source stops offering newly discovered entries from that file type; it does not silently remove buttons already selected.
One header action copies the Buttons AI skill to the clipboard or writes BUTTONS-SKILL.md into the workspace, so a coding agent can generate and maintain .buttons.json on its own.
Install where you work
Buttons is available from the VS Code Marketplace and Open VSX. The project website at buttons.curbsoftware.com is the central product destination, while the GitHub repository contains source, issues, documentation, and local build instructions.
Explicit commands are a feature
Buttons runs commands exactly as written. A shared .buttons.json deserves the same review as a Makefile, shell script, or package script before anyone executes it. The extension does not add a hidden policy layer or claim that a command is safe because it has a friendly label.
The point is to make a project's operational knowledge easy to find without making it opaque. Buttons is free and open-source software released under the MIT License.
The story
- The problem
- Monorepos are where this started. Every package brings its own scripts, and none of them stay in your head. The same commands get retyped all day, the dev server, the tests for one app, the deploy for the package that changed. Buttons exists to remember what its author did not want to.
What it does
- Scans Node, Make, Composer, justfile, Rust, Go, shell, and Python commands across monorepos
- Detects the correct package manager and package working directory
- Keeps project and global command profiles in readable JSON
- Runs, copies, sends to the OS terminal, and grows commands into variants