
Security News
OpenCode User Hit with Hostile Backlash After Reporting Free AI Loophole
An OpenCode user faced harassment after reporting a free AI usage loophole, drawing a bitter backlash in a GitHub thread that has since been deleted.
@forge-glance/sdk
Advanced tools
GitHub & GitLab API client — REST, GraphQL, and real-time ActionCable subscriptions
Provider-agnostic SDK for GitHub & GitLab — types, REST/GraphQL clients, real-time subscriptions, and dashboard helpers. Works in any Node/Bun runtime.
npm install @forge-glance/sdk
# or
bun add @forge-glance/sdk
import { GitLabProvider } from '@forge-glance/sdk';
const provider = new GitLabProvider('https://gitlab.com', process.env.GITLAB_TOKEN!);
const user = await provider.validateToken();
const prs = await provider.fetchPullRequests();
Two built-in providers implement the GitProvider interface:
| Provider | Class | Capabilities |
|---|---|---|
| GitLab | GitLabProvider | Full: merge, rebase, approve, auto-merge, retry pipeline, re-review |
| GitHub | GitHubProvider | Core: merge, approve, rebase |
import { createProvider } from '@forge-glance/sdk';
// Auto-create the right provider by slug
const provider = createProvider('gitlab', 'https://gitlab.com', token);
| Method | Description |
|---|---|
validateToken() | Verify credentials, returns UserRef |
fetchPullRequests() | Fetch all MRs you authored, review, or are assigned to |
fetchSingleMR(path, iid, userId) | Fetch one MR by project path and IID |
fetchPullRequestByBranch(path, branch) | Find an open MR by source branch |
createPullRequest(input) | Create a new MR |
updatePullRequest(path, iid, input) | Update an existing MR |
mergePullRequest(path, iid, input?) | Merge an MR |
rebasePullRequest(path, iid) | Rebase an MR onto its target branch |
approvePullRequest(path, iid) | Approve an MR |
unapprovePullRequest(path, iid) | Remove your approval |
setAutoMerge(path, iid) | Enable auto-merge when pipeline passes |
cancelAutoMerge(path, iid) | Cancel auto-merge |
retryPipeline(path, pipelineId) | Retry a pipeline |
requestReReview(path, iid, usernames?) | Request re-review |
watchMR(path, iid, userId, onUpdate) | Real-time MR subscription (returns dispose()) |
fetchMRDiscussions(repoId, iid) | Fetch MR discussions and notes |
fetchBranchProtectionRules(path) | Fetch branch protection rules |
deleteBranch(path, branch) | Delete a branch |
createDashboardHigh-level factory that bundles real-time MR watching with pre-bound mutation actions. Returns a Dashboard object:
import { createDashboard } from '@forge-glance/sdk';
const { actions, subscribe, dispose } = createDashboard({
provider,
projectPath: 'group/project',
mrIid: 42,
userId
});
// actions are available immediately — no need to wait for the first update
await actions.merge();
await actions.approve();
// subscribe delivers real-time MRDashboardProps on each update
subscribe((mr) => {
console.log(mr.status, mr.pipeline?.status);
renderUI(mr, actions);
});
// When done, stop the subscription
dispose();
| Property | Type | Description |
|---|---|---|
actions | MRDashboardActions | Pre-bound mutation methods — available immediately |
subscribe(cb) | (cb: (mr: MRDashboardProps) => void) => void | Register a listener for real-time updates |
dispose() | () => void | Stop the subscription and clean up |
DashboardGroupPass an array of IIDs to watch multiple MRs over a single WebSocket:
const { actionsFor, subscribe, dispose } = createDashboard({
provider,
projectPath: 'group/project',
mrIid: [42, 43, 44, 45],
userId
});
subscribe((mrs) => {
for (const [iid, mr] of mrs) {
renderRow(mr, actionsFor(iid));
}
});
| Property | Type | Description |
|---|---|---|
actionsFor(iid) | (iid: number) => MRDashboardActions | Get actions for a specific MR |
subscribe(cb) | (cb: (mrs: Map<number, MRDashboardProps>) => void) => void | Real-time updates for all MRs |
dispose() | () => void | Stop all subscriptions |
getMRDashboardPropsLower-level helper that transforms a raw PullRequest into render-ready MRDashboardProps. Useful when you already have the MR data from fetchPullRequests() or fetchSingleMR():
import { getMRDashboardProps } from '@forge-glance/sdk';
const prs = await provider.fetchPullRequests();
const dashboards = prs.map(getMRDashboardProps);
// dashboards[0].status → 'mergeable' | 'blocked' | 'draft' | ...
// dashboards[0].mergeButton.visible, .disabled, .label
// dashboards[0].provider → 'gitlab' | 'github'
MRDashboardPropsPre-computed, UI-ready props — no conditional logic needed in the component layer:
| Field | Description |
|---|---|
provider | 'gitlab' or 'github' — use to pick brand icon |
iid, title, webUrl, state | Identity |
status | 'mergeable' | 'blocked' | 'draft' | 'merged' | 'closed' |
statusDetail | Specific blocker reason (e.g., 'CI_MUST_PASS', 'NEED_REBASE') |
pipeline | Pipeline status breakdown: passing, failing, running counts |
reviews | Reviewer state: required, given, remaining, approvedBy |
mergeButton | { visible, disabled, loading, label } |
rebaseButton | { visible, loading, label, behindBy } |
autoMergeButton | { visible, isActive, strategy, label, cancelLabel } |
blockers | Boolean flags: isDraft, hasConflicts, needsRebase, pipelineFailing, etc. |
diff | { additions, deletions, filesChanged } |
MRDashboardActionsPre-bound mutation methods — call without passing project path or IID:
| Action | Description |
|---|---|
merge(input?) | Merge the MR |
rebase() | Rebase onto target branch |
approve() | Approve the MR |
unapprove() | Remove approval |
setAutoMerge() | Enable auto-merge |
cancelAutoMerge() | Cancel auto-merge |
retryPipeline(id) | Retry a pipeline |
requestReReview(usernames?) | Request re-review |
can | Provider capability flags |
All watchMR calls on a single GitLabProvider instance share one WebSocket connection via ActionCable. Each MR subscribes 3 channels (merge status, approval state, reviewers) on the shared connection. The connection is ref-counted:
watchMR call → opens the WebSocketdispose() a watcher → unsubscribes that MR's channelsThis means watching 30 MRs uses 1 WebSocket with 90 channel subscriptions, not 30 separate connections.
createRealtimeWatcherGeneric self-healing subscription + polling module used internally by watchMR. Also exported for custom use:
All domain types are exported:
import type {
PullRequest,
MRDashboardProps,
MRDashboardActions,
Dashboard,
MRStatus,
Reviewer,
Pipeline,
PipelineJob,
DiffStats,
GitProvider,
ProviderCapabilities,
} from '@forge-glance/sdk';
FAQs
GitHub & GitLab API client — REST, GraphQL, and real-time ActionCable subscriptions
The npm package @forge-glance/sdk receives a total of 0 weekly downloads. As such, @forge-glance/sdk popularity was classified as not popular.
We found that @forge-glance/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
An OpenCode user faced harassment after reporting a free AI usage loophole, drawing a bitter backlash in a GitHub thread that has since been deleted.

Threat Research
/Security News
319 browser extensions installed by 13.4 million users hijack searches, capture queries, and collect referral payments from Yahoo and Bing.

Threat Research
Malicious Firefox extensions mimic Phantom, Jupiter, and Bitget wallets to steal recovery phrases and private keys, with one fetching its payload remotely.