npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

node-gman

v1.1.0

Published

TypeScript/Node.js client SDK and CLI for the g-mand trade daemon

Readme

node-gman

TypeScript/Node.js SDK for g-mand — TF2 trading daemon.

Installation

npm install node-gman

Quick Start

import { GManClient, TradeOfferManagerAdapter, SteamUserAdapter } from 'node-gman';

// Connect to g-mand daemon
const client = new GManClient({
  netType: 'tcp',           // 'tcp' or 'unix'
  address: '127.0.0.1:50051',
});

// Check status
const status = await client.getStatus();
console.log(`Steam ID: ${status.steam_id}, Connected: ${status.connected}`);

// Create adapters
const steamUser = new SteamUserAdapter(client);
const tradeManager = new TradeOfferManagerAdapter(client, { pollInterval: 30000 });

// Handle new offers
tradeManager.on('newOffer', async (offer) => {
  console.log(`New offer from ${offer.partner}`);
  
  // Accept the offer
  await client.execAction(440, 'accept-offer', { offer_id: offer.tradeofferid });
});

// Start polling
tradeManager.startPolling();

Connection

Via environment variables

GMAN_IPC_NET=tcp
GMAN_IPC_ADDR=127.0.0.1:50051

Via constructor

const client = new GManClient({
  netType: 'unix',
  address: '/home/user/.config/gman/gman.sock',
  autoLaunch: true,            // Spawn daemon automatically if it's not running
  daemonPath: './bin/g-mand'   // Optional: specify path to g-mand binary
});

Auto-detection

  • Windows: tcp://127.0.0.1:50051
  • Linux/macOS: unix://~/.config/gman/gman.sock

Classes

GManClient

Main gRPC client for communicating with g-mand.

const client = new GManClient(options?);

Methods:

| Method | Description | |---|---| | getStatus() | Connection status | | playGame(appid) | Launch a game | | exitGame() | Exit the game | | execAction(appid, action, params) | Execute an action | | streamEvents() | Stream events | | updateManualPrices(prices) | Update prices | | freeMemory() | Free memory | | stopDaemon() | Stop daemon | | guardCode() | Steam Guard code | | guardStatus() | Guard status | | guardList() | List confirmations | | guardRespond(id, accept) | Respond to confirmation | | guardImport(...) | Import Guard secrets | | close() | Close connection |

SteamUserAdapter

Adapter for Steam connection (emulates steam-user).

const steamUser = new SteamUserAdapter(client);

Events:

  • loggedOn — successful login
  • webSession — web session established
  • error — error occurred

Methods:

  • gamesPlayed(appid) — launch a game
  • chatMessage(steamID, message) — send a message

TeamFortress2Adapter

Adapter for TF2 Game Coordinator (emulates @tf2autobot/tf2).

const tf2 = new TeamFortress2Adapter(client);

Properties:

  • haveGCSession — whether connected to GC

Events:

  • connectedToGC — connected to GC
  • disconnectedFromGC — disconnected from GC
  • itemAcquired — item received
  • itemRemoved — item removed
  • itemChanged — item changed

Methods:

  • craft(assetids, recipe?) — craft items
  • useItem(assetid) — use an item
  • deleteItem(assetid) — delete an item
  • sortBackpack(type) — sort backpack

TradeOfferManagerAdapter

Adapter for managing trade offers. Uses real-time gRPC event streaming (StreamEvents from the daemon) as the primary transport for instant updates, and falls back to polling for maximum reliability.

const tradeManager = new TradeOfferManagerAdapter(client, {
  pollInterval: 30000, // polling interval in ms (fallback backup)
});

Properties:

  • pollData — polling data
  • pollInterval — polling interval

Events:

  • newOffer — new incoming offer (emitted in real-time)
  • offerChanged — offer status changed (emitted in real-time)
  • poll — polling data updated
  • error — error occurred

Methods:

  • startPolling() — start real-time event streaming subscription and backup polling interval
  • stopPolling() — unsubscribe from event streaming and stop polling interval
  • client.execAction(...) — direct g-mand call

SteamCommunityAdapter

Adapter for Steam Community (emulates @tf2autobot/steamcommunity). Supports web session cookie tracking and synchronization.

const community = new SteamCommunityAdapter(client, { steamID: '...' });

Methods:

  • setCookie(cookie) — set/track custom cookie string
  • setCookies(cookies) — set/track custom cookies array
  • getWebSession(callback) — retrieve active web session ID and cookies
  • getWebSessionSync() — synchronously retrieve active web session ID and cookies

Types

interface TradeOffer {
  tradeofferid: string;
  partner: string;
  trade_offer_state: number;
  items_to_give?: TradeOfferItem[];
  items_to_receive?: TradeOfferItem[];
  message?: string;
  data?: Record<string, unknown>;
}

interface TradeOfferItem {
  appid: number;
  contextid: string;
  assetid: string;
  amount: number;
}

interface PollData {
  sent: Record<string, number>;
  received: Record<string, number>;
  offerData: Record<string, Record<string, unknown>>;
}

enum ETradeOfferState {
  Invalid = 1,
  Active = 2,
  Accepted = 3,
  Countered = 4,
  Expired = 5,
  Cancelled = 6,
  Declined = 7,
  InvalidItems = 8,
  CreatedNeedsConfirmation = 9,
  InEscrow = 10,
}

g-mand Actions

Available actions via client.execAction(440, action, params):

Trading

