Tour Repository Mailing list Issues

This page document changes on each release.

awwan v0.10.0 (2023-12-16)

In this release we add two new commands to awwan CLI: "env-set" and "env-get", the command to set and get value from awwan environment.

We command "serve" now have optional parameter "-address".

New features

internal/cmd: add flag "address" for command www-awwan

This is to allow using different address when running on local, without conflict with "serve-www" task in Makefile.

all: implement command "env-get" to get value from environment files

The env-get command get the value from environment files. Syntax,

<key> [dir]

The "key" argument define the key where value is stored in environment using "section:sub:name" format. The "dir" argument is optional, its define the directory where environment files will be loaded, recursively, from BaseDir to dir. If its empty default to the current directory.

all: implement command to set environment value with "env-set"

The env-set command set the value of environment file. Syntax,

<key> <value> <file>

The "key" argument define the key to be set using "section:sub:name" format. The "value" argument define the value key. The "file" argument define path to environment file.

For example, to set the value for "name" under section "host" to "myhost" in file "awwan.env" run

$ awwan env-set host::name myhost awwan.env

To set the value for key "pass" under section "user" subsection "database" to value "s3cret" in file "awwan.env" run

$ awwan env-set user:database:pass s3cret awwan.env
_wui: implement Encrypt

In the right side of Save button we now have a button Encrypt that allow user to Encrypt opened file.

This require the workspace has been setup with private key (.ssh/awwan.key) and pass file (.ssh/awwan.pass).

_wui: implement Decrypt

In the right side of Save button we now have a button Decrypt that allow user to Decrypt file with ".vault" extension only.

This require the workspace has been setup with private key (.ssh/awwan.key) and pass file (.ssh/awwan.pass).

Breaking changes

all: make the magic line "#local" works on "local" command too

In case we have a script that manage local host and remote server, calling "play" on "#local" lines only always open the connection to remote server.

To minimize opening unused connections, let the "#local" command works on both commands. Its up to user which part of lines that they want to execute on remote or local.

_wui: use CTRL+Enter to trigger save instead of CTRL+s on editor

Using CTRL+s sometimes cause pressing s only trigger the save, due to fast typing (or keyboard error?).

Bug fixes

all: close the SSH connection once Play finished

Previously, we used to run awwan as CLI so each connection is open and closed once the command completed. Since we now use awwan WUI frequently, any command that execute Play does not close the session immediately once finished. This cause many connections open in remote server.

This changes close the SSH connections immediately once the Play command finished.

all: fix memfs excludes regex

Previously, the regex does not contains "^" and "$" which makes file like "" considered as ".tar" file and being excluded.

_wui: update editor component


  • fix paste that always end with newline

  • fix editor content that got wrapped due to width

  • update layout without using float

  • replace execCommand with Selection

all: fix excludes on HTTP server related to .git

The HTTP server should excludes ".git" directory only, not the other files, like ".gitignore" or ".gitconfig".

all: always load SSH config when running Play

In case awwan run with "serve" and we modify the ".ssh/config", the changes does not detected by awwan because we only read ".ssh/config" once we Awwan instance created.

This changes fix this issue by always loading SSH config every time the Play method executed so the user CLI and WUI has the same experiences.


all: reduce the response on HTTP endpoint on GET fs

Previously, the HTTP endpoint for "GET /awwan/api/fs" return the content of files when the requested node is a directory. This is cause unnecessary load because when requesting directory we only need list of file names not the content.

This changes reduce the response by returning only list of node child without its content, which require update on share module on [Node.JSON].

_wui: use the output for displaying notification

Previously, we use a quick "pop-up" to display notification for each information or error from WUI. Sometimes this is annoying, it overlap the buttons, make it hard to Save and Encrypt at the same time.

In this changes we move the nofication message to be displayed in the output, same with output of execution.

all: use the same date format between log and mlog package

In this way, the date-time output from log.Xxx and mlog.Xxx are consistent.

all: remove duplicate errors logged on Copy, Put, and SudoCopy

While at it, replace all call of [log.Printf] with [Request.mlog] so error both written to stderr and to [Request.Output].

_wui: do not clear output when executing another command

This allow user to see the output of previous command without opening the log file.

_wui: store and load the vfs width in local storage

This is allow user to resize vfs width in one window and when new window is opened the vfs width is restored with the same size.

_wui: disable button "Local" and "Play" when clicked

