Skip to content
menicosiaPublic

About

Look up people in Microsoft Graph, enrich career history via People Data Labs, and resolve GitHub identities.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

con — CONSIDER people

Command-line tool inspired by the DikuMUD CONSIDER command. Look up people in Microsoft Graph, enrich career history via People Data Labs, and resolve GitHub identities.

See PLAN.md for design details.

Why con?

Answering a simple “who is this person?” often means opening the corporate directory and LinkedIn, running the same search twice, and mentally joining the person's role, reporting chain, location, and employment history. con does that identity resolution and aggregation in one command.

Keeping the workflow in the terminal also avoids a less obvious productivity cost: opening LinkedIn for a two-minute lookup and losing the next fifteen minutes to the feed. con returns the relevant facts and leaves you in your development context.

Examples

An AMD colleague can be resolved in the directory and enriched in one pass:

$ con -l +2 "mark papermaster"
Papermaster, Mark (EVP & Chief Technology Officer), located in Austin, TX, B100.T.304
Reporting chain:
  -> Su, Lisa (Chair & Chief Executive Officer)

LinkedIn (PDL): mark papermaster · chief technology officer and executive vice president
  amd · santa clara, california, united states · in role since 2019-01
  Works at configured company: yes (current).
  Shared employers: amd (2025-08–present)
  Roles:
    - board member @ penguin solutions (2022-09–present)
    - chief technology officer and executive vice president @ amd (2019-01–present)
  linkedin.com/in/mark-papermaster-66914925

For someone outside the corporate directory, --at supplies evidence that narrows the PDL lookup:

$ con -l --at microsoft +2 "mustafa suleyman"
No match for 'mustafa suleyman' in the Microsoft 365 directory; they do not appear to be a coworker.

LinkedIn (PDL): mustafa suleyman · executive vice president, frontier models and strategy
  microsoft · redmond, washington, united states
  Works at configured company: no match in history.
  Roles:
    - executive vice president, frontier models and strategy @ microsoft
    - chief executive officer, microsoft ai @ microsoft

These examples are abbreviated. Directory details depend on the tenant, and PDL is an independently maintained dataset whose titles and dates can lag the live LinkedIn profile.

What you need

  • Microsoft 365: a corporate account that can read your tenant directory. Run con auth microsoft once to complete device-code authentication. This is required for normal name lookups.
  • LinkedIn-style career data: a People Data Labs API key for -l, stored in [pdl] api_key or PDL_API_KEY. con does not ask for or use LinkedIn credentials.
    • Note: People Data Labs offers a free "Testing" tier which offers 100 credits/month.
  • GitHub: public lookups work anonymously, but authentication avoids the lower anonymous rate limit. Use [github] token, CON_GITHUB_TOKEN/GITHUB_TOKEN, or an existing gh auth login session.
  • Runtime: Python 3.10+ and either uv or pip.

Usage

con [-l] [+N] "firstname lastname"
con -g [-l] [+N] "github-handle"
con --json ...
con --md ...
con config
con auth microsoft
Flag Meaning
(default) MS Graph people search + manager chain (depth 2)
-l PDL enrichment (career / overlap)
-g Treat query as GitHub login
--at COMPANY Company qualifier for -l; required for non-coworkers
+N How deep to go in every list returned (see below). Default +2. +0 = all the way
--json / --md Machine or markdown output

Depth (+N)

con is a research tool, not a per-source data manipulator. One number answers "how deep history do you want?" and applies to every list eventually returned:

  • Directory: manager / reporting-chain length
  • PDL (-l): most recent employment roles (current and past treated the same)

Defaults to 2 when omitted. +0 means full depth (walk to CEO / all roles). A value at or above the length of the list simply returns the whole list.

Exit codes

Code Meaning
0 The lookup ran, including when the person is simply not in the directory (not every name is a coworker) or a GitHub handle does not exist
1 Every requested source failed to answer (not authenticated, network/API error)
2 Usage problem or missing configuration

PDL credit exhaustion never changes the exit code: -l degrades to a notice while directory and GitHub results still print. The same applies when a PDL capability is missing from your plan or no profile matches.

Examples:

con "Marco Nicosia"
con -l +3 "Mark Papermaster"
con -g menicosia
con -g -l menicosia
con -l --json "Mustafa Suleyman"

Agent skill

See skill/SKILL.md — wrap con --json for Cursor/Claude.

Install

cd /path/to/con

# Install with uv
uv venv
source .venv/bin/activate
uv pip install -e .

# Or install with pip
python3 -m pip install -e .

# or without install:
PYTHONPATH=src python3 -m con.cli --help

Requires Python 3.10+. No third-party runtime dependencies (stdlib only).

