Skip to content
Back to skills

Ops Linkedin

ASecurity

Prepare evidence-bounded LinkedIn profile updates, posts, image-post captions, comments, connection notes, messages, manual search plans, lead-research plans, and content reviews as local drafts with typed human-execution handoff packets; export editable JSON for Graham's own LinkedIn profile; prepare bounded Surf own-profile sync plans after explicit account-risk acknowledgement; and prepare bounded read-only contact graph capture plans for named opportunity contacts after explicit account-r...

  • 6 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
businesspythongobashreactapidatabasesecurityperformance

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 20 files and shows the line behind each finding

Scanned September 23, 2026

npx -y skills add grahama1970/agent-skills --skill ops-linkedin --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ops Linkedin?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ops Linkedin
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/grahama1970-ops-linkedin/badge)](https://www.skillsdirectory.com/skills/grahama1970-ops-linkedin)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ops-linkedin
description: >
  Prepare evidence-bounded LinkedIn profile updates, posts, image-post captions,
  comments, connection notes, messages, manual search plans, lead-research plans,
  and content reviews as local drafts with typed human-execution handoff packets;
  export editable JSON for Graham's own LinkedIn profile; prepare bounded
  Surf own-profile sync plans after explicit account-risk acknowledgement; and
  prepare bounded read-only contact graph capture plans for named opportunity
  contacts after explicit account-risk acknowledgement.
  Use when a user says "update my LinkedIn", "draft a LinkedIn post", "write a
  connection note", "plan LinkedIn outreach", "review my LinkedIn content",
  "find mutual LinkedIn contacts", or otherwise asks for LinkedIn operations.
  This skill does not automate outreach, bulk scraping, messages, posts,
  comments, or applications.
triggers:
  - linkedin
  - update my linkedin
  - linkedin profile
  - draft a linkedin post
  - linkedin content
  - linkedin comment
  - linkedin connection note
  - linkedin message
  - linkedin search plan
  - linkedin lead generation
  - linkedin outreach plan
  - review linkedin content
license: MIT
runtime_self_improvement: none
metadata:
  short-description: LinkedIn drafts plus editable own-profile sync plans
  version: "0.1.0"
  policy-snapshot: "2026-08-02"
  outbound-gate: "roundtable-required-2026-08-02"
provides:
  - linkedin-content-drafting
  - linkedin-manual-handoff
  - linkedin-profile-governance
  - linkedin-profile-entry-json
  - linkedin-own-profile-sync-plan
composes:
  - memory
  - brave-search
  - dogpile
  - task-monitor
complies:
  - best-practices-skills
  - best-practices-python
  - best-practices-security
  - best-practices-roundtable
taxonomy:
  - compliance
  - privacy
  - validation
  - human-in-the-loop
  - professional-networking
---

# LinkedIn Operations

Prepare LinkedIn work locally, validate factual claims, and hand final outbound actions
to a human. For Graham's own profile, the skill can export an editable
`ops-linkedin.profile_entry.v1` JSON file from `RESUME.md` and prepare a bounded Surf
sync plan. For named opportunity contacts, after explicit user authorization and account
risk acknowledgement, it can prepare a bounded read-only contact-graph capture plan for
relationship degree and visible mutual-contact evidence. The normal content/outreach
lanes still stop before LinkedIn access.

## Immutable boundary

The skill MUST NOT:

- open, drive, inspect, or modify LinkedIn through a browser, extension, DOM bridge,
  WebSocket bridge, browser-control skill, or headless browser, except for an explicit
  own-profile sync plan generated by `profile-sync-plan` or a bounded read-only
  opportunity contact graph plan generated by `contact-graph-capture-plan`;
- inspect cookies, passwords, session tokens, local storage, or login state;
- scrape profiles, posts, contacts, search results, comments, or company pages in bulk;
- collect anything outside the named `contact-graph-capture-plan` targets;
- automatically post, like, comment, connect, follow, message, apply, or upload;
- perform bulk engagement, outreach sequences, rate-limit evasion, or anti-bot evasion;
- report `PREPARED` work as executed, delivered, published, or platform-verified.

An official LinkedIn API adapter is outside this MVP. Add one only after documented
LinkedIn authorization, a separate security/policy review, and new live receipts.

Read `references/linkedin-policy.md` before proposing any expansion of this boundary.

## Capability lanes

| Lane | Supported preparation | Human-only finish |
|---|---|---|
| `profile` | Evidence-bounded headline, About, Experience, Skills, Featured, profile-field draft, editable own-profile JSON, or Surf sync plan | Review JSON, optionally run bounded own-profile sync, review visibility |
| `explore` | Manual search query and review plan | Run the search and inspect results |
| `publish` | Text post or image-post caption and attachment checklist | Create, preview, and publish the post |
| `interact` | Comment, connection note, or one-to-one message draft | Confirm context and submit one action |
| `lead-gen` | Public-web research plan, individually reviewed prospect criteria, authorized read-only contact graph capture plan, and authorized read-only recruiter/company-page research (a `$surf` headed tab in the user's own session reading one recruiter profile + their company page for `$ops-recruiter` threads) | Inspect selected profiles and decide on outreach |
| `content-ops` | Analysis of user-provided/exported posts and metrics | Make any edits or follow-up actions |

The upstream `linkedin-skills` project inspired these lanes, but its browser bridge and
social-action automation are intentionally not copied. See `references/linkedin-policy.md`.

## Mandatory workflow

1. **Classify the lane and action.** Use only the action vocabulary in
   `references/contracts.md`.
2. **Gather evidence outside LinkedIn.**
   - Use `/memory` for the user's canonical resume, profile state, prior approved copy,
     and earlier handoff receipts.
   - Use `/brave-search` or `/dogpile` for current public facts. Do not ask those skills
     to scrape LinkedIn or bypass access controls.
   - Treat user-provided LinkedIn exports, pasted text, screenshots, and metrics as input
     artifacts; label their capture date.
3. **Build a request manifest.** Every factual claim that is labeled `verified` needs at
   least one source reference. Use `assets/examples/` as shape examples.
4. **Prepare the packet.**

   ```bash
   bash ./skills/ops-linkedin/run.sh prepare request.json --output handoff.json
   ```

5. **Inspect readiness.**
   - `READY_FOR_HUMAN_REVIEW` means the packet may be reviewed and manually executed.
   - `BLOCKED_UNVERIFIED_CLAIMS` means stop. Add evidence, soften the copy, or mark the
     unsupported claim `excluded`; do not bypass the gate.
6. **Give the human the draft and manual steps.** Do not call `/surf`, browser control,
   or any hidden LinkedIn transport for outbound, third-party, search, feed, message, or
   application work.
   - Exception: for Graham's own profile alignment, first export the editable JSON:

     ```bash
     bash ./skills/ops-linkedin/run.sh profile-entry-export \
       --resume-source RESUME.md \
       --profile-url "https://www.linkedin.com/in/grahamanderson/" \
       --output local/linkedin-profile-entry.json
     ```

     A project agent may edit this JSON. Then generate a bounded Surf plan:

     ```bash
     bash ./skills/ops-linkedin/run.sh profile-sync-plan \
       --entry-json local/linkedin-profile-entry.json \
       --accept-account-risk \
       --own-profile-only \
       --output local/linkedin-profile-sync.json
     ```

     The plan remains `execution_claim: NOT_EXECUTED` until a separate Surf execution
     receipt exists.

   - Exception: for a named opportunity contact graph, first prepare a bounded plan:

     ```bash
     bash ./skills/ops-linkedin/run.sh contact-graph-capture-plan \
       --opportunity "Moog Senior AI Engineer" \
       --target "George Small|Moog|https://www.linkedin.com/in/george-small-moog/" \
       --user-authorized-read-only \
       --accept-account-risk \
       --tab-id "<surf-tab-id>" \
       --output local/moog-contact-graph-plan.json
     ```

     The plan remains `execution_claim: NOT_EXECUTED`. A project agent may then perform
     the bounded read-only capture through the project-approved browser tool, recording
     only `monitor_opportunities.linkedin_contact_graph_evidence.v1`: target name, target
     URL, visible relationship degree, visible mutual names if LinkedIn shows them,
     disambiguating title/company/location, screenshot/artifact refs, and limitations.
     It must not connect, follow, react, search broadly, enumerate contacts, send, or
     inspect hidden browser state. It may prepare a relevant InMail/message draft as a
     local handoff packet after the target evidence is captured; sending remains a
     separate human action governed by the outbound roundtable gate.
7. **Record completion only after an explicit user statement.** When the user says they
   personally completed the action, the agent may run:

   ```bash
   bash ./skills/ops-linkedin/run.sh attest handoff.json \
     --actor "<human name>" \
     --confirm-human-completed \
     --output completion.json
   ```

   The resulting proof is `USER_ATTESTED_MANUAL_ACTION` and remains
   `platform_verified: false`.

For multi-item work, use `/task-monitor` to track each packet separately. Never collapse
several recipients or posts into one ambiguous receipt.

## CLI

```bash
# Dated policy snapshot and current implementation state
bash ./skills/ops-linkedin/run.sh policy
bash ./skills/ops-linkedin/run.sh status

# Prepare and validate a local packet
bash ./skills/ops-linkedin/run.sh prepare request.json -o handoff.json
bash ./skills/ops-linkedin/run.sh validate handoff.json

# Export editable profile JSON and prepare a bounded own-profile Surf plan
bash ./skills/ops-linkedin/run.sh profile-entry-export \
  --resume-source RESUME.md \
  --profile-url "https://www.linkedin.com/in/grahamanderson/" \
  -o local/linkedin-profile-entry.json
bash ./skills/ops-linkedin/run.sh profile-sync-plan \
  --entry-json local/linkedin-profile-entry.json \
  --accept-account-risk \
  --own-profile-only \
  -o local/linkedin-profile-sync.json

bash ./skills/ops-linkedin/run.sh contact-graph-capture-plan \
  --opportunity "Moog Senior AI Engineer" \
  --target "George Small|Moog|https://www.linkedin.com/in/george-small-moog/" \
  --user-authorized-read-only \
  --accept-account-risk \
  -o local/linkedin-contact-graph-plan.json

# Record explicit human completion; this is not platform verification
bash ./skills/ops-linkedin/run.sh attest handoff.json \
  --actor "Graham" \
  --confirm-human-completed \
  -o completion.json

# Deterministic local checks
bash ./skills/ops-linkedin/sanity.sh
```

`prepare` exits `3` when it writes a blocked packet. `--allow-blocked` may be used only by
a review pipeline that needs the blocked artifact; it does not make the packet executable.

## Outbound actions require an /ask roundtable

Operator decision 2026-08-02. `post`, `image-post`, `comment`, `connection-note`, and
`message` place content in front of another person or an audience, so each request must
carry a `roundtable_review` whose verdict permits execution. Without one the packet is
`BLOCKED_MISSING_ROUNDTABLE`.

`profile-update` is deliberately **excluded**: it edits the user's own surface rather than
contacting anyone, and it is revised often.

Required in `roundtable_review`: `ran: true`, `topology: concurrent` (a sequential chain
is a pipeline, not a roundtable), an `immutable_goal`, `run_dir` so receipts can be
inspected, **at least two `PASS` seats** (one voice is not a panel), an attributed
`synthesis`, `rounds_run` within the 3-round cap, and
`follows_best_practices_roundtable: true`. Verdicts `DO_NOT_SEND` and
`NEEDS_HUMAN_DECISION` block the packet.

Why the expensive review is the cheap option: outbound volume is deliberately low and
each message is dossier-backed and aimed at a named person, so response likelihood is
high. One badly-worded message costs a contact and their organization permanently. Low
volume plus high hit-rate inverts the usual QA calculus.

`assets/examples/roundtable-review.json` is a reusable receipt shape.

## Claim discipline

- Do not infer evidence from confident wording.
- Do not label a claim `verified` without a source reference.
- A `verified` claim MUST carry `claim_key`, the key of the approved claim in the
  canonical `career_profile` ledger in `/memory`. This is the same vocabulary as
  `grahamaco.inmail_draft.v1` `claims_referenced[].claim_key`, so LinkedIn copy and
  outreach copy cannot drift into two independent claim sets. An unbound verified claim
  is a second source of truth and is rejected.
- `profile-update` and `lead-research-plan` require at least one verified claim.
- Any `needs-source` claim blocks the packet.
- Quantitative, credential, employer, clearance, customer, funding, scale, performance,
  and deployment claims should point to concrete local or public evidence.
- If evidence is unavailable, soften or remove the claim rather than inventing support.

The CLI intentionally does not extract claims from free-form text. The agent or human must
supply the explicit claim ledger so the review boundary remains inspectable.

## Receipt semantics

| Field | Meaning |
|---|---|
| `status: PREPARED` | Local draft and manual steps exist; nothing was done on LinkedIn |
| `readiness: READY_FOR_HUMAN_REVIEW` | Evidence gate passed for human review |
| `readiness: BLOCKED_UNVERIFIED_CLAIMS` | Do not execute the draft |
| `readiness: BLOCKED_MISSING_ROUNDTABLE` | Outbound action with no permitting panel verdict |
| `execution_claim: NOT_EXECUTED` | No action was claimed |
| `execution_claim: USER_ATTESTED_MANUAL_ACTION` | A named human said they performed it |
| `platform_verified: false` | The skill has no independent LinkedIn proof |

Never rewrite these semantics in prose as stronger proof.

For `ops-linkedin.contact_graph_capture_plan.v1`, `execution_claim: NOT_EXECUTED` means
the plan was prepared only. A later browser receipt must carry the actual read-only
capture evidence; the plan is not proof that any mutual contact exists.

## Data handling

- Keep request and handoff JSON at a caller-selected local path.
- Do not store passwords, cookies, session artifacts, or copied contact databases.
- Do not commit real private messages, recipient lists, or private exports.
- Use `/memory` only when the user requests durable recall and apply the appropriate
  purpose/sensitivity scope.
- For public prospect research, store source URLs and capture dates; avoid sensitive
  personal data that is not necessary for the stated purpose.

## Progressive disclosure

Read only what the task needs:

- `references/contracts.md` — request, packet, status, and failure contracts.
- `references/linkedin-policy.md` — policy rationale, official sources, and upstream
  adaptation notes.
- `PROJECT_KNOWLEDGE.md` — implemented, excluded, aspirational, and verification state.
- `README.md` — human-oriented setup and examples.

## Evaluation posture

`fixtures/agentic_eval.json` exercises the real local CLI for positive, negative, and
adversarial cases. It proves request validation, fail-closed evidence gating, and bounded
attestation. It does not prove any live LinkedIn action.

## References (retrieve on demand — do not vendor)

External docs drift; cite the canonical URLs and fetch them when needed
with `/context7` (library docs) or `/fetcher` (any URL/PDF) rather than
caching stale copies. Verified reachable (HTTP 200) 2026-08-24.

- LinkedIn developer docs (Microsoft Learn): <https://learn.microsoft.com/en-us/linkedin/>

```bash
skills/context7/run.sh "linkedin api marketing developer"
skills/fetcher/run.sh "https://learn.microsoft.com/en-us/linkedin/"
```

Files in this skill

  • .ask/browser-oracles.yaml43 B
  • .gitignore76 B
  • PROJECT_KNOWLEDGE.md6.7 KB
  • README.md4.7 KB
  • SKILL.md14.6 KB
  • assets/examples/connection-note.json2 KB
  • assets/examples/profile-update-blocked.json428 B
  • assets/examples/publish-post.json2 KB
  • assets/examples/roundtable-review.json1.2 KB
  • fixtures/agentic_eval.json7.5 KB
  • pyproject.toml745 B
  • references/contracts.md7.6 KB
  • references/linkedin-policy.md3.8 KB
  • run.sh643 B
  • sanity.sh7.1 KB
  • src/ops_linkedin/__init__.py96 B
  • src/ops_linkedin/cli.py12.4 KB
  • src/ops_linkedin/lead_resolver.py6.6 KB
  • src/ops_linkedin/models.py18.8 KB
  • src/ops_linkedin/profile_sync.py15.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.