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
84 changes: 84 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ on:
push:
branches: [main]

permissions:
contents: read

env:
DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }}
DAYTONA_API_URL: ${{ vars.DAYTONA_API_URL }}
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}

jobs:
Check:
name: Check
Expand All @@ -27,3 +35,79 @@ jobs:

- name: TypeScript typecheck
run: bun run typecheck

- name: Unit tests
run: bun test

- name: CLI smoke checks
run: |
bun run analyze -- --help
bun run start -- --help
bun run setup -- --help

BuildPackage:
name: Build Package Artifact
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: Check
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build package
run: bun run build

- name: Pack tarball
run: |
mkdir -p artifacts
npm pack --pack-destination artifacts
ls -la artifacts

- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: npm-package
path: artifacts/*.tgz
if-no-files-found: error

PackageE2E:
name: Package Install E2E
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: BuildPackage
steps:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Download package artifact
uses: actions/download-artifact@v4
with:
name: npm-package
path: artifacts

- name: Install package into clean project
run: |
mkdir e2e-install
cd e2e-install
npm init -y
npm install ../artifacts/*.tgz

- name: Run installed CLI binaries
run: |
cd e2e-install
./node_modules/.bin/opencode-sandboxed-research-analyze --help
./node_modules/.bin/opencode-sandboxed-research-start --help
./node_modules/.bin/opencode-sandboxed-research-setup --help
70 changes: 70 additions & 0 deletions .github/workflows/daytona-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Daytona E2E

on:
workflow_dispatch:
inputs:
repo_url:
description: "Repository URL to analyze"
required: false
default: "https://github.com/octocat/Hello-World"
model:
description: "Model to use"
required: false
default: "zai-coding-plan/glm-4.7-flash"
analyze_timeout_sec:
description: "Analyze timeout seconds"
required: false
default: "600"
install_timeout_sec:
description: "Install timeout seconds"
required: false
default: "300"

permissions:
contents: read

env:
DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }}
DAYTONA_API_URL: ${{ vars.DAYTONA_API_URL }}
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}

jobs:
E2E:
name: Run Daytona Analyze E2E
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Validate required environment
run: |
if [ -z "${DAYTONA_API_KEY:-}" ]; then
echo "DAYTONA_API_KEY is required" >&2
exit 1
fi

- name: Run analyze e2e
run: |
mkdir -p .memory/daytona-e2e
bun run analyze -- \
--out-dir .memory/daytona-e2e/findings \
--model "${{ inputs.model }}" \
--install-timeout-sec "${{ inputs.install_timeout_sec }}" \
--analyze-timeout-sec "${{ inputs.analyze_timeout_sec }}" \
"${{ inputs.repo_url }}"

- name: Upload findings artifact
uses: actions/upload-artifact@v4
with:
name: daytona-e2e-findings
path: .memory/daytona-e2e/findings
if-no-files-found: error
98 changes: 98 additions & 0 deletions .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Publish Package

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
Publish:
name: Publish To GitHub Packages
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Validate package
run: |
bun run check
bun run typecheck
bun test
bun run build

- name: Publish package
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm publish --registry https://npm.pkg.github.com

VerifyInstall:
name: Verify Registry Install
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: Publish
permissions:
contents: read
packages: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Configure npm for GitHub Packages
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npm config set @shpitdev:registry https://npm.pkg.github.com
npm config set //npm.pkg.github.com/:_authToken "$NODE_AUTH_TOKEN"
npm config set always-auth true

- name: Install published package
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")
PACKAGE_REF="${PACKAGE_NAME}@${PACKAGE_VERSION}"

mkdir -p e2e-install
cd e2e-install
npm init -y

for attempt in 1 2 3 4 5 6; do
if npm install "$PACKAGE_REF"; then
break
fi
if [ "$attempt" -eq 6 ]; then
echo "Failed to install $PACKAGE_REF after retries" >&2
exit 1
fi
sleep 10
done

- name: Run installed CLI binaries
run: |
cd e2e-install
./node_modules/.bin/opencode-sandboxed-research-analyze --help
./node_modules/.bin/opencode-sandboxed-research-start --help
./node_modules/.bin/opencode-sandboxed-research-setup --help
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ node_modules/
dist/
coverage/
.turbo/
.memory/

# Logs
*.log
Expand Down
1 change: 1 addition & 0 deletions .ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!.memory
69 changes: 66 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ This project automates Daytona sandbox setup and OpenCode execution.

- [What is this?](#what-is-this)
- [Prerequisites](#prerequisites)
- [Install On New Machine](#install-on-new-machine)
- [Quick Start](#quick-start)
- [Installer & Obsidian Cataloging](#installer--obsidian-cataloging)
- [Commands](#commands)
- [Repository Audit Workflow](#repository-audit-workflow)
- [Output Layout](#output-layout)
Expand All @@ -42,6 +44,24 @@ This project automates Daytona sandbox setup and OpenCode execution.
- `DAYTONA_API_KEY`
- `DAYTONA_API_URL` for self-hosted Daytona (example: `https://daytona.example.com/api`)
- Optional but recommended: `OPENCODE_SERVER_PASSWORD`
- Optional: `obsidian` command in `PATH` (for Obsidian note cataloging/open)

---

## Install On New Machine

Use the bootstrap installer:

```bash
curl -fsSL https://raw.githubusercontent.com/shpitdev/opencode-sandboxed-ad-hoc-research/main/scripts/install-gh-package.sh | bash
```

It will:

- ask for (or reuse) a GitHub token with `read:packages`
- configure `~/.npmrc` for GitHub Packages
- install `@shpitdev/opencode-sandboxed-ad-hoc-research` globally
- launch the guided setup flow for Daytona/model credentials

---

Expand All @@ -58,13 +78,50 @@ Stop with `Ctrl+C`.

---

## Installer & Obsidian Cataloging

Run the guided installer:

```bash
bun run setup
```

It sets up:

- `~/.config/opencode/shpit.toml` for shared preferences
- `~/.config/opencode/.env` for optional credential storage

No provider API key is required if you only use free `opencode/*` models (for example `opencode/minimax-m2.5-free`).

`analyze` automatically catalogs findings to Obsidian when enabled in `shpit.toml`.

Example config:

```toml
[obsidian]
enabled = true
command = "obsidian"
vault_path = "/absolute/path/to/vault"
notes_root = "Research/OpenCode"
catalog_mode = "date" # date | repo
open_after_catalog = false
```

Project-level `shpit.toml` or `.shpit.toml` overrides global config.
The configured command must be `obsidian` (not `obs`).

---

## Commands

| Command | Purpose |
|---|---|
| `scripts/install-gh-package.sh` | Bootstrap install from GitHub Packages on a new machine |
| `bun run setup` | Guided setup for shared config/env and Obsidian cataloging |
| `bun run start` | Launch OpenCode web in a Daytona sandbox |
| `bun run analyze -- --input example.md` | Analyze repos listed in a file |
| `bun run analyze -- <url1> <url2>` | Analyze direct repo URLs |
| `bun run build` | Compile distributable CLI files into `dist/` |
| `bun run lint` | Lint with Biome |
| `bun run format` | Format with Biome |
| `bun run check` | Run Biome checks |
Expand Down Expand Up @@ -94,17 +151,22 @@ bun run start -- --no-open

### Defaults and behavior

- Default model: `opencode/gpt-5-nano`
- Default model selection:
- Standard: `zai-coding-plan/glm-4.7-flash`
- Vision mode (`--vision`): `zai-coding-plan/glm-4.6v`
- Override with `--model`, `--variant`, `OPENCODE_ANALYZE_MODEL`, or `OPENCODE_ANALYZE_VARIANT`
- Auto-installs missing `git` and `node/npm` inside sandbox
- Forwards provider env vars (`OPENAI_*`, `ANTHROPIC_*`, `XAI_*`, `OPENROUTER_*`, etc.)
- Forwards provider env vars (`OPENAI_*`, `ANTHROPIC_*`, `XAI_*`, `OPENROUTER_*`, `ZHIPU_*`, `MINIMAX_*`, etc.)
- Syncs local OpenCode config files from `~/.config/opencode` when present
- Auto-catalogs findings into Obsidian when enabled via `shpit.toml`

### Examples

```bash
bun run analyze -- --input example.md
bun run analyze -- https://github.com/owner/repo-one https://github.com/owner/repo-two
bun run analyze -- --out-dir findings --model openai/gpt-5 --target us
bun run analyze -- --out-dir findings --model zai-coding-plan/glm-4.7-flash --target us
bun run analyze -- --vision
bun run analyze -- --analyze-timeout-sec 3600 --keep-sandbox
```

Expand Down Expand Up @@ -141,6 +203,7 @@ Project config files:
- `biome.json`
- `.zed/settings.json`
- `.zed/tasks.json`
- `tsconfig.build.json`

---

Expand Down
2 changes: 2 additions & 0 deletions bin/analyze.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
import "../dist/analyze-repos.js";
Loading