Once the execution completed, both buttons will be enabled again. While at it, add an icon to show the execution status.

_wui: rename "Remote" to "Play"

This is to make command between the CLI and WUI consistent.

all: refactoring HTTP endpoint for Execute

Previously, the Execute endpoint wait for command execution to finish. In case the command takes longer than proxy or server write timeout, it will return with a timeout error to client.

In this changes, we generate an execution ID for each request and return it immediately.

The new API "GET /awwan/api/execute/tail" implement Server-sent events, accept the execution ID from "/awwan/api/execute".

Once called with valid ID, it will streaming the command output to client.

By using this new API, the WUI can receive the output of command immediately without waiting for all commands to be completed.

_wui: add vertical resizer, to resize between VFS and editor
_wui: allow all content type but decrease max file size to 1 MB

Previously, only file with type json, message, octet-stream, script, text, or XML that can be opened by editor. In this changes we allow all files as long as the size is less than 1 MB.

_wui: update vfs component

This changes allow user browse the crumb in path and item in the list using tab key. While at it, fix the layout to make VFS and editor aligned.

_wui: implement file filter

This changes move the text input for creating new file above the list.

Filling the text field will filter the list based on the node name using regular expression.

Another changes is for node with type directory now suffixed with "/".

awwan v0.9.0 (2023-11-11)

Awwan now have a website at

New features

all: implement remote "#get!" and "#put!" with owner and mode

The magic command "#get" and "#put" now have an inline options to set the owner and permission of copied file. Example of usage are,

#get:$USER:$GROUP+$PERM src dst
#put!$USER:$GROUP+$PERM src dst

The $USER, $GROUP and $PERM are optionals.

If $USER and/or $GROUP is set, a copied file will have owner set to user $USER and/or group to $GROUP. If $PERM is set, a copied file will have the mode permission set to $MODE.

all: add magic command "#local"

The magic command "#local" define the command to be executed using shell in local environment. Its have effect and can only be used in script that executed using "play". In script that is executed using "local" it does nothing.

_www: replace button "Clear selection" with text input for line range

Instead of using mouse to select which lines to be executed, let user input it manually like in the CLI.

all: log all execution into file

For each script execution, a file suffixed with ".log" will be created in the same directory with the same name as script file. For example, if the script is path is "a/b/c.aww" then the log file would named "a/b/c.aww.log".

This is to provides history and audit in the future.

cmd/awwan: add option "-address" to command serve

The "-address" option allow defining the HTTP server address to serve the web-user interface.

Bug fixes

all: trim spaces in passphrase when its read from file

Using vim, or UNIX in general, the file always end with "\n". If we read the whole file then the passphrase will end with it, this cause the decryption may fail (or wrong encryption passphrase used).

_www: fix saving file content using CTRL+s

The issue is using "this.editorOnSave" result on undefined "this" inside the editorOnSave.

all: remove the node when requested from HTTP API /awwan/api/fs

Previously, the HTTP API for deleting node only remove the file but not the node in the memfs.

This changes remove the child node from memfs, so the next refresh on directory will not contains the removed file.

all: return the error as reponse in HTTP API execute

Previously, when the command execution failed, we check the error and return it as HTTP status code 500. In this way, user cannot view the log and actual error.

In this changes, if the command failed, we store the error in separate field "Error" and return to the caller with HTTP status code 200.


all: fix printing the statement to be executed

This fix missing magic command not printed in stdout.

all: use "mlog.MultiLogger" to log Request output and error

By using "mlog.MultiLogger" every output or error can be written to stdout/stderr and additional log writer that can collect both of them, buffered and returned to the caller.

This changes simplify the HttpResponse to use only single output that combine both stdout and stderr.

_www: add button to resize editor and output

The button can be dragged up and down to resize both the editor and output panes.

_www: show confirmation when user open other file with unsaved changes

If user modify the current file without saving it and then open another file, it will show confirmation dialog to continue opening file or cancel it.

all: on file save, make sure file end with line-feed

On some application, like haproxy configuration, line-feed (LF or "n") are required, otherwise the application would not start.

script: respect spaces when joining multi lines command

If a multi lines command does not have spaces or have multiple spaces, join them as is. For example,


should return the value as ab, while

a \\

should return "a<space><space>b".

_wui: various enhancements


  • The "File" tag now highlighted to distinguish with file name

  • The "Execute" action moved to replace the Output, so we have some additional horizontal space

  • The "Output" tag removed

  • Fix layout on mobile devices where height is set to static

  • editor: re-render content after save

  • editor: handle paste event manually

