- name=value (one or more) without a command sets variables of the shell
- name=value before a command sets them only in its environment (for
builtins only while they run)
- an assignment needs an unquoted name and =; the value is not split
and not expanded as wildcard or brace pattern, ~ is expanded after =
and :
- the status of an assignment is the one of its last $(...)
- new builtin unset
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- new parser (parser.go) for lists, pipelines, ! and if/elif/else/fi,
for ... in ... do/done, while/until ... do/done; simple commands are
kept as text and expanded when they run (in every iteration)
- break [n], continue [n] and the : builtin
- incomplete input (open control structure, trailing &&, |, quote or
backslash) continues on the next line: prompt "> " in interactive
shells, scripts and startup files read on
- Ctrl+C aborts the whole command line, including loops
- aliases are expanded at the start of every simple command, also inside
control structures
- control structures in pipelines, with redirections or in the
background are reported as not supported
- completion: commands after if, then, do etc.
- main_test.go reformatted with gofmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- $(command) is replaced by the output of command, which runs in a
subshell (gosh -c), so cd/set in it do not change the shell
- trailing newlines are removed; unquoted the output is split into words
at blanks and newlines, "$(...)" stays one word; wildcards in the
output are not expanded
- nested substitutions, quotes and operators inside are handled; the
list, alias and brace scanners skip $(...) as a whole
- a command that consists only of a substitution has its exit status,
Ctrl+C in a substitution aborts the command
- $((...)) is reported as not supported
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- user@host:dir [N] $ after a command failed with exit status N,
the plain prompt again after a successful command
- the status is colored bold red by default, configurable with the new
GOSH_COLORS key error
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- a{b,c}d, nested braces, empty alternatives (file{,.bak})
- sequences {1..5}, {5..1}, {1..10..3}, zero-padded {01..10}, letters
{a..e}
- happens first on the command text, the results go through ~,
variable and wildcard expansion
- quoted/escaped braces, ${...} and braces without comma or valid
sequence are kept; \, protects a comma
- a redirection target must expand to one word (ambiguous redirect),
a word may expand to at most 100000 words
- completion escapes { in file names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Go's syscall.WaitStatus decodes the "continued" status wrongly on BSD:
on FreeBSD it is read as killed by SIGCONT, so after bg the job was
reported as "Exit 147" and removed from the job table while it was
still running (fg: "no such job"); on macOS it is read as stopped.
The shell marks jobs as running itself when it continues them, so wait4
is called without WCONTINUED and only exited/signaled statuses finish a
process.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- alias name=value defines aliases, alias lists or shows them in a form
that can be read back, unalias removes them (unalias -a: all)
- the first word of every command (at the start and after ;, &, &&, ||
and |) is replaced, the value is expanded again except for aliases
that are already being expanded (alias ls='ls --color' works)
- a value ending with a blank makes the next word a command name too
- quoted or escaped words (\ll, 'll') skip the alias
- aliases are only expanded in interactive shells and their startup
files, like in bash
- tab completion includes aliases
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- in an interactive shell every pipeline runs in its own process group
and gets the terminal while it runs in the foreground
- Ctrl+Z stops the foreground job, command & starts a job in the
background; finished and stopped jobs are reported before the prompt
- new builtins jobs, fg, bg and wait (wait also works without job
control, e.g. in scripts, where background jobs read from /dev/null)
- terminal modes are saved and restored when a job stops or continues
- exit and Ctrl+D warn once if there are stopped jobs
- processes are waited for with wait4 (WUNTRACED) instead of exec.Cmd.Wait
- pty based test for job control (Linux)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- login shells (-l or argv[0] starting with -) read /etc/gosh/profile
and ~/.gosh_profile, interactive shells /etc/gosh/goshrc and ~/.goshrc;
--noprofile and --norc skip them
- source file / . file runs a file in the current shell, nesting is
limited to stop files that source themselves
- errors in startup files and scripts are reported with file and line
- ~ and the startup files use $HOME (like sh), the user database is
only the fallback
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- unquoted * ? and [...] (including [!...]) are expanded to the
matching file names, sorted, per path component
- hidden files only match if the pattern starts with a dot, a trailing /
only matches directories, a pattern without match is kept as is
- quoted or escaped characters and values of variables are never
expanded
- redirections to a pattern must match exactly one file
- completion escapes * ? [ and $ in file names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tokenizer recognizes unquoted |, <, >, >>, N>, N>>, N>&M, N<&M,
&> and &>>; only a word of unquoted digits is a file descriptor
- pipelines run concurrently, the status is the one of the last command,
errors of earlier stages are printed
- redirections are applied left to right (fds 0-2), a redirection
without a command creates/truncates the file
- pwd and help can be redirected and piped; cd, set, export, exit and
quit are rejected in pipelines
- syntax errors have exit status 2
- completion: commands after |, ;, && and ||, files after redirections;
operator characters are escaped in completed names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- split input at unquoted ;, && and || and run the commands like sh;
variables are expanded per command when it runs
- $? and ${?} expand to the exit status of the last command,
exit/quit without argument use it
- syntax errors for missing commands around operators (status 2)
- "command not found" message instead of the raw exec error, no more
"exit status N" message when a command fails
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- gosh -c 'command' runs the command and exits, so gosh works as login
shell for ssh host command, scp and rsync
- gosh script runs a script file, lines starting with # are skipped
- without a terminal, commands are read from stdin (byte by byte, so
started commands can read the rest of stdin)
- the exit status is the one of the last command (127 not found,
126 not executable, 128+n killed by signal n)
- -i forces interactive mode, -l/--login is accepted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- add -version flag (besides --version and -V)
- help output includes the version
- commit and branch are set via ldflags by goreleaser; plain go build
falls back to the VCS revision embedded by Go
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without Stdin, commands read from /dev/null, so interactive programs
like 'sudo su -', vim or ssh got EOF right away.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GOSH_COLORS='user=..:root=..:path=..' with ANSI SGR codes,
empty value disables the color for that part
- only digits and ';' are accepted, invalid entries are ignored
- read before every prompt, so 'set GOSH_COLORS=...' takes effect immediately
- document in help and README, including example color schemes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- user@host in bold green (bold red for root), directory in bold blue
- colors are disabled with NO_COLOR, TERM=dumb or when stdout is not a terminal
- parts are sanitized before adding the color codes
- only replace the home directory with ~ on a path boundary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- build static binaries for linux, darwin and freebsd
- create deb and rpm packages that register gosh in /etc/shells
- publish releases to Gitea
- add --version flag, set at build time via ldflags
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>