diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 253f0b7..45e09df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: branches: [main] pull_request: +# CI runs the same `make` targets a contributor runs locally, so the two can +# never drift. The toolchain is built from gnolang/gno master: this repo is the +# first thing a newcomer runs, so it has to work against what they install today. jobs: test: runs-on: ubuntu-latest @@ -23,7 +26,7 @@ jobs: echo "$HOME/.gno/bin" >> "$GITHUB_PATH" - name: Test - run: gno test . + run: make test - name: Lint - run: gno lint . + run: make lint diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..86a1465 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,52 @@ +# AGENTS.md + +Guide for coding agents (and humans in a hurry) working in this repository. +It is deliberately tiny, like the repo. + +## What this is + +One Gno realm, `hello.gno`, plus its test. `gnomod.toml` declares the on-chain +path it deploys to. Nothing else. Keep it that way: this repo's whole job is to +be understandable in five minutes. + +## Commands + +```sh +make # list every target +make install # build the gno toolchain into $HOME/.gno/bin (then add it to PATH) +make dev # local chain + web UI on http://localhost:8888, reloads on save +make test # gno test . +make lint # gno lint . +make fmt # gno fmt -w . +``` + +`make test lint` is the bar for any change. CI runs those two targets against a +`gno` built from `gnolang/gno` master, while yours is whatever you installed +last, so re-run `make install` before trusting a green local run. + +## Gno is not Go + +Close enough that Go habits compile in your head and fail on the chain. Read, +do not guess: + +- [Realms](https://docs.gno.land/resources/realms): `Render` and realm state +- [Interrealm](https://docs.gno.land/resources/gno-interrealm): crossing + functions, the `realm` parameter, `cross(...)` +- [Go/Gno compatibility](https://docs.gno.land/resources/go-gno-compatibility): + what the language keeps, drops and adds +- [Standard libraries](https://docs.gno.land/resources/gno-stdlibs): the subset + that exists, and `chain/*` in place of Go's runtime packages +- [Testing](https://docs.gno.land/resources/gno-testing): including why an + `Example*` function needs an `// Output:` block +- [Effective Gno](https://docs.gno.land/resources/effective-gno): idioms worth + copying + +## Tooling worth having + +- [`gnoverse/gno-mcp`](https://github.com/gnoverse/gno-mcp): MCP server plus + agent skills for gno.land. Read and render realms, evaluate expressions, + deploy to a testnet, audit a realm. Pre-release, and writes are gated to + dev/testnet. +- [`gnoverse/gnopls`](https://github.com/gnoverse/gnopls): the Gno language + server, for editors. Setup in + [Editor Setup](https://docs.gno.land/builders/editor-setup). diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fded5dc --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See [AGENTS.md](./AGENTS.md). diff --git a/Makefile b/Makefile index aa8bc85..dde6370 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,29 @@ -.PHONY: install dev test +# getting-started. Run `make` (or `make help`) to see every target. -install: +GNO ?= gno +GNODEV ?= gnodev + +.DEFAULT_GOAL := help +.PHONY: help install dev test lint fmt + +help: ## list the available targets + @awk 'BEGIN{FS=":.*?## "} /^[a-zA-Z_-]+:.*?## /{printf " %-8s %s\n",$$1,$$2}' $(MAKEFILE_LIST) + +install: ## build the gno toolchain into $HOME/.gno/bin # --from-source is required: the installer's prebuilt-binary mode looks for # v* release tags, and gnolang/gno only publishes chain/* tags today. curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/gnolang/gno/master/misc/install.sh | sh -s -- --from-source - @echo '>> binaries are in $$HOME/.gno/bin — add it to your PATH:' + @echo '>> binaries are in $$HOME/.gno/bin, add it to your PATH:' @echo ' export PATH="$$HOME/.gno/bin:$$PATH"' -dev: - gnodev . +dev: ## run a local chain + web UI on http://localhost:8888, reloading on save + $(GNODEV) . + +test: ## run the tests + $(GNO) test . + +lint: ## catch what only the chain would otherwise catch + $(GNO) lint . -test: - gno test . +fmt: ## format every .gno file in place + $(GNO) fmt -w . diff --git a/README.md b/README.md index 7f45f0c..0f1e46f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,7 @@ # Getting Started with Gno -This repository is intentionally kept minimal and simple. It's designed to help -you get your first experience with Gno in under five minutes, focusing on the -most common tools and basic concepts. - -If you're already familiar with Gno or looking for a more comprehensive setup, -check out the "Next Steps" section below for links to more advanced resources. +One Gno realm, its test, and a Makefile, small enough to read in five minutes. +Everything this file does not explain is in the [Gno documentation](https://docs.gno.land). ## Quick Start @@ -14,19 +10,14 @@ check out the "Next Steps" section below for links to more advanced resources. git clone https://github.com/gnolang/getting-started.git cd getting-started -2. Install dependencies: +2. Install the toolchain: make install - -This clones `gnolang/gno` and builds `gno`, `gnokey`, `gnodev`, `gnobro` and -`gnoweb` into `$HOME/.gno/bin`. It needs Go, git and make, and takes a few -minutes the first time. Add the directory to your `PATH` before continuing: - export PATH="$HOME/.gno/bin:$PATH" -(The installer also has a faster prebuilt-binary mode, but it currently looks -for `v*` release tags and `gnolang/gno` only publishes `chain/*` tags, so -`--from-source` is the path that works today.) + This builds `gno`, `gnokey`, `gnodev` and `gnoweb` from source into + `$HOME/.gno/bin`. Other ways to install them: + [Installation](https://docs.gno.land/builders/install). 3. Start the development server: @@ -34,30 +25,45 @@ for `v*` release tags and `gnolang/gno` only publishes `chain/*` tags, so 4. Open your browser and visit http://localhost:8888 -## What's Included +Edit `hello.gno` while `make dev` runs and the page reloads with your change. +Run `make` at any point to see every available target. What else `gnodev` can do: +[Local development with gnodev](https://docs.gno.land/builders/local-dev-with-gnodev). -This repository contains a simple Gno realm with: -- A `Render` function that displays a welcome message and instructions -- A `Set` function to update the realm's state -- A `Get` function to retrieve the stored message +## What's in here -## Deploying it +- `hello.gno`: a realm with `Render` (what gnoweb displays), plus `Set` and `Get`. +- `hello_test.gno`: one test for the state-changing function, one that calls + `Render`. Every realm wants both. -`gnodev` runs a throwaway local chain. When you want your realm on a real -network: +Why `Set` takes a `realm` parameter and the test calls `cross(...)`: +[Realms](https://docs.gno.land/resources/realms) and +[Interrealm](https://docs.gno.land/resources/gno-interrealm). -- **A testnet** — start here. Testnets are renamed and replaced every few - weeks, so look up the current one and its RPC endpoint in - [Gno networks](https://docs.gno.land/resources/gnoland-networks), and get - tokens from the [faucet](https://faucet.gno.land). -- **[Mainnet](https://gno.land)** (`gnoland-1`, - `https://rpc.gno.land:443`) has been live since 12 September 2026. Real - GNOT, no faucet. +## Testing it -## Next Steps + make test # run the tests + make lint # catch what only the chain would otherwise catch + make fmt # format every .gno file in place -Ready to learn more? Check out these resources: +More: [Testing Gno code](https://docs.gno.land/resources/gno-testing). + +## Deploying it + +`gnodev` runs a throwaway local chain. To put your realm on a real network, +point `module` in `gnomod.toml` at a path you control (`gno.land/r//hello` +always works and needs no registration), then follow +[Deploy to a shared network](https://docs.gno.land/builders/getting-started#deploy-to-a-shared-network), +which covers the key, the faucet, the namespace and the deploy command itself. + +## Next Steps -- Gno Documentation: https://docs.gno.land -- Gno Repository Template: https://github.com/gnolang/repo-template - +- [Gno documentation](https://docs.gno.land) +- [Editor setup](https://docs.gno.land/builders/editor-setup), with the + [`gnopls`](https://github.com/gnoverse/gnopls) language server +- [gnoverse/gno-mcp](https://github.com/gnoverse/gno-mcp): MCP server plus + skills that put an AI agent on gno.land +- [examples/](https://github.com/gnolang/gno/tree/master/examples): the realms + and packages that ship with the chain +- [moul/gno-contracts](https://github.com/moul/gno-contracts): what a serious + Gno repository grows into +- [gnoverse/awesome-gno](https://github.com/gnoverse/awesome-gno): everything else diff --git a/hello.gno b/hello.gno index 30b75cd..882955f 100644 --- a/hello.gno +++ b/hello.gno @@ -7,14 +7,11 @@ var message string = "Hello, Gno!" func Render(path string) string { return `# ` + message + ` -This is a simple Gno realm that demonstrates basic functionality. -Try it out with gnokey: +This page is what Render returns. Edit hello.gno while "make dev" is running +and it reloads with your change. - gnokey add myaccount - gnokey list - -[And click here](/r/example/hello$help&func=Set&newMsg=Hello%20from%20Gnokey!) - ` +Add $help to this page's URL to call Set from your browser. +` } func Set(_ realm, newMsg string) { diff --git a/hello_test.gno b/hello_test.gno index 2be6411..b470fb0 100644 --- a/hello_test.gno +++ b/hello_test.gno @@ -1,6 +1,7 @@ package hello import ( + "strings" "testing" ) @@ -16,3 +17,12 @@ func TestSetAndGet(cur realm, t *testing.T) { t.Errorf("Expected 'Hello, Test!', got %s", got) } } + +// gnoweb calls Render for every page view, so always keep a test that actually +// calls it. A realm with an untested Render only fails once it is on-chain. +func TestRender(t *testing.T) { + out := Render("") + if !strings.Contains(out, Get()) { + t.Errorf("Render() should show the message %q, got:\n%s", Get(), out) + } +}