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
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The release and Nix flake support `x86_64-linux` only. With
[Nix](https://nixos.org/download) and flakes enabled:

```sh
nix run github:nerima-lisp/nshell/v0.6.2
nix run github:nerima-lisp/nshell/v0.6.3
```

At the prompt, enter `string upper hello`. Commands and paths colorize live, and a
Expand Down Expand Up @@ -52,10 +52,17 @@ hard links, and files owned by another user are rejected. A malformed tail is
reported without discarding existing bytes; further appends are refused until
the file is moved aside. `--no-history` disables persistence.

The interactive `agent` builtin proposes commands for review. Every proposal,
including one classified as safe, requires Enter before execution; blocked
commands cannot be approved. The assistant refuses to start if its sidecar
reports tools or MCP servers outside the permitted initialization contract.
See [Use the assistant](docs/src/guide/recipes.md#use-the-assistant) for controls
and session settings.

## Install

```sh
nix profile install github:nerima-lisp/nshell/v0.6.2
nix profile install github:nerima-lisp/nshell/v0.6.3
```

Pin a release tag rather than following the default branch.
Expand Down
32 changes: 16 additions & 16 deletions docs/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ Install [Nix](https://nixos.org/download) and enable its `nix-command` and
`flakes` experimental features before running:

```sh
nix run github:nerima-lisp/nshell/v0.6.2
nix run github:nerima-lisp/nshell/v0.6.3
```

## Install

```sh
nix profile install github:nerima-lisp/nshell/v0.6.2
nix profile install github:nerima-lisp/nshell/v0.6.3
man nshell # the manual page is installed alongside the binary
nshell
```
Expand All @@ -26,34 +26,34 @@ leave the interactive shell.
### Prebuilt Linux bundle

Without Nix, download both assets from the
[v0.6.2 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.2),
[v0.6.3 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.3),
verify the checksum, and extract the bundle. On `x86_64-linux`, with `curl`,
`sha256sum`, and `tar` available, run these commands in an empty directory:

```sh
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.2/nshell-v0.6.2-x86_64-linux.tar.gz
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.2/nshell-v0.6.2-x86_64-linux.tar.gz.sha256
sha256sum --check nshell-v0.6.2-x86_64-linux.tar.gz.sha256
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.3/nshell-v0.6.3-x86_64-linux.tar.gz
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.3/nshell-v0.6.3-x86_64-linux.tar.gz.sha256
sha256sum --check nshell-v0.6.3-x86_64-linux.tar.gz.sha256
```

Proceed only if the checksum command exits successfully and prints
`nshell-v0.6.2-x86_64-linux.tar.gz: OK`:
`nshell-v0.6.3-x86_64-linux.tar.gz: OK`:

```sh
tar -xzf nshell-v0.6.2-x86_64-linux.tar.gz
./nshell-v0.6.2-x86_64-linux/bin/nshell --version
man ./nshell-v0.6.2-x86_64-linux/share/man/man1/nshell.1
./nshell-v0.6.2-x86_64-linux/bin/nshell
tar -xzf nshell-v0.6.3-x86_64-linux.tar.gz
./nshell-v0.6.3-x86_64-linux/bin/nshell --version
man ./nshell-v0.6.3-x86_64-linux/share/man/man1/nshell.1
./nshell-v0.6.3-x86_64-linux/bin/nshell
```

Keep the extracted directory intact: the launcher resolves libraries and
helpers relative to itself. The version output must identify `v0.6.2`.
helpers relative to itself. The version output must identify `v0.6.3`.
Type `exit` to return to your existing shell. To use `nshell` by name in
the examples below, add the extracted `bin` directory to that shell's
`PATH`. For Bash or Zsh, from the download directory:

```sh
export PATH="$PWD/nshell-v0.6.2-x86_64-linux/bin:$PATH"
export PATH="$PWD/nshell-v0.6.3-x86_64-linux/bin:$PATH"
```

This changes only the current terminal session. Alternatively, replace
Expand Down Expand Up @@ -95,14 +95,14 @@ nshell -c 'string upper hello'
### Run a script

```sh
curl --fail --location --output greet.nsh https://raw.githubusercontent.com/nerima-lisp/nshell/v0.6.2/examples/greet.nsh
curl --fail --location --output greet.nsh https://raw.githubusercontent.com/nerima-lisp/nshell/v0.6.3/examples/greet.nsh
nshell greet.nsh World
```

Script files support multiline blocks (functions, `if`/`for`/`while`/`switch`),
comments, and a `#!` shebang; arguments after the script name are available as
`$argv`. See
[`examples/`](https://github.com/nerima-lisp/nshell/tree/v0.6.2/examples) for a
[`examples/`](https://github.com/nerima-lisp/nshell/tree/v0.6.3/examples) for a
runnable sample.

### Command line
Expand Down Expand Up @@ -131,7 +131,7 @@ The Nix build supplies [SBCL](http://www.sbcl.org/), ASDF, and the dependencies.
On `x86_64-linux`, with Git and flake-enabled Nix installed:

```sh
git clone --branch v0.6.2 https://github.com/nerima-lisp/nshell
git clone --branch v0.6.3 https://github.com/nerima-lisp/nshell
cd nshell
nix build
./result/bin/nshell
Expand Down
18 changes: 12 additions & 6 deletions docs/src/guide/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ Start an interactive assistant task from a terminal:
agent "inspect the current job state"
```

The `agent` builtin is interactive-only. Commands classified as safe execute
automatically. Commands requiring confirmation are shown for review and execute
only after Enter; blocked commands are not executed. Review this policy before
starting a task, especially in a directory containing sensitive data.
The `agent` builtin is interactive-only. Every proposed command, including one
classified as safe, is shown for review and executes only after Enter. Blocked
commands are not executed. Approval applies to one proposal, not the rest of
the task. Review each command, especially in a directory containing sensitive
data.

The assistant refuses to start if its sidecar reports tools or MCP servers
outside the permitted initialization contract, even if a later initialization
event reports an acceptable configuration.

Inspect assistant state and configure the session with `ai`:

Expand Down Expand Up @@ -104,8 +109,9 @@ job-control lifecycle checks.
perl -e '$SIG{ALRM}=sub { exit 124 }; alarm 900; exec @ARGV' nix develop -c sbcl --script scripts/coverage.lisp
```

The report is written to `coverage/cover-index.html`. Set `NSHELL_COVERAGE_DIR`
to redirect the output.
The report is written to `$TMPDIR/nshell-coverage/cover-index.html` when `TMPDIR`
is set, otherwise to `coverage/cover-index.html`. Set `NSHELL_COVERAGE_DIR` to
choose the output directory explicitly.

## Performance evidence

Expand Down
26 changes: 14 additions & 12 deletions docs/src/project/public-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@

## Positioning

nshell targets daily interactive use first. v0.6.1 is a development preview,
nshell targets daily interactive use first. v0.6.2 is a development preview,
not a POSIX/fish-compatible script interpreter.

## Capability Matrix

The evidence and statuses below describe the published `v0.6.1` tree, not
The evidence and statuses below describe the published `v0.6.2` tree, not
unreleased changes on the default branch.

| Area | Release bar | Published evidence | Status |
| Area | Capability or policy | Published evidence | Status |
| --- | --- | --- | --- |
| Interactive editor | Live syntax feedback, Emacs bindings, optional vi mode, multiline editing, undo/yank, predictable rendering | input-state, rendering, and PTY integration tests | CI-verified on `x86_64-linux` |
| History and suggestions | Persistent history, reverse search, prefix autosuggestions, handling of multiline entries | history, autosuggest, and E2E editing tests | CI-verified on `x86_64-linux` |
| Completion | Context-aware command/path/flag completion, candidate menu, deterministic cycling and cancellation | completion domain and REPL rendering tests, hierarchical command resolution, curated external command metadata and selective help-text enrichment | Broader command discovery/cache policy and subcommand coverage remain future work |
| Shell language | Functions, control flow, command substitution, expansions, heredocs, here-strings, redirection, pipelines | parser, expansion, source, pipeline, process-substitution, descriptor-duplication, tab-stripping-heredoc, and smoke tests | Tested subset; full POSIX/fish parity is not claimed |
| Process control | Foreground/background jobs, `jobs`/`fg`/`bg`/`disown`, Ctrl-C recovery, terminal restoration; terminal-attached commands have no default timeout, while redirected execution defaults to 3600 seconds and command substitution to 300 seconds | job-control and non-sandboxed PTY integration tests | CI-verified on `x86_64-linux` |
| Distribution | Nix-pinned build, installed man page, release binary smoke, checksummed artifacts | flake build, man page, CI/release workflows, [v0.6.1 release assets](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.1) | Prebuilt `x86_64-linux` binary and SHA-256 checksum published; nixpkgs/Homebrew remain future work |
| Security and operations | Private vulnerability reporting, explicit security scope, validation of secret handling in history/completion/diagnostics | [repository security policy](https://github.com/nerima-lisp/nshell/blob/v0.6.1/SECURITY.md) and [contribution guidelines](contributing.md) | Reporting policy exists; it does not establish a security audit of runtime behavior |
| Process control | Foreground/background jobs, `jobs`/`fg`/`bg`/`disown`, Ctrl-C recovery, terminal restoration; foreground external commands whose standard output is a terminal have no default timeout, while file/pipe output defaults to 3600 seconds and command substitution to 300 seconds | job-control and non-sandboxed PTY integration tests | CI-verified on `x86_64-linux` |
| Distribution | Nix-pinned build, installed man page, release binary smoke, checksummed artifacts | flake build, man page, CI/release workflows, [v0.6.2 release assets](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.2) | Prebuilt `x86_64-linux` binary and SHA-256 checksum published; nixpkgs/Homebrew remain future work |
| Security and operations | Private vulnerability reporting and explicit security scope | [repository security policy](https://github.com/nerima-lisp/nshell/blob/v0.6.2/SECURITY.md) and [contribution guidelines](contributing.md) | Reporting policy exists; it does not establish a security audit of runtime behavior |

The [v0.6.1 CI run](https://github.com/nerima-lisp/nshell/actions/runs/38050042888)
and [release workflow](https://github.com/nerima-lisp/nshell/actions/runs/38052885425)
The [v0.6.2 CI run](https://github.com/nerima-lisp/nshell/actions/runs/38120933504)
and [release workflow](https://github.com/nerima-lisp/nshell/actions/runs/38120952046)
validate the tagged tree. The non-sandboxed
integration job runs the PTY and external-process cases skipped by the Nix
sandbox.

## Release Gates

These are the existing nshell gates, not a production-readiness verdict.
The workflow also requires dependency-suite and extracted-artifact checks;
the older published runs linked above do not establish these newer gates.
The linked v0.6.2 release run includes dependency-suite and extracted-artifact
checks, including the extracted executable's real-PTY gate.

Before a public release can claim the capabilities listed here:

Expand All @@ -51,14 +51,16 @@ Before a public release can claim the capabilities listed here:
GitHub Release notes, and completion metadata when applicable.
6. Open roadmap gaps remain explicit instead of being implied as complete.

The [release workflow](https://github.com/nerima-lisp/nshell/blob/main/.github/workflows/release.yml)
The [v0.6.2 release workflow](https://github.com/nerima-lisp/nshell/blob/v0.6.2/.github/workflows/release.yml)
runs hermetic checks and a non-sandboxed integration job against the same
resolved tagged commit, and only then builds the release assets in a draft.
A maintainer reviews the assets and release notes before publishing the draft.

## Verification outside CI

The current flake declares only `x86_64-linux`. On another host, the Nix
Run these checks from the checkout being verified. To reproduce the historical
release evidence above, use the `v0.6.2` tag. The flake declares only
`x86_64-linux`. On another host, the Nix
checks require an `x86_64-linux` builder. Running the dev shell or PTY suite
also requires an `x86_64-linux` execution environment; a remote builder alone
does not supply that runtime coverage.
Expand Down
21 changes: 10 additions & 11 deletions docs/src/project/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,24 @@ shift, and ternary operators; brace expansion; command substitution
here-strings `<<<`; and function arguments via `$argv` / `$argv[N]`.
This list does not establish that every edge case has been audited.

**Command discovery:** extend help-text-driven discovery beyond the static
command catalog to additional commands and subcommands. See the
**Command discovery:** expand the existing command catalog and selective
help-text enrichment to additional commands and subcommands. See the
[completion model](../guide/concepts.md#completion-is-a-knowledge-base-not-a-table).

**Distribution:** evaluate nixpkgs and Homebrew packaging. Neither channel
is published; a packaging target has not been selected. A prebuilt
`x86_64-linux` bundle is available for v0.6.1; see the
[installation instructions](../getting-started.md#prebuilt-linux-bundle).
`x86_64-linux` bundle is available in the
[v0.6.2 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.2).
See the [installation instructions](../getting-started.md#prebuilt-linux-bundle)
for the current distribution.

## Release evidence

The [v0.6.1 Linux CI run](https://github.com/nerima-lisp/nshell/actions/runs/38050042888)
and [release workflow](https://github.com/nerima-lisp/nshell/actions/runs/38052885425)
The [v0.6.2 Linux CI run](https://github.com/nerima-lisp/nshell/actions/runs/38120933504)
and [release workflow](https://github.com/nerima-lisp/nshell/actions/runs/38120952046)
validate the tagged tree. The published
[v0.6.1 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.1)
[v0.6.2 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.2)
contains the x86_64-linux bundle and SHA-256 checksum. The non-sandboxed
integration suite covers foreground external commands and pipelines with
`Ctrl-Z` suspension, `bg` resumption, `fg` terminal handoff, and `Ctrl-C`
interruption. This does not establish compatibility with every terminal; see
[Release readiness](public-readiness.md).

[GitHub Releases](https://github.com/nerima-lisp/nshell/releases).
interruption.
16 changes: 15 additions & 1 deletion man/nshell.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH NSHELL 1 "2026-09-30" "nshell 0.6.2" "User Commands"
.TH NSHELL 1 "2026-09-30" "nshell 0.6.3" "User Commands"
.SH NAME
nshell \- a fish-inspired interactive shell written in Common Lisp
.SH SYNOPSIS
Expand Down Expand Up @@ -233,6 +233,20 @@ provides the following builtins:
Run
.B help
inside the shell for details.
.SH ASSISTANT
The
.B agent
builtin is interactive-only. Every proposed command, including one classified
as safe, requires
.B Enter
before execution. Blocked commands cannot be approved.
.PP
The assistant refuses to start if its sidecar reports tools or MCP servers
outside the permitted initialization contract. Use
.B ai status
to inspect assistant state and
.B ai set
to change session settings.
.SH HISTORY FILE
.I ~/.nshell_history
is created with owner-only permissions. Symlinks, hard links, nonregular files,
Expand Down
8 changes: 4 additions & 4 deletions nshell.asd
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
:license "MIT"
;; Single source of truth for the version. flake.nix reads this form
;; line-by-line, and release.yml refuses a tag that disagrees with it.
:version "0.6.2"
:version "0.6.3"
:homepage "https://github.com/nerima-lisp/nshell"
:bug-tracker "https://github.com/nerima-lisp/nshell/issues"
:source-control (:git "https://github.com/nerima-lisp/nshell.git")
Expand Down Expand Up @@ -403,7 +403,7 @@
:in-order-to ((test-op (test-op "nshell/test"))))

(asdf:defsystem "nshell/test"
:version "0.6.2"
:version "0.6.3"
:author "takeokunn <bararararatty@gmail.com>"
:maintainer "takeokunn <bararararatty@gmail.com>"
:license "MIT"
Expand Down Expand Up @@ -590,7 +590,7 @@
(error "cl-weave tests failed"))))

(asdf:defsystem "nshell/weave"
:version "0.6.2"
:version "0.6.3"
:author "takeokunn <bararararatty@gmail.com>"
:maintainer "takeokunn <bararararatty@gmail.com>"
:license "MIT"
Expand Down Expand Up @@ -620,7 +620,7 @@ primary suite in nshell/test."
:reporter :spec)
(error "cl-weave suite failed"))))
(asdf:defsystem "nshell/benchmark"
:version "0.6.2"
:version "0.6.3"
:author "takeokunn <bararararatty@gmail.com>"
:maintainer "takeokunn <bararararatty@gmail.com>"
:license "MIT"
Expand Down
27 changes: 21 additions & 6 deletions src/application/command-substitution.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,31 @@
((char= ch #\)) (decf depth)
(when (zerop depth) (return (1+ index))))))))

(defun %command-substitution-source-text (value)
;; Re-parsing must retain escape syntax, while data tokens decode only once.
(with-output-to-string (out)
(loop for character across value
for code = (char-code character)
do (when (and nshell.domain.expansion::*fragment-escape-context*
(<= +command-fragment-escape-base+ code
(1- +command-fragment-escape-limit+)))
(write-char #\\ out))
(write-char (nshell.domain.expansion::%decode-fragment-character character) out))))

(defun %command-sub-fields-at (context value open-paren &optional preserve-newlines-p)
"Run the command substitution at OPEN-PAREN, if balanced and non-empty."
(let ((end (nshell.domain.parsing:%balanced-substitution-end value open-paren)))
(when (and end (> end (1+ open-paren)))
(values (if preserve-newlines-p
(%execute-command-substitution-output
context (subseq value (1+ open-paren) end))
(%execute-command-substitution-fields
context (subseq value (1+ open-paren) end)))
(1+ end)))))
(let* ((text (%command-substitution-source-text (subseq value (1+ open-paren) end)))
(replacement
(let ((nshell.domain.expansion::*fragment-escape-context* nil))
(if preserve-newlines-p
(%execute-command-substitution-output context text)
(%execute-command-substitution-fields context text)))))
(values (if preserve-newlines-p
(nshell.domain.expansion::%encode-fragment-data replacement)
(mapcar #'nshell.domain.expansion::%encode-fragment-data replacement))
(1+ end))))))

(defun %expand-arithmetic-command-substitution-at (value pos parts len)
(when (and (char= (char value pos) #\$)
Expand Down
Loading
Loading