Native Shell
Native Shell은 모든 플랫폼의 앱 안에서 만들어지는 AI UI입니다
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A batteries-included scripting runtime in one static binary: download it, run your script.
chirp is Janet, a small, fast Lisp, built together with what real scripts reach for: an HTTPS client and server, JSON, SQLite with full-text search, TOML, YAML, compression, subprocesses, argument parsing, regexes and Markdown. There is one file per platform (Linux x64 and arm64, macOS arm64, Windows x64). It is static, and needs no runtime, package manager or C compiler.
chirp is an unofficial build of Janet. It is not a Janet release and is not made by Janet's maintainers. Please report problems with chirp here, not to Janet.
chirp is young and not yet stable. It is used daily by its authors, but every 0.x release may still change chirp's own interfaces (its command line, yaml, omap) and move the pinned versions of what it bundles. Pin a release if a script must keep working, and read chirp --changelog before updating.
Scripts tend to start small and then need one more thing: an API call, a config file, somewhere to keep state. In most languages that one thing means an install step. Python wants a matching interpreter, a virtualenv and pip. Shell wants curl, jq and sqlite3 to be present, at versions that agree. Stock Janet has no TLS at all, and adding it means a C toolchain and OpenSSL headers on every machine.
chirp removes that step. The batteries are inside the binary, so a script written on a laptop runs unchanged on a fresh server, in a CI job, in a FROM scratch container or on an air-gapped machine. The only setup is copying one file.
chirp --help query searches the docs of every bundled module and of Janet's core, and chirp --changelog says what changed.chirp --self-update installs the latest release only after checking its signature.chirp does not fork Janet or its libraries. It pins upstream versions and bundles them, so Janet's own docs and community apply as they are.
chirp # REPL, like janet
chirp script.janet # run a script, like janet
echo '(print 1)' | chirp # run code from stdin
chirp --version # chirp 0.7.0 (unofficial build, not a Janet release) on Janet …
chirp --help # chirp's entry points, the help topics, then Janet's options
chirp --changelog # what changed in each release, offline
chirp --self-update # replace chirp with the latest signed release (--check only reports)
Inside chirp, every bundled module can be imported without anything on disk:
(import spork-https :as https)
(print ((https/get "https://example.com/") :status))
From 0.2.0, scripts can also keep data in SQLite and read configuration from TOML:
(import sqlite3)
(import tomlin)
(def db (sqlite3/open "notes.db"))
(sqlite3/eval db "CREATE TABLE IF NOT EXISTS notes (body TEXT);")
(print ((tomlin/toml->janet (slurp "config.toml")) :title))
YAML is built in too. yaml/decode and yaml/encode work like json/decode and json/encode, and plain scalars follow the YAML 1.2 Core schema, so no stays a string:
(import yaml)
(def cfg (yaml/decode (slurp "config.yaml") true))
(print (cfg :title))
(print (yaml/encode {:name "chirp" :tags ["a" "b"]}))
A table has no order, so a script that rewrites a JSON or YAML file loses the author's key order. Pass a fourth argument, ordered, to json/decode or yaml/decode (or yaml/decode-all) and every object comes back as an omap, a map that keeps its keys in insertion order. json/encode and yaml/encode write an omap in that order, and a plain table as before:
(import omap)
(import yaml)
(def doc (yaml/decode (slurp "config.yaml") false false true))
(put doc "version" 2) # an existing key keeps its place, a new one goes last
(put doc "obsolete" nil) # nil removes a key
(spit "config.yaml" (yaml/encode doc))
(print (omap/omap? doc) (keys doc)) # keys, get, put, in, pairs, eachp and length work as on a table
An omap is not a table, so table? and dictionary? are false for it and deep= does not compare it; a function that does not know the type fails loudly instead of dropping the order.
From 0.4.0, pcre2 brings Perl-style regular expressions, the syntax that grep, sed and Python documentation use. A pattern is a string, or compiled once with pcre2/compile:
(import pcre2)
(pcre2/match "(?<year>\\d{4})-(?<mon>\\d\\d)" "on 2026-10-27") # {0 "2026-10" 1 "2026" 2 "10" :mon "10" :year "2026"}
(pcre2/replace-all "(\\w+)@(\\w+)" "a@b c@d" "$2:$1") # "b:a d:c"
(pcre2/split ",\\s*" "a, b,c") # @["a" "b" "c"]
(pcre2/find-all "\\d+" "1 22 333") # an array of matches
Matching is bounded by counts instead of time (:match-limit, :depth-limit and :heap-limit, all with defaults), so a pattern that backtracks without end stops with an error that names the limit, the same way on every machine. chirp --help query pcre2 lists the functions and their options.
From 0.4.0, md4c renders Markdown to HTML. The default is plain CommonMark; :github adds tables, strikethrough, task lists, autolinks, admonitions and footnotes, and each extension can also be set on its own:
(import md4c)
(md4c/to-html "# Hi\n\n*a* `b`") # "<h1>Hi</h1>\n<p><em>a</em> <code>b</code></p>\n"
(md4c/to-html (slurp "README.md") {:github true}) # the body only, without <html> or <head>
Raw HTML in the input is passed through, as CommonMark says, so pass :no-html true for text you do not trust. chirp --help query md4c lists the options.
From 0.4.0, lexbor parses HTML the way a browser does and finds elements with CSS selectors, for example to check what a deployed site serves:
(import lexbor)
(def page (lexbor/parse (slurp "out/site/index.html")))
(map |(lexbor/attr $ "href") (lexbor/select page "nav a[href]")) # in document order
(lexbor/text (lexbor/select-first page "h1")) # nil when nothing matches
A node is a handle into its document, so it can be searched in turn ((lexbor/select node "li")), and lexbor/html gives its markup back. chirp --help query lexbor lists the functions.
From 0.7.0, gzip reads and writes .gz data and tar lists, extracts and creates tar archives, gzipped or not, so a release can be fetched and unpacked on a host without tar:
(import spork-https :as https)
(import tar)
(def s (https/open-stream "https://github.com/roobie/chirp/archive/refs/heads/main.tar.gz"))
(tar/extract s "chirp-main" {:strip 1}) # streamed; refuses entries that would land outside
(:close s)
(tar/create "notes.tar.gz" ["notes"]) # gzipped, from the name
chirp --help read archives covers both, including what extraction refuses.
chirp -h lists the help topics, chirp --help query '<words>' searches them and the docstrings of every bundled module offline, and chirp --help read <id> prints a result in full. The text is inside the binary. chirp --help serve shows the same help in a browser at http://127.0.0.1:3111/.
Each component is pinned to an exact upstream commit in pins.jdn. None of them is forked.
| Component | What it adds | License |
|---|---|---|
| Janet | the language and runtime | MIT |
| spork | the standard library extras, including spork/http and spork/zip (zlib and zip, via miniz) | MIT |
| jsec | TLS and DTLS streams for ev, certificates, crypto | ISC |
| spork-https | an HTTPS client and server on top of spork/http | ISC |
| janet-lang/sqlite3 | sqlite3, Janet bindings to an embedded SQLite (the amalgamation, so no system library is needed), with FTS5 full-text search enabled; from 0.2.0 | MIT (binding), public domain (SQLite) |
| tomlin | tomlin, a TOML parser written in Janet; from 0.2.0 | MIT |
| libyaml | yaml, YAML parsing and emitting: chirp's own small binding over libyaml 0.2.5, with Core schema scalars, anchors, aliases and merge keys; from 0.3.0 | MIT |
| PCRE2 | pcre2, Perl-style regular expressions: chirp's own small binding over PCRE2 10.49 (interpreter only, no JIT), with named groups, replacement with group references and split; from 0.4.0 | BSD-3-Clause with the PCRE2 exception |
| md4c |
Every release ships a NOTICES-<target>.txt with the full license texts of everything linked into that target's binary.
Releases are on the releases page. Each release has:
| Asset | For |
|---|---|
chirp-<version>-linux-x64 | Linux x86-64, static (musl), any distribution |
chirp-<version>-linux-arm64 | Linux arm64, static (musl), any distribution |
chirp-<version>-macos-arm64 | macOS 11+ on Apple silicon |
chirp-<version>-windows-x64.exe | Windows x64 |
NOTICES-<target>.txt | third-party license texts for that binary |
SHA256SUMS | the sha256 of every asset |
SHA256SUMS.sig | Ed25519 signature of SHA256SUMS, checked by chirp --self-update |
On Linux and macOS, make the binary executable with chmod +x. macOS binaries are signed ad hoc, not by an Apple developer ID, so a downloaded one is quarantined. After verifying it, remove the quarantine flag with xattr -d com.apple.quarantine chirp-<version>-macos-arm64.
Every binary is built twice by CI, in different directories on different runners, and the release is only published when both builds produce the same sha256. Two checks tell you that a download is the file CI built.
The checksum. Download SHA256SUMS next to the binary, then run:
sha256sum -c SHA256SUMS --ignore-missing # Linux
shasum -a 256 -c SHA256SUMS --ignore-missing # macOS
The build provenance. GitHub attests which workflow run and commit produced each asset. With the GitHub CLI:
gh attestation verify chirp-<version>-linux-x64 --repo roobie/chirp
Because the build is reproducible, you can also rebuild a release from its tag with sh tools/build/container.sh <target> <outdir> (this needs Docker) and compare the hashes.
chirp checks certificates by default. At startup it uses SSL_CERT_FILE if that is set. Otherwise it looks for the system's CA bundle in the usual Linux and macOS locations, and chirp --version shows which bundle it found.
Windows has no CA bundle file, so for now HTTPS on Windows needs SSL_CERT_FILE. Point it at a PEM bundle, for example the curl CA bundle or the ca-bundle.crt that ships with Git for Windows (in ucrt64 in current versions, mingw64 in older ones):
$env:SSL_CERT_FILE = "C:\Program Files\Git\ucrt64\etc\ssl\certs\ca-bundle.crt"
A later release will embed a pinned CA bundle as a fallback.
From 0.2.0, chirp layers two fixes over the bundled spork-https client, without forking it:
User-Agent header sends User-Agent: chirp/<version>, because some services, GitHub's API among them, reject requests without one. A User-Agent you set is sent unchanged.:tls-opts {:ca "ca.pem"} makes the client trust that CA, as the spork-https docs describe. jsec's client otherwise ignores :ca and falls back to the system store.The server is unchanged.
The build needs Docker. It runs in a container image pinned by digest in pins.jdn (Alpine plus the packages in tools/build/packages.txt), which Docker pulls from a public registry. zig cross-compiles every target from Linux:
sh tools/build/container.sh linux-x64 out/ # or linux-arm64, macos-arm64, windows-x64
The targets are defined in tools/build/config.jdn.
The website is generated by chirp from this repo's Markdown: chirp site/build.janet writes it to out/site/. The chirp must bundle md4c, from 0.4.0. The pages workflow publishes it after each release. chirp site/check.janet <dir|url> checks a built or deployed site with lexbor, by its structure rather than its text: navigation, unique ids, links and their fragments, the stylesheet, and the commit and chirp version in each footer. The workflow runs it on out/site before upload, and on the live site after deploy.
chirp's own code is under the MIT license. Bundled components keep their own licenses; see the table above and the release notices.
md4c, Markdown to HTML: chirp's own small binding over md4c 0.6.0's renderer, CommonMark by default with GitHub's extensions on request; from 0.4.0 |
| MIT |
| lexbor | lexbor, HTML parsing and CSS selectors: chirp's own small binding over lexbor 3.0.1's HTML, DOM and selectors modules; from 0.4.0 | Apache-2.0 |
| chirp itself | gzip, gzip framing over spork's miniz, whole or in pieces, and tar, tar archives in Janet, extracted safely; from 0.7.0 | MIT |
| chirp itself | omap, an insertion-ordered map that yaml and json can decode to and encode from; written in C for chirp, with json-omap, a copy of spork's JSON decoder that builds it; from 0.3.0 | MIT |
| OpenSSL 3 | statically linked under jsec | Apache-2.0 |