Skip to content

Commit c0ddcc3

Browse files
authored
Merge pull request #20 from AxmeAI/feat/publish-and-install-20260407
feat: publish workflows, native installer, per-repo .mcp.json
2 parents 1efd477 + 11a9b67 commit c0ddcc3

File tree

6 files changed

+248
-17
lines changed

6 files changed

+248
-17
lines changed

.github/workflows/publish-npm.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: publish-npm
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
tags:
7+
- "v*"
8+
9+
jobs:
10+
publish:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
id-token: write
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Node
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: "20"
23+
registry-url: "https://registry.npmjs.org"
24+
cache: "npm"
25+
26+
- name: Install dependencies
27+
run: npm ci
28+
29+
- name: Build
30+
run: npm run build
31+
32+
- name: Type check
33+
run: npx tsc --noEmit
34+
35+
- name: Publish to npm
36+
run: npm publish --access public
37+
env:
38+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: release-binary
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
tags:
7+
- "v*"
8+
9+
jobs:
10+
build:
11+
strategy:
12+
matrix:
13+
include:
14+
- os: ubuntu-latest
15+
target: linux-x64
16+
node-arch: x64
17+
- os: ubuntu-latest
18+
target: linux-arm64
19+
node-arch: arm64
20+
- os: macos-latest
21+
target: darwin-arm64
22+
node-arch: arm64
23+
- os: macos-latest
24+
target: darwin-x64
25+
node-arch: x64
26+
27+
runs-on: ${{ matrix.os }}
28+
permissions:
29+
contents: write
30+
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
35+
- name: Setup Node
36+
uses: actions/setup-node@v4
37+
with:
38+
node-version: "20"
39+
cache: "npm"
40+
41+
- name: Install dependencies
42+
run: npm ci
43+
44+
- name: Build
45+
run: npm run build
46+
47+
- name: Create standalone bundle
48+
run: |
49+
mkdir -p release
50+
# Bundle everything into a single file with node shebang
51+
npx esbuild dist/cli.mjs --bundle --platform=node --target=node20 \
52+
--outfile=release/axme-code-${{ matrix.target }} \
53+
--banner:js='#!/usr/bin/env node'
54+
chmod +x release/axme-code-${{ matrix.target }}
55+
56+
- name: Upload artifact
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: axme-code-${{ matrix.target }}
60+
path: release/axme-code-${{ matrix.target }}
61+
62+
release:
63+
needs: build
64+
runs-on: ubuntu-latest
65+
permissions:
66+
contents: write
67+
steps:
68+
- name: Download all artifacts
69+
uses: actions/download-artifact@v4
70+
with:
71+
path: artifacts
72+
73+
- name: Create GitHub Release
74+
uses: softprops/action-gh-release@v2
75+
with:
76+
files: artifacts/*/axme-code-*
77+
generate_release_notes: true

README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,26 @@ AXME Code fixes all of this. You just work with Claude Code as usual - AXME Code
2222

2323
## Quick Start
2424

25+
### Option A: npm (recommended)
26+
2527
```bash
26-
# Install globally
2728
npm install -g @axme/code
29+
```
2830

29-
# Initialize in your project (or workspace root for multi-repo)
30-
cd your-project
31-
axme-code setup
31+
### Option B: Native binary (no Node.js required)
32+
33+
```bash
34+
curl -fsSL https://raw.githubusercontent.com/AxmeAI/axme-code/main/install.sh | bash
35+
```
36+
37+
Or specify a version: `curl -fsSL ... | bash -s v0.1.0`
38+
39+
### Setup
3240

33-
# That's it. Use Claude Code as usual:
34-
claude
41+
```bash
42+
cd your-project # or workspace root for multi-repo
43+
axme-code setup
44+
claude # that's it - use Claude Code as usual
3545
```
3646

3747
`axme-code setup` does three things:

install.sh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
REPO="AxmeAI/axme-code"
5+
INSTALL_DIR="${AXME_INSTALL_DIR:-$HOME/.local/bin}"
6+
7+
# Detect OS and architecture
8+
detect_platform() {
9+
local os arch
10+
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
11+
arch="$(uname -m)"
12+
13+
case "$os" in
14+
linux) os="linux" ;;
15+
darwin) os="darwin" ;;
16+
*) echo "Unsupported OS: $os" >&2; exit 1 ;;
17+
esac
18+
19+
case "$arch" in
20+
x86_64|amd64) arch="x64" ;;
21+
aarch64|arm64) arch="arm64" ;;
22+
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;;
23+
esac
24+
25+
echo "${os}-${arch}"
26+
}
27+
28+
# Get latest release tag from GitHub API
29+
get_latest_version() {
30+
local url="https://api.github.com/repos/${REPO}/releases/latest"
31+
if command -v curl &>/dev/null; then
32+
curl -fsSL "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//'
33+
elif command -v wget &>/dev/null; then
34+
wget -qO- "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//'
35+
else
36+
echo "Neither curl nor wget found" >&2; exit 1
37+
fi
38+
}
39+
40+
# Download binary
41+
download() {
42+
local url="$1" dest="$2"
43+
if command -v curl &>/dev/null; then
44+
curl -fsSL -o "$dest" "$url"
45+
else
46+
wget -qO "$dest" "$url"
47+
fi
48+
}
49+
50+
main() {
51+
local platform version download_url tmp
52+
53+
platform="$(detect_platform)"
54+
echo "Detected platform: ${platform}"
55+
56+
if [ -n "${1:-}" ]; then
57+
version="$1"
58+
else
59+
echo "Fetching latest release..."
60+
version="$(get_latest_version)"
61+
fi
62+
63+
if [ -z "$version" ]; then
64+
echo "Could not determine latest version. Specify version: ./install.sh v0.1.0" >&2
65+
exit 1
66+
fi
67+
68+
echo "Installing axme-code ${version} (${platform})..."
69+
70+
download_url="https://github.com/${REPO}/releases/download/${version}/axme-code-${platform}"
71+
72+
tmp="$(mktemp)"
73+
trap 'rm -f "$tmp"' EXIT
74+
75+
download "$download_url" "$tmp"
76+
77+
mkdir -p "$INSTALL_DIR"
78+
mv "$tmp" "${INSTALL_DIR}/axme-code"
79+
chmod +x "${INSTALL_DIR}/axme-code"
80+
81+
echo ""
82+
echo "Installed axme-code to ${INSTALL_DIR}/axme-code"
83+
84+
if ! echo "$PATH" | tr ':' '\n' | grep -qx "$INSTALL_DIR"; then
85+
echo ""
86+
echo "Add to your PATH:"
87+
echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
88+
fi
89+
90+
echo ""
91+
echo "Get started:"
92+
echo " cd your-project"
93+
echo " axme-code setup"
94+
}
95+
96+
main "$@"

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"build": "node build.mjs",
1212
"start": "node dist/server.js",
1313
"dev": "tsx src/cli.ts",
14-
"test": "node --test --experimental-strip-types test/*.test.ts",
14+
"test": "tsx --test test/*.test.ts",
1515
"lint": "tsc --noEmit"
1616
},
1717
"engines": {
@@ -34,5 +34,6 @@
3434
"url": "https://github.com/AxmeAI/axme-code.git"
3535
},
3636
"license": "MIT",
37-
"keywords": ["mcp", "claude-code", "ai-agent", "developer-tools"]
37+
"keywords": ["mcp", "claude-code", "ai-agent", "developer-tools"],
38+
"files": ["dist", "README.md", "LICENSE"]
3839
}

src/cli.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,25 @@ async function main() {
307307
for (const e of result.errors) console.log(` Warning: ${e}`);
308308
}
309309

310-
// Create or update .mcp.json
311-
const mcpPath = join(projectPath, ".mcp.json");
312-
let mcpConfig: Record<string, any> = {};
313-
if (existsSync(mcpPath)) {
314-
try { mcpConfig = JSON.parse(readFileSync(mcpPath, "utf-8")); } catch { mcpConfig = {}; }
310+
// Create or update .mcp.json (workspace root + each child repo)
311+
const mcpEntry = { command: "axme-code", args: ["serve"] };
312+
const mcpPaths = [projectPath];
313+
if (isWorkspace) {
314+
for (const p of ws.projects) {
315+
mcpPaths.push(join(projectPath, p.path));
316+
}
317+
}
318+
for (const dir of mcpPaths) {
319+
const mcpPath = join(dir, ".mcp.json");
320+
let mcpConfig: Record<string, any> = {};
321+
if (existsSync(mcpPath)) {
322+
try { mcpConfig = JSON.parse(readFileSync(mcpPath, "utf-8")); } catch { mcpConfig = {}; }
323+
}
324+
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
325+
mcpConfig.mcpServers.axme = mcpEntry;
326+
writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
315327
}
316-
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
317-
mcpConfig.mcpServers.axme = { command: "axme-code", args: ["serve"] };
318-
writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
319-
console.log(` .mcp.json: updated`);
328+
console.log(` .mcp.json: updated (${mcpPaths.length} locations)`);
320329

321330
// Generate CLAUDE.md
322331
generateClaudeMd(projectPath, isWorkspace);

0 commit comments

Comments
 (0)