awwan v0.8.0 (2023-10-04)

This release add support for encryption, with two new commands "encrypt" and "decrypt" for encrypting and decrypting file with RSA private key.

The awwan command also can read encrypted environment file with the name ".awwan.env.vault", so any secret variables can stored there and the script that contains '{{.Val "…​"}}' works as usual.

Any magic put "#put" also can copy encrypted file without any changes, as long as the source file with ".vault" extension exist.

For environment where awwan need to be operated automatically, for example in build system, awwan can read the private key’s passphrase automatically from the file ".ssh/awwan.pass".

Bug fixes

all: do not expand environment during parseScript

Environment variables in the script may only expanded by shell on remote not always on local.

all: fix #require does not get executed on the same start position

Previously, executing "local" or "play" command start from line "#require" will not run the "#require" on that line. This changes fix it.

_www: fix execute request that still use "begin_at" and "end_at"

While at it, reformat the TypeScript files using prettier v3.0.3.


all: make .Vars, .Val, and .Vals panic if values is empty

This is to prevent copying or executing command with value that are not defined or typo which make the result empty and may result in undefined behaviour.

For example if we have "app_dir =" with empty variable and command in the script that remove that directory recursively,

sudo rm -r {{.Val "::app_dir"}}/bin

will result removing "/bin" entirely.

all: print any path relative to base directory

This is to minimize log length in stdout and stderr, which make it more readable.

all: move field bufout and buferr out of httpServer struct

Those fields are used on each HTTP request to /awwan/api/execute, which make them not safe if two or more requests processed at the same time.

awwan v0.7.0 (2023-05-14)

Breaking changes

all: changes the line number arguments for "local" and "play" command

Previously, the "local" and "play" command only accept two kind of arguments: one argument for executing single line or two arguments for executing line range. There are no options to executing multiple single line, multiple line range, or combination of them.

This changes make the both commands accept list of lines or line range where each separated by comma. For example, to execute multiple, different single lines

awwan local 4,8,12

To execute multiple line range,

awwan local 4-8,12-16

Or to execute multiple lines and line range,

awwan local 4,8,10-12


all: convert README from Asciidoc to Markdown

I use two remote repositories: GitHub and SourceHut. GitHub support rendering README using asciidoc while SourceHut not. This cause the repository that use README.adoc rendered as text in SourceHut which make the repository page less readable.

Also, the now render README but only support Markdown.

Since we cannot control the SourceHut and, the only option is to support converting Markdown in ciigo so I can write README using Markdown and the rest of documentation using Asciidoc.

all: move code for development to package internal
all: add configuration for golangci-lint

With configuration we can enable or disable specific linters and customize it without touching the Makefile.

While at it, enable linter presets for bugs, comment, metalinter, module, performance, unused and fix the reported issues.

all: move _doc to directory _www

Previously, the /_www/doc is a symlink to /_adoc. To minimize symlinks in this repository, we replace the _www/doc with its actual directory.

While at it, move CHANGELOG.adoc to root directory for better view ability.

go.mod: set the Go module version to 1.19

The Go 1.18 has been archived and not maintained anymore.

awwan v0.6.2 (2023-03-03)

This release set minimum Go to 1.18 and update all dependencies.


all: fix the git clone URL in README

The clone URL should be in https scheme to make works for non-authenticated user.

all: restructure the documents


  • Store all documents into directory _doc. This changes make the directory doc inside _www become symlinks.

  • Move CHANGELOG.adoc to _doc

  • Rename README.adoc to README so it can be rendered on, and make it symlink so it can still rendered as AsciiDoc on GitHub.

  • Add To-do to _doc/index.adoc that was previously uncommitted as NOTEs

awwan v0.6.1 (2022-08-06)

This release fix the build process due to unused dependencies, private submodules URL, and missing directory; which is not caught when running on local.


all: remove calling tsc when building main.js

The main.js already build with esbuild.

all: add empty .ssh directory to allow running build command
all: changes the submodule wui to use https schema

Using git schema will fail on user that does not have SSH key in

_AUR: add package script for Arch Linux user
all: update the README with the latest implementation

This include updating the license to GPL v3.0.

all: watch and convert .adoc files during development
all: convert the adoc during build and serve
all: realign some structs to minimize memory usage

awwan v0.6.0 (2022-07-04)