| Action | Params | Description | |---|---|---| | send-offer | offer_params (JSON) | Send trade offer | | accept-offer | offer_id | Accept offer | | decline-offer | offer_id | Decline offer | | cancel-offer | offer_id | Cancel offer | | check-escrow | offer (JSON) | Check escrow | | active-offers | — | Active incoming offers | | active-sent-offers | — | Active outgoing offers |

Inventory

| Action | Params | Description | |---|---|---| | inventory | — | Get inventory | | get-partner-inventory | partner_id | Partner's inventory | | item-details | item_id | Item details | | sort-backpack | type, sort_type | Sort backpack |

Crafting

| Action | Params | Description | |---|---|---| | craft | recipe, items (JSON) | Craft items | | craft-metal | type | Combine metal | | smelt-weapons | class | Smelt weapons | | condense-metal | — | Condense metal | | make-change | target_defindex, target_count | Break down metal |

Other

| Action | Params | Description | |---|---|---| | send-chat | steam_id, message | Send chat message | | price-check | sku | Check item price | | backpack-value | — | Backpack value | | delete-item | item_id | Delete item | | use-item | item_id | Use item | | schema | — | Get schema |

CLI

# Install
npm install -g node-gman

# Daemon status
gmanctl-node status

# Launch TF2
gmanctl-node play 440

# Send a message
gmanctl-node exec 440 send-chat steam_id=76561198000000000 message=Hello

# Check price
gmanctl-node exec 440 price-check sku=5021;6

# Stop daemon
gmanctl-node stop

# Auto-migrate credentials and secrets from current folder (.env or config.json)
gmanctl-node migrate

Example: Simple Bot

import { GManClient, TradeOfferManagerAdapter, SteamUserAdapter, TeamFortress2Adapter } from 'node-gman';

async function main() {
  const client = new GManClient();
  const status = await client.getStatus();
  
  if (!status.connected) {
    console.error('g-mand is not connected to Steam');
    process.exit(1);
  }

  const steamUser = new SteamUserAdapter(client);
  const tradeManager = new TradeOfferManagerAdapter(client);
  const tf2 = new TeamFortress2Adapter(client);

  // Wait for TF2 GC connection
  await new Promise<void>((resolve) => {
    if (tf2.haveGCSession) resolve();
    else tf2.once('connectedToGC', () => resolve());
  });

  console.log('Bot started');

  tradeManager.on('newOffer', async (offer) => {
    console.log(`Offer from ${offer.partner}`);
    
    try {
      // Accept all offers (example)
      await client.execAction(440, 'accept-offer', { 
        offer_id: offer.tradeofferid 
      });
      console.log(`Offer ${offer.tradeofferid} accepted`);
      
      // Send thank you message
      await client.execAction(440, 'send-chat', {
        steam_id: offer.partner,
        message: 'Thanks for the trade!',
      });
    } catch (err) {
      console.error('Error:', err);
    }
  });

  tradeManager.startPolling();
}

main();

Security & Session Isolation

To keep Steam accounts highly secure, sensitive session tokens (cookies) and shared secrets are never exported over the gRPC / IPC channels to the JS client.

  • All authentication session cookies are kept strictly in g-mand daemon memory space.
  • The JS emulators (steamcommunity and tradeoffer-manager) route HTTP requests to the daemon via ExecRequest.
  • The daemon automatically injects the proper cookies and updates the sessionid parameter on the fly for every request, maintaining seamless compatibility with external frameworks (like tf2autobot) while minimizing the attack surface.

If you really need to access the daemon's IPC channel directly, you can:

  1. Execute a GET request via client.execRequest on any Steam page (e.g., /my).
  2. In the returned HTTP headers (Headers), intercept the new Set-Cookie headers that Steam, and parse them.

Drop-in Subpackages

To simplify the migration of existing bots (such as tf2autobot), node-gman includes a set of drop-in subpackage replacements in the packages/ directory. These packages fully emulate the API of their original Node.js counterparts, routing actions to the g-mand daemon or resolving them locally:

  • @node-gman/steam-totp — replacement for steam-totp (generates 2FA codes locally or via the daemon).
  • @node-gman/steam-user — replacement for steam-user (Steam connection via g-mand).
  • @node-gman/steamcommunity — replacement for steamcommunity (community web sessions).
  • @node-gman/tf2 — replacement for @tf2autobot/tf2 (TF2 Game Coordinator interaction).
  • @node-gman/tradeoffer-manager — replacement for @tf2autobot/tradeoffer-manager (real-time trade offers).
  • @node-gman/tf2-sku — replacement for @tf2autobot/tf2-sku (item SKU parsing and generation).
  • @node-gman/tf2-currencies — replacement for @tf2autobot/tf2-currencies (TF2 currency math and formatting).

Using in Existing Projects

You can drop these replacements into your existing project's package.json using npm aliases:

"dependencies": {
  "steam-totp": "npm:@node-gman/steam-totp@^1.1.0",
  "steam-user": "npm:@node-gman/steam-user@^1.1.0",
  "@tf2autobot/tradeoffer-manager": "npm:@node-gman/tradeoffer-manager@^1.1.0",
  "@tf2autobot/tf2": "npm:@node-gman/tf2@^1.1.0",
  "@tf2autobot/steamcommunity": "npm:@node-gman/steamcommunity@^1.1.0",
  "@tf2autobot/tf2-sku": "npm:@node-gman/tf2-sku@^1.1.0",
  "@tf2autobot/tf2-currencies": "npm:@node-gman/tf2-currencies@^1.1.0"
}

Build & Tests

The library uses static type generation from protobuf files.

# Generate types and compile TypeScript to dist/
npm run build

# Run Jest unit test suite
npm run test

License

BSD-3-Clause