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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 0.4.1 - Unreleased

- Add cached release checks with `gitcrawl check-update` and passive terminal
notices when a newer OpenClaw release is available.

## 0.4.0 - 2026-05-17

- Harden portable-store publishing and reads with manifest integrity checks, temp-DB validation before runtime replacement, stale Git lock cleanup, reclone fallback, and richer `doctor` DB health output.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ go build -ldflags "-X github.com/openclaw/gitcrawl/internal/cli.version=$(git de
./bin/gitcrawl --version
```

Check for newer releases manually with:

```bash
gitcrawl check-update
```

Interactive terminal runs also perform a cached daily release check and print a
stderr notice when a newer OpenClaw release is available. Set
`GITCRAWL_NO_UPDATE_CHECK=1` or `CRAWLKIT_NO_UPDATE_CHECK=1` to disable that
passive notice.

Docker:

```bash
Expand Down
12 changes: 12 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ gitcrawl --version

Browse the [releases page](https://github.com/openclaw/gitcrawl/releases) for the latest tag and the full asset list. Use a directory that is already on your `PATH`; `~/bin` and `~/.local/bin` avoid needing elevated permissions.

## Check for updates

```bash
gitcrawl check-update
gitcrawl check-update --json
```

Interactive terminal runs perform a cached daily release check and print a
stderr notice when a newer OpenClaw release is available. Scripted, JSON, CI,
and non-TTY runs skip the passive notice. Set `GITCRAWL_NO_UPDATE_CHECK=1` or
`CRAWLKIT_NO_UPDATE_CHECK=1` to disable it.

## Install from source

```bash
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/charmbracelet/x/ansi v0.11.7
github.com/mattn/go-isatty v0.0.22
github.com/openclaw/crawlkit v0.5.3
github.com/openclaw/crawlkit v0.6.0
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/openclaw/crawlkit v0.5.3 h1:bRfix5IaajxsN9QAExkW8qMM7uVaT5yXnQpSI1Qu3SI=
github.com/openclaw/crawlkit v0.5.3/go.mod h1:+2kUqiyecwK/vWySHqZnu968wmdWGBebJ22uUhQEalM=
github.com/openclaw/crawlkit v0.6.0 h1:7ef1UDl6qrV3KJu74mw2WJn1+G5zEMhzTFaktn0CMZ4=
github.com/openclaw/crawlkit v0.6.0/go.mod h1:+2kUqiyecwK/vWySHqZnu968wmdWGBebJ22uUhQEalM=
github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc=
github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
10 changes: 10 additions & 0 deletions internal/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,13 @@ func (a *App) Run(ctx context.Context, args []string) error {
a.printUsage()
return nil
}
a.maybeNotifyRelease(ctx, rest)

switch rest[0] {
case "version":
return a.writeOutput("version", map[string]string{"version": version}, false)
case "check-update":
return a.runCheckUpdate(ctx, rest[1:])
case "metadata":
return a.runMetadata(rest[1:])
case "serve":
Expand Down Expand Up @@ -2843,6 +2846,7 @@ func (a *App) runMetadata(args []string) error {
manifest.Privacy = control.Privacy{ContainsPrivateMessages: false, ExportsSecrets: false, LocalOnlyScopes: []string{"github", "sqlite", "portable"}}
manifest.Commands = map[string]control.Command{
"status": {Title: "Status", Argv: []string{"gitcrawl", "status", "--json"}, JSON: true},
"check-update": {Title: "Check for updates", Argv: []string{"gitcrawl", "check-update", "--json"}, JSON: true},
"doctor": {Title: "Doctor", Argv: []string{"gitcrawl", "doctor", "--json"}, JSON: true},
"sync": {Title: "Sync repository", Argv: []string{"gitcrawl", "sync", "--json"}, JSON: true, Mutates: true},
"search": {Title: "Search", Argv: []string{"gitcrawl", "search", "--json"}, JSON: true},
Expand Down Expand Up @@ -3588,6 +3592,7 @@ Global flags:

Core commands:
metadata print crawlkit control metadata
check-update check for a newer gitcrawl release
status print fast read-only archive status
init create config, optionally from a portable store
doctor check config, token, and database readiness
Expand Down Expand Up @@ -3629,6 +3634,11 @@ Usage:

Usage:
gitcrawl status [--json]
`,
"check-update": `gitcrawl check-update checks GitHub Releases for a newer gitcrawl build.

Usage:
gitcrawl check-update [--json] [--force]
`,
"init": `gitcrawl init creates a local config and SQLite database.

Expand Down
61 changes: 61 additions & 0 deletions internal/cli/releasecheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cli

import (
"context"
"errors"
"flag"
"fmt"

"github.com/openclaw/crawlkit/releasecheck"
"github.com/openclaw/gitcrawl/internal/config"
)

const gitcrawlUpgradeHint = "brew upgrade openclaw/tap/gitcrawl"

func gitcrawlReleaseCheckOptions(force bool) releasecheck.Options {
cfg := config.Default()
return releasecheck.Options{
AppName: "gitcrawl",
Owner: "openclaw",
Repo: "gitcrawl",
CurrentVersion: version,
CacheDir: cfg.CacheDir,
Force: force,
}
}

func (a *App) maybeNotifyRelease(ctx context.Context, args []string) {
_, _ = releasecheck.Notify(ctx, releasecheck.NotifyOptions{
Options: gitcrawlReleaseCheckOptions(false),
Stderr: a.Stderr,
InstallHint: gitcrawlUpgradeHint,
Args: args,
JSONOutput: a.format == FormatJSON,
IsTerminal: releasecheck.StderrIsTerminal(),
})
}

func (a *App) runCheckUpdate(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("check-update", flag.ContinueOnError)
fs.SetOutput(a.Stderr)
jsonOut := fs.Bool("json", false, "write JSON output")
force := fs.Bool("force", false, "force a fresh release check")
if err := fs.Parse(args); err != nil {
return usageErr(err)
}
if fs.NArg() != 0 {
return usageErr(fmt.Errorf("check-update takes flags only"))
}
result, err := releasecheck.Check(ctx, gitcrawlReleaseCheckOptions(*force))
if err != nil && !errors.Is(err, releasecheck.ErrSkipped) {
return err
}
if *jsonOut || a.format == FormatJSON {
if *jsonOut {
a.format = FormatJSON
}
return a.writeOutput("check-update", result, false)
}
_, err = fmt.Fprint(a.Stdout, releasecheck.StatusText("gitcrawl", gitcrawlUpgradeHint, result))
return err
}