Build distributions

uv build

This creates the standard artifacts in dist/:

  • con-<version>-py3-none-any.whl
  • con-<version>.tar.gz

Install the wheel directly with:

uv pip install dist/con-<version>-py3-none-any.whl

Configure

con config

Writes ~/.con.ini. If both ~/.con.ini and ~/.con.json exist, INI wins and JSON is ignored (with a warning).

Minimal example:

[company]
name = Advanced Micro Devices, Inc.
linkedin_name = AMD

[user]
display_name = Marco Nicosia
email = marco.nicosia@amd.com
linkedin_url = https://www.linkedin.com/in/menicosia

[pdl]
api_key = YOUR_PDL_KEY
billing_cycle_start = 2024-01-15

[microsoft]
token_path = ~/.config/microsoft-graph/token.json

[github]
token =

[output]
default_format = human

Microsoft Graph

con auth microsoft

con independently implements Microsoft Graph authentication and API calls using Python's standard library. It shares the same token-file and authentication pattern as AMD's m365 skills (~/.config/microsoft-graph/token.json), so you can re-use an existing token.

People Data Labs (LinkedIn-style enrichment)

  • Free tier allotments are per product (e.g. ~100 Person Enrich, ~100 Person Search, only ~5 Person Identify per month).
  • Contact fields may be obfuscated on free plans; con does not need them.
  • When credits are exhausted, -l prints LinkedIn enrichment not available (with replenishment date) and still returns directory / GitHub results.
  • Set billing_cycle_start to your plan start date so replenishment uses the monthly anniversary; otherwise the date is estimated as the next calendar month start (UTC).

Developer note: Only an HTTP 402 means credits are actually spent. The x-totallimit-remaining header is recorded for reference but never blocks a request: PDL reports it per product, so an endpoint your plan excludes returns 0 while your Person Enrich allotment is untouched. con never disables an endpoint on its own — it asks the API every time, since a 402 costs nothing. Rate limiting (429) is reported separately from exhaustion.

Which APIs con uses, and what they cost

Step API Cost
1. Work email (directory hits only) Person Enrich 1 credit per match; a 404 no-match is free
1b. Qualified lookup Person Enrich 1 credit per match; a 404 no-match is free
2. Same-name fallback Person Search 1 credit per record returned; zero results are free
— Person Identify Not used. Free plans get only ~5 credits/month

When the corporate directory supplies a work email, that is tried first: email is the strongest identifier PDL accepts and needs no name at all, so it still lands when the directory's spelling differs from the profile's (nicknames, married names, transliterations). It costs nothing extra — a miss is free, and a hit spends the same single credit the name lookup would have.

Person Enrich needs a qualifier alongside a name (company, location, country), so a bare name cannot be enriched directly. When Enrich misses, con falls back to Person Search with an exact-name query, capped by [pdl] search_candidates (default 5, hard maximum 10). That cap is a spending limit: a five-result picker costs up to five Search credits. Search records are complete, so the profile you pick needs no follow-up Enrich call.

Naming your qualifier is cheaper and more accurate than falling back to Search:

con -l --at meta "alexandr wang"     # 1 Enrich credit, no Search fallback needed

With -g -l, the GitHub profile's company and location are used as qualifiers automatically. Names from the Microsoft directory arrive as "Last, First" and are normalized to given-name-first before being sent to PDL.

con only qualifies a PDL lookup with a company that some evidence supports: an explicit --at, a hit in the corporate directory, or the GitHub profile. Roughly half of all lookups are not coworkers, so a directory miss is treated as evidence the person works elsewhere — the configured employer is not silently used as the qualifier. In that case Enrich is skipped (it requires a qualifier) and the name goes straight to Search, unnarrowed. The directory and PDL are independent: neither has to find the person for the other to answer.

Match confidence

A Person Search result matched on name alone is only a guess. When the chosen record has no tie to a qualifying company — or when there was no qualifier to begin with — output is labeled Low confidence (and match_confidence: "low" in --json), because same-name strangers are common. Use --at to resolve those. The caution never names a company that was not actually being tested.

GitHub

Optional token in config, or CON_GITHUB_TOKEN / GITHUB_TOKEN, or gh auth token.

Tests

python3 -m pip install -e ".[dev]"
pytest

Limitations

  • PDL is not live LinkedIn; data can lag.
  • Graph People search ranks by relevance to you.
  • GitHub org list is public memberships only.
  • Do not use unofficial LinkedIn scrapers or broken “LinkedIn MCP” apps that call gated partner APIs.

About

Look up people in Microsoft Graph, enrich career history via People Data Labs, and resolve GitHub identities.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages