Skip to content

Commit bcd1fd6

Browse files
ZaynJarvisclaude
andcommitted
feat(cli): publish native CLI to npm on tag push
Replace GitHub Release with npm publishing for CLI tags (cli@*). Each tag triggers: build 5 platform binaries → publish platform-specific @openviking/cli-{os}-{arch} packages → publish @openviking/cli wrapper. - Add npm/cli/ wrapper package with postinstall help message - Generate platform packages in CI from build artifacts - Remove GitHub Release and artifact upload from CLI workflow Required GitHub secret: NPM_TOKEN Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8c01e97 commit bcd1fd6

6 files changed

Lines changed: 280 additions & 76 deletions

File tree

.github/workflows/rust-cli.yml

Lines changed: 97 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99
- 'Cargo.toml'
1010
- '.github/workflows/rust-cli.yml'
1111
tags:
12-
- 'cli@*' # Trigger release on tags starting with cli@
12+
- 'cli@*'
1313
pull_request:
1414
branches: [ main ]
1515
paths:
@@ -28,18 +28,33 @@ jobs:
2828
- os: ubuntu-24.04
2929
target: x86_64-unknown-linux-gnu
3030
artifact_name: ov-linux-x86_64
31+
npm_pkg: cli-linux-x64
32+
npm_os: linux
33+
npm_cpu: x64
3134
- os: ubuntu-24.04
3235
target: aarch64-unknown-linux-gnu
3336
artifact_name: ov-linux-aarch64
37+
npm_pkg: cli-linux-arm64
38+
npm_os: linux
39+
npm_cpu: arm64
3440
- os: macos-15-intel
3541
target: x86_64-apple-darwin
3642
artifact_name: ov-macos-x86_64
43+
npm_pkg: cli-darwin-x64
44+
npm_os: darwin
45+
npm_cpu: x64
3746
- os: macos-14
3847
target: aarch64-apple-darwin
3948
artifact_name: ov-macos-aarch64
49+
npm_pkg: cli-darwin-arm64
50+
npm_os: darwin
51+
npm_cpu: arm64
4052
- os: windows-latest
4153
target: x86_64-pc-windows-msvc
4254
artifact_name: ov-windows-x86_64.exe
55+
npm_pkg: cli-win32-x64
56+
npm_os: win32
57+
npm_cpu: x64
4358

4459
steps:
4560
- uses: actions/checkout@v6
@@ -85,109 +100,116 @@ jobs:
85100
${{ runner.os }}-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}-
86101
${{ runner.os }}-target-${{ matrix.target }}-
87102
88-
- name: Build CLI
89-
run: cargo build --release --target ${{ matrix.target }} -p ov_cli
90-
91-
- name: Create compressed artifacts
103+
- name: Inject version from tag
92104
shell: bash
93105
run: |
94-
mkdir -p artifacts
95-
cd target/${{ matrix.target }}/release
96-
97-
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
98-
# Windows: create zip
99-
7z a ../../../artifacts/${{ matrix.artifact_name }}.zip ov.exe
100-
cd ../../../artifacts
101-
# Use PowerShell to get hash in correct format
102-
powershell -Command "(Get-FileHash -Algorithm SHA256 '${{ matrix.artifact_name }}.zip').Hash.ToLower() + ' ${{ matrix.artifact_name }}.zip'" > ${{ matrix.artifact_name }}.zip.sha256
103-
else
104-
# Unix: create tar.gz
105-
tar czf ../../../artifacts/${{ matrix.artifact_name }}.tar.gz ov
106-
cd ../../../artifacts
107-
# shasum format: <hash> <filename>
108-
shasum -a 256 ${{ matrix.artifact_name }}.tar.gz > ${{ matrix.artifact_name }}.tar.gz.sha256
106+
VERSION="${GITHUB_REF#refs/tags/cli@}"
107+
if [[ "$VERSION" != "$GITHUB_REF" ]]; then
108+
sed -i.bak "s/^version = \"0.0.0\"/version = \"$VERSION\"/" crates/ov_cli/Cargo.toml
109+
rm -f crates/ov_cli/Cargo.toml.bak
110+
echo "Injected version $VERSION into Cargo.toml"
109111
fi
110112
111-
- name: Verify checksum format
113+
- name: Build CLI
114+
run: cargo build --release --target ${{ matrix.target }} -p ov_cli
115+
116+
- name: Package platform npm package
112117
shell: bash
113118
run: |
114-
echo "Contents of checksum file:"
115-
cat artifacts/*.sha256
116-
echo ""
117-
echo "Verifying checksum locally:"
118-
cd artifacts
119+
VERSION="${GITHUB_REF#refs/tags/cli@}"
120+
# For non-tag builds, use 0.0.0-dev
121+
if [[ "$VERSION" == "$GITHUB_REF" ]]; then
122+
VERSION="0.0.0-dev"
123+
fi
124+
125+
PKG_DIR="npm-pkg"
126+
mkdir -p "$PKG_DIR/bin"
127+
119128
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
120-
sha256sum -c *.sha256 || shasum -a 256 -c *.sha256 || echo "Checksum verification skipped on Windows"
129+
cp "target/${{ matrix.target }}/release/ov.exe" "$PKG_DIR/bin/ov.exe"
121130
else
122-
shasum -a 256 -c *.sha256
131+
cp "target/${{ matrix.target }}/release/ov" "$PKG_DIR/bin/ov"
132+
chmod +x "$PKG_DIR/bin/ov"
123133
fi
124134
125-
- name: Upload artifacts
135+
node -e "
136+
const pkg = {
137+
name: '@openviking/${{ matrix.npm_pkg }}',
138+
version: '$VERSION',
139+
description: 'OpenViking CLI native binary for ${{ matrix.npm_os }}-${{ matrix.npm_cpu }}',
140+
os: ['${{ matrix.npm_os }}'],
141+
cpu: ['${{ matrix.npm_cpu }}'],
142+
files: ['bin'],
143+
license: 'Apache-2.0',
144+
repository: { type: 'git', url: 'git+https://github.com/volcengine/openviking.git' },
145+
publishConfig: { access: 'public' }
146+
};
147+
require('fs').writeFileSync('$PKG_DIR/package.json', JSON.stringify(pkg, null, 2) + '\n');
148+
"
149+
150+
- name: Upload npm package artifact
126151
uses: actions/upload-artifact@v7
127152
with:
128-
name: ${{ matrix.artifact_name }}
129-
path: artifacts/*
153+
name: ${{ matrix.npm_pkg }}
154+
path: npm-pkg/
130155

131-
release:
132-
name: Create GitHub Release
156+
npm-publish:
157+
name: Publish to npm
133158
runs-on: ubuntu-24.04
134159
needs: build
135160
if: startsWith(github.ref, 'refs/tags/cli@')
136-
permissions:
137-
contents: write
138161
steps:
139162
- name: Checkout code
140163
uses: actions/checkout@v6
141164

165+
- name: Setup Node.js
166+
uses: actions/setup-node@v4
167+
with:
168+
node-version: '22'
169+
registry-url: 'https://registry.npmjs.org'
170+
142171
- name: Get version from tag
143172
id: get_version
144173
run: echo "version=${GITHUB_REF#refs/tags/cli@}" >> $GITHUB_OUTPUT
145174

146-
- name: Download all artifacts
175+
- name: Download all platform artifacts
147176
uses: actions/download-artifact@v8
148177
with:
149178
path: artifacts
150179

151180
- name: Display artifact structure
152181
run: ls -R artifacts/
153182

154-
- name: Create GitHub Release
155-
uses: softprops/action-gh-release@v2
156-
with:
157-
name: CLI v${{ steps.get_version.outputs.version }}
158-
body: |
159-
# OpenViking CLI v${{ steps.get_version.outputs.version }}
160-
161-
## Installation
162-
163-
### Quick Install (macOS/Linux)
164-
```bash
165-
curl -fsSL https://raw.githubusercontent.com/${{ github.repository }}/refs/tags/cli@${{ steps.get_version.outputs.version }}/crates/ov_cli/install.sh | bash
166-
```
167-
168-
### Manual Installation
169-
Download the appropriate binary for your platform below, extract it, and add it to your PATH.
170-
171-
The CLI command is simply `ov`:
172-
```bash
173-
# After extraction
174-
chmod +x ov # Unix only
175-
mv ov /usr/local/bin/ # or any directory in your PATH
176-
177-
# Verify installation
178-
ov --version
179-
```
180-
181-
### Checksums
182-
SHA256 checksums are provided for each binary for verification.
183-
184-
## Changes
185-
See the [commit history](https://github.com/${{ github.repository }}/commits/cli@${{ steps.get_version.outputs.version }}) for details.
186-
files: |
187-
artifacts/**/*.tar.gz
188-
artifacts/**/*.zip
189-
artifacts/**/*.sha256
190-
draft: false
191-
prerelease: ${{ contains(steps.get_version.outputs.version, 'alpha') || contains(steps.get_version.outputs.version, 'beta') || contains(steps.get_version.outputs.version, 'rc') }}
183+
- name: Publish platform packages
184+
env:
185+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
186+
run: |
187+
VERSION="${{ steps.get_version.outputs.version }}"
188+
for pkg_dir in artifacts/cli-*/; do
189+
pkg_name=$(basename "$pkg_dir")
190+
echo "Publishing @openviking/$pkg_name@$VERSION..."
191+
chmod +x "$pkg_dir/bin/ov" 2>/dev/null || true
192+
cd "$pkg_dir"
193+
npm publish --access public
194+
cd "$GITHUB_WORKSPACE"
195+
done
196+
197+
- name: Publish wrapper package
192198
env:
193-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
199+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
200+
run: |
201+
VERSION="${{ steps.get_version.outputs.version }}"
202+
cd npm/cli
203+
204+
# Inject version into package.json
205+
node -e "
206+
const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8'));
207+
pkg.version = '$VERSION';
208+
for (const dep of Object.keys(pkg.optionalDependencies || {})) {
209+
pkg.optionalDependencies[dep] = '$VERSION';
210+
}
211+
require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
212+
"
213+
214+
echo "Publishing @openviking/cli@$VERSION..."
215+
npm publish --access public

