Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,22 @@

![repocard](https://repocard.dannyben.com/svg/opcode.svg)

Opcode lets you define a simple configuration file in any directory.
This file includes shortcuts to other commands.
Opcode lets you define a simple executable command catalog in any directory.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Instead of repeatedly typing or pasting long commands, save them in `op.conf`
and run them by name:

```shell
$ op check
$ op test
$ op deploy
```

Agents can also run a named command catalog like `agent check` or `agent test`,
backed by `agent.op.conf`, without mixing generated helper commands into your
main `op.conf`.

![Demo](/demo/cast.gif)

Expand DownExpand Up@@ -93,30 +107,23 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

op -v, --version
Show version number
```

## Config Selection
Use `op --syntax` for a compact summary of the config file format.

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:
## Named Command Catalogs

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking `op` under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main `op.conf`:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -134,6 +141,13 @@ The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.

This lets agents maintain reusable commands like `agent check`, `agent test`,
or `agent fix-ci` while keeping the human-owned `op.conf` focused.

Use `op --syntax` or `agent --syntax` for a compact summary of the config file
format. Config files can also be selected explicitly with `--config` or
`OPCODE_CONFIG`.

## Multiline Commands

In order to specify multiple commands for a single code, provide the commands
Expand Down
51 changes: 27 additions & 24 deletions doc/op.1
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,11 +10,15 @@
.PD
\f[B]op\f[R] OPTIONS
.SH DESCRIPTION
\f[B]opcode\f[R] lets you define a simple configuration file in any
directory.
\f[B]opcode\f[R] lets you define a simple executable command catalog in
any directory.
.PP
This file includes command shortcuts (\f[I]opcodes\f[R]) that can be
executed by running \f[B]op CODE\f[R].
It works as a lightweight makefile for humans, AI agents, and any
workflow that benefits from short, memorable repo\-local commands.
.PP
Agents can also run a named command catalog like \f[B]agent check\f[R]
or \f[B]agent test\f[R], backed by \f[B]agent.op.conf\f[R], without
mixing generated helper commands into the main \f[B]op.conf\f[R].
.SH OPTIONS
.SS ?, \-\-info, \-i
Show all codes and their usage comments (#?)
Expand All@@ -30,6 +34,8 @@ Open the config file for editing
Append a command to the config file
.SS \-\-config, \-c FILE CODE [ARGS]
Use a specific config file
.SS \-\-syntax
Show config file syntax
.SS \-\-help, \-h
Show help message
.SS \-\-version, \-v
Expand DownExpand Up@@ -69,23 +75,11 @@ You can supply a commit message:
.EX
$ op commit \(dqmy commit message\(dq
.EE
.SS Config Selection
Use \f[CR]\-c, \-\-config\f[R] or \f[CR]OPCODE_CONFIG\f[R] to run
commands from a specific config file:
.IP
.EX
$ op \-c agent.op.conf check
$ op \-\-config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
.EE
.PP
The \f[CR]\-c, \-\-config\f[R] flag must appear before the command code.
Any \f[CR]\-c\f[R] that appears after the command code is passed through
to the command as an argument.
The flag has precedence over \f[CR]OPCODE_CONFIG\f[R].
.PP
You can also create another local command namespace by symlinking
\f[CR]op\f[R] under a different name:
.SS Named Command Catalogs
Opcode can provide separate command namespaces by symlinking
\f[B]op\f[R] under any other executable name.
This is useful for AI agents, automation, or any workflow that should
keep its commands separate from the main \f[B]op.conf\f[R]:
.IP
.EX
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -100,9 +94,18 @@ agent \-> agent.op.conf, agent.conf
.EE
.PP
The \f[CR].op.conf\f[R] file is preferred when both files exist.
A renamed executable does not fall back to \f[CR]opcode\f[R] or
\f[CR]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[CR]op\f[R] namespace.
A renamed executable does not fall back to \f[B]opcode\f[R] or
\f[B]op.conf\f[R]; this keeps separately named catalogs from
accidentally running commands from the main \f[B]op\f[R] namespace.
.PP
This lets agents maintain reusable commands like \f[B]agent check\f[R],
\f[B]agent test\f[R], or \f[B]agent fix\-ci\f[R] while keeping the
human\-owned \f[B]op.conf\f[R] focused.
.PP
Use \f[B]op \-\-syntax\f[R] or \f[B]agent \-\-syntax\f[R] for a compact
summary of the config file format.
Config files can also be selected explicitly with \f[B]\-\-config\f[R]
or \f[B]OPCODE_CONFIG\f[R].
.SS Multiline Commands
In order to specify multiple commands for a single code, provide the
commands indented with one or more spaces immediately under the command
Expand Down
44 changes: 23 additions & 21 deletions doc/op.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,10 +16,14 @@ SYNOPSIS
DESCRIPTION
==================================================

**opcode** lets you define a simple configuration file in any directory.
**opcode** lets you define a simple executable command catalog in any directory.

This file includes command shortcuts (*opcodes*) that can be executed by
running **op CODE**.
It works as a lightweight makefile for humans, AI agents, and any workflow that
benefits from short, memorable repo-local commands.

Agents can also run a named command catalog like **agent check** or
**agent test**, backed by **agent.op.conf**, without mixing generated helper
commands into the main **op.conf**.

OPTIONS
==================================================
Expand All@@ -45,6 +49,9 @@ Append a command to the config file
## --config, -c FILE CODE [ARGS]
Use a specific config file

## --syntax
Show config file syntax

## --help, -h
Show help message

Expand DownExpand Up@@ -89,23 +96,11 @@ You can supply a commit message:
$ op commit "my commit message"
```

### Config Selection
### Named Command Catalogs

Use `-c, --config` or `OPCODE_CONFIG` to run commands from a specific config
file:

```shell
$ op -c agent.op.conf check
$ op --config agent.op.conf check
$ OPCODE_CONFIG=agent.op.conf op check
```

The `-c, --config` flag must appear before the command code. Any `-c` that
appears after the command code is passed through to the command as an argument.
The flag has precedence over `OPCODE_CONFIG`.

You can also create another local command namespace by symlinking `op` under a
different name:
Opcode can provide separate command namespaces by symlinking **op** under any
other executable name. This is useful for AI agents, automation, or any workflow
that should keep its commands separate from the main **op.conf**:

```shell
$ cd /usr/local/bin # or wherever op is installed
Expand All@@ -120,8 +115,15 @@ agent -> agent.op.conf, agent.conf
```

The `.op.conf` file is preferred when both files exist. A renamed executable
does not fall back to `opcode` or `op.conf`; this keeps separately named
catalogs from accidentally running commands from the main `op` namespace.
does not fall back to **opcode** or **op.conf**; this keeps separately named
catalogs from accidentally running commands from the main **op** namespace.

This lets agents maintain reusable commands like **agent check**, **agent test**,
or **agent fix-ci** while keeping the human-owned **op.conf** focused.

Use **op --syntax** or **agent --syntax** for a compact summary of the config
file format. Config files can also be selected explicitly with **--config** or
**OPCODE_CONFIG**.

### Multiline Commands

Expand Down
57 changes: 57 additions & 0 deletions op
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,11 @@ opcode_context() {
printf " Use a specific config file\n\n"
fi

printf " %s --syntax\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show config file syntax\n\n"
fi

printf " %s -h, --help\n" "$PROGRAM_NAME"
if [[ $long_usage == 1 ]]; then
printf " Show this message\n\n"
Expand DownExpand Up@@ -241,6 +246,57 @@ opcode_context() {
cat "$CONFIG_FILE"
}

show_syntax() {
cat <<EOF
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

$PROGRAM_NAME test
$PROGRAM_NAME check

Arguments passed after the code are available to the script as "\$@", "\$1", "\$2", ...

greet: echo "hello \$1"
commit: git commit -am "\$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in \`$PROGRAM_NAME ?\`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in \`$PROGRAM_NAME ?\`:

## Testing

Private commands are hidden from \`$PROGRAM_NAME ?\` and \`$PROGRAM_NAME --list\`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: $PROGRAM_NAME -c FILE CODE
EOF
}

what_command() {
local code="$1"
local script
Expand DownExpand Up@@ -324,6 +380,7 @@ opcode_context() {
-a | --add) add_command "${@:2}" ;;
-h | --help) usage 'long' ;;
-v | --version) echo "$VERSION" ;;
--syntax) show_syntax ;;
--completion) send_completion ;;
*) run_command "$@" ;;
esac
Expand Down
46 changes: 46 additions & 0 deletions test/approvals/op_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
Opcode config syntax

Each command is CODE: SCRIPT

test: npm test
check: shellcheck op setup

Run with:

op test
op check

Arguments passed after the code are available to the script as "$@", "$1", "$2", ...

greet: echo "hello $1"
commit: git commit -am "$@"

Multiline commands are indented below the code:

up:
docker compose build
docker compose up web

Usage comments appear in `op ?`. Put them after their command.
Repeat #? lines for multiline comments:

test: npm test
#? Run tests
#? Use before opening a pull request

Headers appear in `op ?`:

## Testing

Private commands are hidden from `op ?` and `op --list`
after a line containing:

private

Command codes may contain letters, digits, underscores, dots, and dashes.

Config files:

op uses: opcode, op.conf
renamed executable uses: <name>.op.conf, <name>.conf
explicit config: op -c FILE CODE
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
1 change: 1 addition & 0 deletions test/fixtures/empty-dir/approvals/op_add
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,5 +8,6 @@ Usage:
op -e, --edit
op -a, --add CODE COMMAND...
op -c, --config FILE CODE [ARGS]
op --syntax
op -h, --help
op -v, --version
3 changes: 3 additions & 0 deletions test/fixtures/empty-dir/approvals/op_help
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,9 @@ Usage:
op -c, --config FILE CODE [ARGS]
Use a specific config file

op --syntax
Show config file syntax

op -h, --help
Show this message

Expand Down
5 changes: 5 additions & 0 deletions test/syntax_spec.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
source 'approvals.bash'

describe "op --syntax"
approve "op --syntax"
Loading