本文へ移動
hikari 仕様

hikari コマンド仕様 v1

本書は hikari CLI の起動形態と各サブコマンドの仕様を定める。言語の意味論は language-spec.md、組込関数群は prelude.md を参照。分量の大きいモードは別冊に分離した — REPL は repl.md、LSP サーバは lsp.md、ビルド (hikari build) は build.md、静的検査 (hikari check) は check.md、テスト (hikari test) は test.md、整形 (hikari fmt) は format.md、スタイル検査 (hikari lint) は lint.md。本書中の §N は本書内の節を指し、別冊内の節は「repl.md「動作モード」」のように書名+節名で参照する。

1. 起動ディスパッチ

hikari [SUBCOMMAND | <path>] [ARGS...]

第 1 引数によって起動モードが決まる。

第 1 引数 モード
なし (または --strict のみ) REPL repl.md
lsp LSP サーバ lsp.md
build バイナリビルド build.md
check 静的検査のみ check.md
test テスト実行 test.md
fmt ソース整形 format.md
lint スタイル検査 lint.md
doc リファレンス生成 §10
add 依存追加 §11
get 依存取得 §11
update 依存更新 §11
remove 依存削除 §11
eval 標準入力評価 §5.6
それ以外 ファイル実行 §5

サブコマンド名 (lsp / build / check / test / fmt / lint / doc / add / get / update / remove / eval) は予約。同名の .hikari ファイルを実行したい場合は ./lsp のようにディレクトリ付きで指定する。

1.1 終了コード

ファイル実行モード・eval モード・build モード・check モードの終了コード:

code 意味
0 成功
1 構文エラー / 評価エラー / ビルドエラー
2 I/O エラー / 引数不正 / 必須ツール不在

REPL と LSP サーバは正常終了時 0

1.2 ソース系サブコマンドの住み分け

check / fmt / lint はいずれも評価せずソースを扱うが、責務が異なる。

ツール 対象 動作 不変条件
check (check.md) 正しさ(構文 + 静的エラー、到達可能グラフ全体) 検出のみ
fmt (format.md) 具体構文の正規形 -w で書き換え 抽象構文木を保存
lint (lint.md) スタイル/品質(パース可能前提、保守的) 検出、--fix で書き換え --fix抽象構文を変えうる
  • `check` と `lint` はどちらも評価せず診断するが、check は「正しさ」(エラーの有無、モジュールグラフ単位)、lint は「書き方」(エラーではないスタイル問題、ファイル単位で import 解決なし)。
  • `fmt` と `lint --fix` はどちらもソースを書き換えるが、不変条件が違う。fmt抽象構文木を保存する正規化のみ(具体構文の見た目を正す。例: 1 引数 f(x)f x)。lint --fix抽象構文を変える正規化まで踏み込む(例: 制御構造 if(c, t, e)if c {t} {e}。評価結果は同じだが適用の段数=抽象構文が変わる)。よって fmt は制御構造のタプル形を保ち、並置化は lint --fix が担う。

2. REPL

REPL (hikari を引数なし、または --strict のみで起動) の仕様は repl.md に分離した。

3. LSP サーバ (hikari lsp)

LSP サーバ (hikari lsp) の仕様は lsp.md に分離した。

4. ビルド (hikari build)

ビルド (hikari build) の仕様は build.md に分離した。

5. ファイル実行 (hikari <path> [args...])

<path>.hikari ソースとして読み込み、評価する。<path> より後ろのトークンは プログラム起動引数としてそのまま実行プログラムへ渡り、std:envargs() (std/env.md §3) で取得できる。

hikari app.hikari list --json hello     # args() は ["list", "--json", "hello"]

hikari 自身のフラグ (--strict、§5.5) は位置を問わず entry に渡る前に取り除かれるため args() には現れない。その帰結として、プログラムへ literal --strict を引数として渡すことはできない。

5.1 ヘッダ要件