This release set minimum Go version to 1.17.

Bug fix

all: fix the #get! statement when executing on local

Since fa94025f8e, we change the local statement to be executed using "/bin/sh", "-c", "<statement>". This cause the #get! command failed to execute because

  • we try to read the input file without permission, and

  • we did not set the raw statement required by ExecLocal.


cmd/awwan: make the "help" and "version" as command

Previously, to print the help and version we use the flag package, "-h" for printing usage and "-v" for printing "version".

The flag should be used to changes the behaviour of command not terminating the command. Using and mixing flag as command make the CLI API to be inconsistent.

For example, the following argument is inconsistent,

$ awwan -h play script.aww 1 -

Instead of executing script.aww, it print the usage and terminate.


all: changes the way to build JavaScript using esbuild

Previously, we build the JavaScript files on directory _www by using TypeScript compiler (tsc).

This changes replace the tsc with esbuild, a Go module that provide API to convert TypeScript to JavaScript, and use tsc for type checking only.

awwan v0.5.0 (2022-03-14)

This release re-lincesing the awwan software under GPL 3.0 or later.

See for more information.

awwan 0.4.0 (2022.02.05)

This release bring new command "serve" to awwan. The serve command run HTTP server that provide web-user interface to create, edit, save, and execute script.

New features

all: implement HTTP API and function to Save file on web-user interface

The web-user interface now have button "Save" that save the edited content of file to storage.

all: implement serve command

The serve command will run a HTTP server that provide web-user interface to edit and execute script.

Currently, the web-user interface provide the following features,

  • Browsing the workspace

  • Running the script on local or remote


all: make the local statement executed with "/bin/sh -c …​"

By using "sh -c", the statement can contains environment variable, piping, and other shell commands that cannot be supported if executed directly using native os.Exec.

all: expand the environment on statement when executing local script

This changes replace the string ${x} or $x in the statements with the current environment variables values.

For example, statement "mkdir ${HOME}/tmp" will expand the ${HOME} to the current user home directory.

all: use native SFTP to put and get file when possible

Previously, the command to put and get file from remote server depends on installed scp program on the host computer.

In this changes we add the SFTP client and use it as primary function to put and get file to/from remote when possible and use the scp as fallback.

awwan 0.3.0 (2021.06.09)

go.mod: set the minimum Go to 1.16 and update to share module v0.25.1


cmd/awwan: print the awwan version on command usage output
all: check and return an error if start index is out of range
all: log error when executing script (local or play)
all: do not load SSH config if command mode is "local"

If the mode is local there is no need to parse and load the SSH config, since the command to be executed will run on local machine anyway.

all: set base dir based on the first .ssh directory that we found

Previously, the base directory is set on current working directory. This limit the way to execute awwan only from the directory that contains the .ssh directory.

This changes set the environment BaseDir based on the first .ssh directory that we found from script path up to the "/". So, user can execute awwan script from any sub-directories.

awwan 0.2.1 (2021.01.18)

Update the share modules which bring fixes to "#put" commands.

awwan 0.2.0 (2020.07.05)

New features

environment: export the SSH key, user, host, and port

By knowing this values, user can use it to invoke other SSH related command, for example to copy file using scp

scp -i {{.SSHKey}} src {{.SSHUser}}@{{.SSHHost}}:{{.SSHPort}}/dst
all: add magic command "#require:"

Magic word #require: will ensure that the next statement will always executed when its skipped with start number. For example, given following script with line number

1: #require:
2: echo a
3: echo b
4: #require:
5: echo c

executing awwan local script.aww 3, will always execute line number 2 echo a, but not line number 5 (because its before line start 3).

Bug fixes

command: change the owner of file when doing #get!

In case the owner of file is not active user and it does not have read permission, the "#get!" command will fail when copying command from remote to local.

command: fix magic copy and get command on templates


command: merge sequences of spaces on command into single space
command: check for single, double, or back quote on command

Previously, if command contains quote like,

echo "a b"

the script will run it as ["echo", "a, b"] which is not what we will expected and may cause some command failed to run.

This changes fix the parsing of command string by detecting possible quote.

awwan 0.1.0 (2020.05.30)

Its better late than never.

The first release works for everyday use. The local, play command works as it is, and its has been used for deploying and managing postfix, dovecot, haproxy, and my personal server and services at Also it has been used to deploy Go microservices using Kubernetes using combination of gcloud and kubectl.