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
73 changes: 73 additions & 0 deletions .github/workflows/release-pi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Release pi package

on:
push:
tags:
- 'pi-v*'
workflow_dispatch:
inputs:
publish:
description: Publish to npm (unchecked = dry run only)
type: boolean
required: false
default: false

permissions:
contents: read
id-token: write

concurrency:
group: release-pi
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org

- name: Read package metadata
id: pkg
run: |
echo "name=$(node -p \"require('./pi/package.json').name\")" >> "$GITHUB_OUTPUT"
echo "version=$(node -p \"require('./pi/package.json').version\")" >> "$GITHUB_OUTPUT"

- name: Validate release tag matches package version
if: github.event_name == 'push'
run: |
expected="pi-v${{ steps.pkg.outputs.version }}"
if [ "${GITHUB_REF_NAME}" != "$expected" ]; then
echo "::error title=Tag/version mismatch::Expected tag $expected for version ${{ steps.pkg.outputs.version }}, got ${GITHUB_REF_NAME}."
exit 1
fi

- name: Ensure npm version is not already published
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish)
run: |
if npm view "${{ steps.pkg.outputs.name }}@${{ steps.pkg.outputs.version }}" version >/dev/null 2>&1; then
echo "::error title=Version already published::${{ steps.pkg.outputs.name }}@${{ steps.pkg.outputs.version }} already exists on npm."
exit 1
fi

- name: Validate package contents
working-directory: pi
run: npm pack --dry-run

- name: Publish to npm
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish)
working-directory: pi
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Dry-run summary
if: github.event_name == 'workflow_dispatch' && !inputs.publish
run: |
echo "Dry run complete for ${{ steps.pkg.outputs.name }}@${{ steps.pkg.outputs.version }}."
echo "Re-run this workflow with publish=true to publish."
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,37 @@ Paste a screenshot in your browser, your agent gets the URL instantly.

## Available plugins

| Agent | Directory | Status |
|---|---|---|
| [pi](https://github.com/mariozechner/pi) | [`pi/`](pi/) | |
| [OpenCode](https://github.com/anomalyco/opencode) | [`opencode/`](opencode/) | |
| Agent | Directory | npm package | Install |
|---|---|---|---|
| [pi](https://github.com/mariozechner/pi) | [`pi/`](pi/) | `@modem-dev/glance-pi` | `pi install npm:@modem-dev/glance-pi` |
| [OpenCode](https://github.com/anomalyco/opencode) | [`opencode/`](opencode/) | — | See [`opencode/README.md`](opencode/README.md) |

## How it works

Each plugin creates a live session on glance.sh, gives you a URL to open, and waits for you to paste an image. The image URL is returned to the agent over SSE — no manual copy-paste needed.

```
```text
agent ──POST /api/session──▶ { id, url }
agent ──GET /api/session/<id>/events──▶ SSE (waiting…)
user ──opens /s/<id>, pastes image──▶ agent receives URL
```

Sessions are anonymous and ephemeral (10-minute TTL). Images expire after 30 minutes.

## Adding a new plugin
## Packaging policy

New plugins should be published as installable packages (npm where possible) with a one-command install path in their README.

Create a directory for your agent (e.g. `cursor/`, `cline/`) with:
Each plugin directory should include:

1. The integration code
2. A `README.md` with install instructions
1. Integration code
2. `README.md` with install / verify / update / remove steps
3. `package.json` (if the target agent supports package-based install)
4. Release automation (GitHub Actions workflow + documented version/tag convention)

## Adding a new plugin

Open a PR.
Create a directory for your agent (e.g. `cursor/`, `cline/`) with the files above and open a PR.

## License

Expand Down
68 changes: 61 additions & 7 deletions pi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,75 @@ Maintains a **persistent background session** on glance.sh. Paste an image anyti

## Install

Symlink or copy `glance.ts` into your pi extensions directory:
Recommended (npm package):

```bash
# symlink (recommended — stays up to date with git pulls)
ln -s "$(pwd)/glance.ts" ~/.pi/extensions/glance.ts
pi install npm:@modem-dev/glance-pi
```

If you are working from a local checkout instead:

```bash
# from this directory (agent-plugins/pi)
pi install .

# or copy
cp glance.ts ~/.pi/extensions/glance.ts
# from the main repo root
pi install ./agent-plugins/pi
```

Restart pi. The background session starts automatically.
Then restart pi or run `/reload`.

## How it works
## Verify

Run:

```text
/glance
```

You should see a session URL like `https://glance.sh/s/<id>`.

## Update / remove

```bash
pi update
pi remove npm:@modem-dev/glance-pi
```

For a local path install, remove that path from your pi settings (or run `pi remove` with the same path you installed).

## Publishing (maintainers)

Releases are automated via GitHub Actions.

Prerequisite: configure `NPM_TOKEN` in the `glance-agent-plugins` repository with publish access to `@modem-dev/glance-pi`.

1. Bump `version` in `pi/package.json`.
2. Commit and push to `main`.
3. Create and push a matching tag:

```bash
git tag pi-v0.1.0
git push origin pi-v0.1.0
```

The `Release pi package` workflow validates the tag/version match and publishes with npm provenance.
You can also run the workflow manually in dry-run mode from Actions.

## Manual install (legacy)

If you prefer manual file management, symlink or copy `glance.ts` into your pi extensions directory:

```bash
mkdir -p ~/.pi/agent/extensions
ln -s "$(pwd)/glance.ts" ~/.pi/agent/extensions/glance.ts
# or:
cp glance.ts ~/.pi/agent/extensions/glance.ts
```

## How it works

```text
pi starts
└─▶ create session on glance.sh
└─▶ connect SSE (background, auto-reconnect)
Expand Down
6 changes: 4 additions & 2 deletions pi/glance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
* - `glance` tool — the LLM can call it to request a screenshot;
* it surfaces the existing session URL and waits for a paste.
*
* Install: symlink or copy this file into your pi extensions directory,
* e.g. ~/.pi/extensions/glance.ts
* Install:
* - Recommended: `pi install npm:@modem-dev/glance-pi`
* - Local checkout: `pi install /path/to/glance-agent-plugins/pi`
* - Manual fallback: symlink/copy into ~/.pi/agent/extensions/glance.ts
*/

import { Type } from "@mariozechner/pi-ai";
Expand Down
37 changes: 37 additions & 0 deletions pi/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@modem-dev/glance-pi",
"version": "0.1.0",
"description": "glance.sh extension package for pi",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/modem-dev/glance-agent-plugins.git",
"directory": "pi"
},
"homepage": "https://github.com/modem-dev/glance-agent-plugins/tree/main/pi",
"bugs": {
"url": "https://github.com/modem-dev/glance-agent-plugins/issues"
},
"keywords": [
"pi-package",
"pi-extension",
"pi",
"glance",
"screenshot",
"agent"
],
"files": [
"glance.ts",
"README.md"
],
"pi": {
"extensions": [
"./glance.ts"
]
},
"peerDependencies": {
"@mariozechner/pi-ai": "*",
"@mariozechner/pi-coding-agent": "*",
"@mariozechner/pi-tui": "*"
}
}