crates/ov_cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ov_cli"
3-
version = "0.2.6"
3+
version = "0.0.0"
44
edition = "2024"
55
rust-version = "1.91.1"
66
authors = ["OpenViking Contributors"]

npm/cli/README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# @openviking/cli
2+
3+
Native CLI for [OpenViking](https://github.com/volcengine/openviking) — an agent-native context database for AI workflows.
4+
5+
Store, search, and retrieve context (memories, resources, embeddings) across conversations and agents.
6+
7+
## Install
8+
9+
```bash
10+
npm i -g @openviking/cli
11+
```
12+
13+
This installs the `ov` binary for your platform (macOS, Linux, Windows).
14+
15+
### Alternative install methods
16+
17+
```bash
18+
# via curl
19+
curl -fsSL https://openviking.tos-cn-beijing.volces.com/cli/install.sh | bash
20+
21+
# one-shot with npx
22+
npx @openviking/cli --help
23+
```
24+
25+
## Quick start
26+
27+
```bash
28+
# Check connectivity
29+
ov health
30+
31+
# Store context
32+
ov add-resource ./notes.md
33+
ov add-memory "key insight from today's debugging session"
34+
35+
# Retrieve context
36+
ov find "what did I learn about caching?"
37+
ov ls
38+
ov read /path/to/resource
39+
40+
# Semantic search
41+
ov search "authentication flow"
42+
ov grep "TODO"
43+
```
44+
45+
## Commands
46+
47+
### Data
48+
49+
| Command | Description |
50+
|---------|-------------|
51+
| `add-resource` | Add files or URLs into OpenViking |
52+
| `add-memory` | Store a memory in one shot |
53+
| `add-skill` | Add a skill from a directory or SKILL.md |
54+
| `ls` | List directory contents |
55+
| `tree` | Hierarchical tree view |
56+
| `read` | Read full file content |
57+
| `abstract` | Brief summary (L0) |
58+
| `overview` | Medium detail (L1) |
59+
| `write` | Write or append text content |
60+
| `find` | Semantic retrieval with scoring |
61+
| `search` | Context-aware retrieval (experimental) |
62+
| `grep` | Pattern search with regex |
63+
| `glob` | File glob pattern search |
64+
| `rm` | Remove a resource or directory |
65+
| `mv` | Move or rename a resource |
66+
| `stat` | Get resource metadata |
67+
| `get` | Download file to local path |
68+
| `session` | Manage sessions |
69+
| `export` / `import` | Backup and restore as .ovpack |
70+
71+
### Interactive
72+
73+
| Command | Description |
74+
|---------|-------------|
75+
| `tui` | Interactive file explorer |
76+
| `chat` | Chat with vikingbot agent |
77+
78+
### Status
79+
80+
| Command | Description |
81+
|---------|-------------|
82+
| `health` | Quick health check |
83+
| `status` | Show server components status |
84+
| `config` | Configuration management |
85+
| `version` | Show CLI and server version |
86+
| `task` | Track async processing tasks |
87+
88+
## Supported platforms
89+
90+
| Platform | Architecture | Package |
91+
|----------|-------------|---------|
92+
| macOS | Apple Silicon | `@openviking/cli-darwin-arm64` |
93+
| macOS | Intel | `@openviking/cli-darwin-x64` |
94+
| Linux | x64 | `@openviking/cli-linux-x64` |
95+
| Linux | ARM64 | `@openviking/cli-linux-arm64` |
96+
| Windows | x64 | `@openviking/cli-win32-x64` |
97+
98+
## Links
99+
100+
- [GitHub](https://github.com/volcengine/openviking)
101+
- [Documentation](https://github.com/volcengine/openviking#readme)
102+
103+
## License
104+
105+
Apache-2.0

npm/cli/bin/ov.mjs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env node
2+
import { execFileSync } from "node:child_process";
3+
import { createRequire } from "node:module";
4+
import { join } from "node:path";
5+
6+
const require = createRequire(import.meta.url);
7+
const platforms = {
8+
"darwin-arm64": "@openviking/cli-darwin-arm64",
9+
"darwin-x64": "@openviking/cli-darwin-x64",
10+
"linux-arm64": "@openviking/cli-linux-arm64",
11+
"linux-x64": "@openviking/cli-linux-x64",
12+
"win32-x64": "@openviking/cli-win32-x64",
13+
};
14+
15+
const key = `${process.platform}-${process.arch}`;
16+
const pkg = platforms[key];
17+
if (!pkg) {
18+
console.error(`Unsupported platform: ${key}`);
19+
process.exit(1);
20+
}
21+
22+
const ext = process.platform === "win32" ? ".exe" : "";
23+
const bin = join(require.resolve(`${pkg}/package.json`), "..", "bin", `ov${ext}`);
24+
25+
try {
26+
execFileSync(bin, process.argv.slice(2), { stdio: "inherit" });
27+
} catch (e) {
28+
process.exit(e.status ?? 1);
29+
}

npm/cli/bin/postinstall.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env node
2+
process.stderr.write(`
3+
╔═══════════════════════════════════════════════════╗
4+
║ OpenViking CLI installed ║
5+
╚═══════════════════════════════════════════════════╝
6+
7+
Usage: ov <command> [options]
8+
9+
Commands:
10+
ov health Check server connectivity
11+
ov search "query" Context-aware semantic search
12+
ov ls List directory contents
13+
ov read <uri> Read full file content
14+
ov add-resource <path> Add files or URLs
15+
ov add-memory "text" Store a memory
16+
ov config show Show current configuration
17+
18+
Run "ov --help" for the full command list.
19+
\n`);

0 commit comments

Comments
 (0)