ファイル先頭の #{hikari} ヘッダは省略できる (省略時は #{hikari} 明示と同一意味、language-spec.md §1.1 / §13.1)。#[hikari] ヘッダ (ライブラリ形) は省略不可。先頭の空行・行コメント・shebang #!... は許容される。

5.2 標準入出力

  • 標準入力: input(prompt) (prelude.md §1) の読み取り元。
  • 標準出力: print(s) の出力先。
  • 標準エラー: パース/評価エラーメッセージの出力先(トップレベルに達した ? の失敗 bail 診断を含む、language-spec.md §16.5)。

5.3 import の解決

import <対象> := "<rel>"caller ファイルのディレクトリ を起点に絶対化される。同じファイルを複数回 import してもパースは 1 度だけ (*module.Manager の Cache による)。循環 import は呼び出し位置のエラーで停止する (詳細は language-spec.md の import 章を参照)。

ファイル実行モードでは OS の filepath.Abs ベースの解決が使われ、ファイルシステム外への参照 (絶対パスなど) も許される。embed バイナリ (build.md) では FS ルートからの slash 相対パスに限定される (runtime.Config.EmbedMode)。

std:fs の各関数 (read / write / readdir ほか、std/fs.md) は import fs := "std:fs" で取得するが、データファイルの読み書きはソースの import m := "x.hikari" とは 解決系統が別 で、embed バイナリ内でも常にホスト FS の cwd 相対で動く (embed FS にはアクセスしない)。std:fs モジュール自体は embed バイナリにも常に含まれる。

5.4 終了コード

状況 code
正常終了 0
パース・評価エラー 1
ファイル読み取り失敗 2

トップレベルに達した未処理失敗(? の失敗 bail、language-spec.md §16.5)は評価エラーとして 1。診断は stderr(§5.2)に出す。

5.5 strict 型検査 (--strict)

hikari <path> --strict は、評価の 前に strict 型検査 (static-analysis.md §3) を走らせ、型エラーが 1 件でもあれば診断を stderr に出して 評価せず exit code 1 で停止する。型検査がクリーンなら通常どおり評価する。フラグは path の前後どちらに置いてもよい (hikari --strict <path> / hikari <path> --strict)。

  • strict モードは static-analysis.md §2 の健全・漸進検査に「名前付き関数の結果型の暗黙 Any を禁止 (明示 Any はオプトインで許容)」「名前付き関数のパラメータ型必須化」「宣言結果型を契約とした越境照合」を上乗せする (static-analysis.md §3)。
  • 実効 strict はファイル単位で決まる。entry ファイルが header #{hikari strict} / #[hikari strict] (language-spec.md §13.1) を宣言していれば、--strict を付けなくてもそのファイルは strict として検査される。実効 strict = 「CLI --strict」OR「entry header の strict 属性」。
  • フラグ無し・header に strict 無しの hikari <path> は従来どおり型検査せず実行する (実行時照合が backstop)。
  • 終了コードは §5.4 と同じ (型エラーは構文/評価エラーと同じ 1)。

5.6 標準入力からの評価 (hikari eval)

hikari eval は標準入力から読み込んだソース全量を .hikari プログラムとして評価する。エディタの選択範囲など、ファイルに無いソース断片を実行する用途を想定する。

  • 入力: 標準入力全量がソース。パス引数は取らない。
  • ヘッダ: ファイル実行 (§5.1) と同じく #{hikari} は省略可。
  • `--strict`: ファイル実行 (§5.5) と同じく strict 型検査 (static-analysis.md §3) を適用する。実効 strict = 「CLI --strict」OR「ソース header の strict 属性」。型エラーが 1 件でもあれば評価せず exit code 1
  • 標準出力: print(s) の出力先。標準エラー: パース/評価エラーの出力先。
  • `input()`: 標準入力はソースとして消費されるため、input(prompt) は即座に EOF(空)を受け取る。
  • import の解決: import <対象> := "<rel>"実行時カレントディレクトリ を起点に絶対化される(§5.3 と同じ OS filepath ベース)。エラー位置のファイルラベルは <stdin> と表示する。
  • 終了コード: ファイル実行 (§5.4) と同一。
状況 code
正常終了 0
パース・評価エラー 1
標準入力の読み取り失敗 2

eval評価する 点で、評価せずソースを扱う check / fmt / lint (§1.2) とは別系統である。

6. 静的検査 (hikari check)

静的検査 (hikari check) の仕様は check.md に分離した。

7. テスト (hikari test)

テスト (hikari test) の仕様は test.md に分離した。

8. 整形 (hikari fmt)

整形 (hikari fmt) の仕様は format.md に分離した。

9. スタイル検査 (hikari lint)

スタイル検査 (hikari lint) の仕様は lint.md に分離した。

10. リファレンス生成 (hikari doc)

hikari doc は prelude・std・言語構文の doc コメント(実装内 //| / #|)からユーザ向けリファレンス Markdown を docs/reference/ に生成する。ソース (internal/prelude 等の Go 実装、および言語構文の doc コメント) が真実源であり、docs/reference/ はそこから機械的に生成される派生物である。ライブラリ項目には、処理系の静的型表 (LSP hover と同じ出所) から型シグネチャ (hikari 型表記) を合成し、形と同じコードブロックの 2 行目に束縛注釈と同じ「名前: 型」の形 (例 range: {Int, Int | Range}) で併記する。型表から確定しない項目 (型名の値束縛・each のように戻り型を静的に固定できないメソッドなど) は形と意味だけを出す。

10.1 構文

hikari doc [--check]

引数を取らない (対象は常にリポジトリ全体の doc コメント)。

10.2 動作

  • hikari doc — prelude・std 各モジュール・言語構文の doc コメントを収集し、ライブラリ項目に静的型表から型シグネチャを join した上で、docs/reference/{prelude.md, std/*.md, syntax.md} を生成して上書きする。
  • hikari doc --check — 同じ生成処理を行い、結果が現在の docs/reference/ の内容と一致するか検査する。差分があれば非ゼロ終了 (CI で「生成物が最新か」を検査する用途)。

10.3 doctest

doc コメント中の >>> で始まる例は doctest として抽出され、go test 実行時に実際に評価してその出力が期待値と一致するか検証される。ドキュメント中の例が実装と乖離することを防ぐ。

10.4 出力と終了コード

状況 code
生成 (--check 無し) 成功 0
--check で差分なし 0
--check で差分あり 1
I/O エラー 2

11. パッケージ管理 (add / get / update / remove)

third-party パッケージ (packages.md) の依存を、マニフェスト (package.hikari) と lockfile (package-lock.hikari) を介して管理する。取得元は git source とローカル path dep。別名解決・キャッシュ・推移依存・複数共存の意味論は packages.mdpkg: 解決の言語側は language-spec.md §13.4 を参照。

各コマンドは cwd を起点に上方探索で最も近いマニフェストを対象とする。マニフェストが無い場合は §11.5 のエラー。

add / remove はマニフェストの deps / entry を読み、正規形 (2 スペースインデント・末尾カンマなし) で書き戻す。deps 内に書いたコメントは保持されない。

11.1 hikari add

hikari add <host/path@tag> [--as <alias>]
  • <host/path@tag> の git source をキャッシュ (§12 HIKARI_CACHE) へ取得し、tag → commit を解決して lockfile に固定する。マニフェスト depsalias := "<host/path@tag>" を追記する。
  • --as <alias> 省略時、alias は path の末尾要素の -_ に正規化したもの (例 github.com/u/hikari-httphikari_http)。alias は hikari の識別子 (スロット名) になるためハイフンを含めず、正規化しても有効な識別子にならない場合 (先頭が数字など) は取得せずエラーで --as <alias> を要求する。短い別名にしたい場合も --as http を使う。
  • 既存の同名 alias があればその pin を更新する (version の差し替え)。
  • path dep の追加は hikari add では扱わず、マニフェストを直接編集する (取得を伴わないため)。

11.2 hikari get

hikari get
  • 引数なし。マニフェストと lockfile を読み、未取得の依存をキャッシュへ復元する。lockfile があれば commit を信頼し tag の再解決はしない。CI・新規 clone 後の初期化に使う。
  • lockfile が無い場合はマニフェストから tag → commit を解決して取得し、lockfile を生成する。

11.3 hikari update

hikari update [alias]
  • マニフェストに記載された tag を再解決 (tag → 現在の commit) し、lockfile を書き換える。alias 指定でその 1 件、省略で全 git 依存。
  • バージョンを上げるのは tag の変更 (hikari add <...@新tag> またはマニフェスト編集) であり、update は記載済み tag の commit 固定を最新化するもの (semver range の自動引き上げは持たない)。

11.4 hikari remove

hikari remove <alias>
  • マニフェスト deps から <alias> を削除し、どの依存からも参照されなくなった実体を lockfile から除く。キャッシュ実体は他プロジェクトと共有のため削除しない。

11.5 出力と終了コード

状況 code
成功 0
取得・解決失敗 (不正な tag / リポジトリ到達不可 / マニフェスト不正) / 対象 alias 不在 1
引数不正 / マニフェスト読み取り失敗 / git 不在 2

git ツールチェーンは exec.LookPath("git") で確認し、無ければ exit code 2

12. 環境変数

変数 影響先 意味
HIKARI_REPO hikari build / hikari lsp hikari 本体ソースの絶対パス。設定すれば自動検出 (build.md「hikari リポジトリの位置解決」/ lsp の定義ジャンプ lsp.md「定義ジャンプ」) より優先
HIKARI_CACHE add / get / update / ファイル実行・buildpkg: 解決 third-party パッケージのグローバルキャッシュ。未設定時の既定は XDG の $XDG_CACHE_HOME/hikari (既定 ~/.cache/hikari) (packages.md)

13. 意図的に残す制約

  • go install github.com/bluegreenhq/hikari/cmd/hikari@latest でインストールしたバイナリから hikari build を使うには現状 HIKARI_REPO が必要 (本体ソースの自動配置は未対応)。
  • Universal Binary (darwin/arm64 + darwin/amd64lipo 結合) は非対応 — 別ターゲットとして個別バイナリを並べるのみ。
  • バイナリサイズ最適化は -ldflags="-s -w" のみ。UPX 等の圧縮は行わない。
  • LSP は semantic tokens・go-to-definition・references・hover (型情報)・補完 (ドットメンバ)・整形 (全文フォーマット)・コードアクション (lint 自動修正)・シンボル一覧 (アウトライン)・リネーム・インレイヒント (推論型)・出現ハイライト・診断 (静的検査 Error + lint Warning、publishDiagnostics) を提供 (各機能は lsp.md)。hover は prelude 組込名・ユーザ定義識別子に加え、型メソッド (list.each 等) とユーザ定義オブジェクトのメンバも対象とする (lsp.md「hover」)。補完はドット (.) を trigger に、レシーバの slot・型メソッド・std メンバ・universal method を返す (lsp.md「補完」)。
  • hikari fmt は AST 再構成方式のため、行内の任意改行位置やスロットの positional/named 混在順といった意味に影響しない見た目は正規形へ寄せる (原文どおりには保たない)。
  • hikari lint のルールは lint.md「ルール」の 10 個 (unused / self-assign / single-assign / control-juxtaposition / non-tail-recur / unit-else / nested-if / trivial-match / bool-match / import-order)。多くは全体走査による保守的判定に留める (制御構造名・条件分岐系ルールは構文上の callee 名のみで判定し、シャドーイングは見ない)。例外は single-assign で、=/:= の別が意味に効くためオブジェクトリテラル単位のスコープ木を組んで束縛ごとに書き込み回数を数える (lint.md「single-assign がスコープ厳密解析を行う理由と健全性」)。
  • third-party パッケージの取得元は git と ローカル path dep のみ (packages.md)。中央レジストリ・HTTPS tarball 直取得・semver range の自動解決は非対応 (exact pin + 複数共存)。hikari add 等のパッケージ管理コマンドは git ツールチェーンを必要とする。