Agent skill

Refactor Legacy

by cartography-cncf in cartography-cncf/cartography

Convert a legacy handwritten-Cypher Cartography sync (load / cleanup JSON jobs) into the modern declarative data model (load(), GraphJob.fromnodeschema()).

Apache-2.0Auto-check passedDevelopment

Install Refactor Legacy

skills CLI
$ npx skills add cartography-cncf/cartography --skill refactor-legacy -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install cartography-cncf/cartography refactor-legacy --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/cartography-cncf/cartography.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/refactor-legacy .claude/skills/refactor-legacy && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
refactor-legacy
GitHub stars
4.1k
Token cost
~2.5k tokens
SKILL.md length
701 words
Files
1
Skills in repo
11
Repo updated
First seen
Licence
Apache-2.0

At a glance

Convert a legacy handwritten-Cypher Cartography sync (load / cleanup JSON jobs) into the modern declarative data model (load(), GraphJob.fromnodeschema()).

  • Works in 3 steps: Prevent regressions (CRITICAL) → Convert to the data model → Cleanup legacy artefacts
  • The user asks to refactor
  • SKILL.md covers Critical rules, Instructions, Common refactoring patterns and Things you may encounter, plus 5 more sections
  • Calls git

What it does

Refactor Legacy is an agent skill from cartography-cncf/cartography. Convert a legacy handwritten-Cypher Cartography sync (load / cleanup JSON jobs) into the modern declarative data model (load(), GraphJob.fromnodeschema()). Use when the user asks to refactor, modernise, migrate, or "clean up" a legacy intel module, or to remove a cleanup/.json job tied to an old MERGE query.

Its SKILL.md is about 2.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Refactoring. The repository describes itself as: Cartography is a Python tool that pulls infrastructure assets and their relationships into a Neo4j graph database. The licence is Apache-2.0.

When your agent uses it

  • The user asks to refactor
  • Clean up a legacy intel module
  • Remove a cleanup/.json job tied to an old MERGE query

Example prompts

  • “clean up”
  • “/refactor-legacy”

Requirements

  • Python 3

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. Prevent regressions (CRITICAL)
  2. Convert to the data model
  3. Cleanup legacy artefacts

What it can do on your machine

Read from SKILL.md and the folder at commit e345364. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • git

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Refactor Legacy loads about 2.5k tokens when it runs. Until then it costs about 86 tokens; SKILL.md has 701 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~86
When it runs · the whole SKILL.md, loaded when a task matches
~2.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from cartography-cncf/cartography at commit e345364, republished under its Apache-2.0 licence (© cartography-cncf). 701 words, ~2,471 tokens.

Download SKILL.mdSave it as .claude/skills/refactor-legacy/SKILL.md (or your agent's skills folder).
name
refactor-legacy
description
Convert a legacy handwritten-Cypher Cartography sync (`load_*` / `cleanup_*` JSON jobs) into the modern declarative data model (`load()`, `GraphJob.from_node_schema()`). Use when the user asks to refactor, modernise, migrate, or "clean up" a legacy intel module, or to remove a `cleanup/*.json` job tied to an old `MERGE` query.

refactor-legacy

A critical task for AI agents: refactor legacy Cartography modules from handwritten Cypher to the declarative data model. The modern approach generates optimised queries automatically, improves maintainability, and removes manual index / cleanup boilerplate.

Critical rules

  1. Test coverage first. Do not touch production code until an integration test exists and passes against the legacy code. If no test exists, write one and confirm it passes before refactoring.
  2. Convert MERGE/CREATE write queries to load() with CartographyNodeSchema. Convert handwritten cleanup to GraphJob.from_node_schema().
  3. If a hand-written write must remain temporarily, switch it to run_write_query() (managed transaction + retries). Never keep raw neo4j_session.run(...) writes during refactors.
  4. Only delete legacy artefacts for the nodes you actually converted — leave indexes and cleanup JSON for unconverted nodes alone.
  5. Re-run the integration test after every chunk of conversion. If it fails, debug before continuing — do not pile on more changes.
  6. Stop and ask the user when business logic in legacy Cypher is unclear, when relationships don't map cleanly, when tests fail repeatedly, or when modules look interdependent.

Instructions

Step 1 — Prevent regressions (CRITICAL)
1a. Identify the sync function

Locate the main sync_*() for the module — usually sync_ec2_instances(), sync_users(), etc.

Example: cartography.intel.aws.ec2.instances.sync().

1b. Ensure an integration test exists

Look in tests/integration/cartography/intel/[module]/. The test must call the sync function directly. If none exists, create one before any refactoring:

python
# tests/integration/cartography/intel/aws/ec2/test_instances.py
from unittest.mock import patch

import cartography.intel.aws.ec2.instances
from tests.data.aws.ec2.instances import MOCK_INSTANCES_DATA
from tests.integration.util import check_nodes, check_rels


TEST_UPDATE_TAG = 123456789
TEST_AWS_ACCOUNT_ID = "123456789012"


@patch.object(cartography.intel.aws.ec2.instances, "get", return_value=MOCK_INSTANCES_DATA)
def test_sync_ec2_instances(mock_get, neo4j_session):
    cartography.intel.aws.ec2.instances.sync(
        neo4j_session,
        boto3_session=None,  # mocked
        regions=["us-east-1"],
        current_aws_account_id=TEST_AWS_ACCOUNT_ID,
        update_tag=TEST_UPDATE_TAG,
        common_job_parameters={
            "UPDATE_TAG": TEST_UPDATE_TAG,
            "AWS_ID": TEST_AWS_ACCOUNT_ID,
        },
    )

    expected_nodes = {
        ("i-1234567890abcdef0", "running"),
        ("i-0987654321fedcba0", "stopped"),
    }
    assert check_nodes(neo4j_session, "AWSEC2Instance", ["id", "state"]) == expected_nodes

Run the test against the legacy code and ensure it passes. If it does not exist or does not pass, fix that first — no exceptions.

Step 2 — Convert to the data model
2a. Create schemas in cartography/models/[module]/
python
# cartography/models/aws/ec2/instances.py
from dataclasses import dataclass

from cartography.models.core.common import PropertyRef
from cartography.models.core.nodes import CartographyNodeProperties, CartographyNodeSchema
from cartography.models.core.relationships import CartographyRelSchema, LinkDirection, make_target_node_matcher


@dataclass(frozen=True)
class EC2InstanceNodeProperties(CartographyNodeProperties):
    id: PropertyRef = PropertyRef("id")
    lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
    instanceid: PropertyRef = PropertyRef("InstanceId")
    state: PropertyRef = PropertyRef("State")
    # ... other properties


@dataclass(frozen=True)
class EC2InstanceToAWSAccountRel(CartographyRelSchema):
    target_node_label: str = "AWSAccount"
    target_node_matcher: TargetNodeMatcher = make_target_node_matcher({
        "id": PropertyRef("AWS_ID", set_in_kwargs=True),
    })
    direction: LinkDirection = LinkDirection.INWARD
    rel_label: str = "RESOURCE"
    properties: EC2InstanceToAWSAccountRelProperties = EC2InstanceToAWSAccountRelProperties()


@dataclass(frozen=True)
class EC2InstanceSchema(CartographyNodeSchema):
    label: str = "AWSEC2Instance"
    properties: EC2InstanceNodeProperties = EC2InstanceNodeProperties()
    sub_resource_relationship: EC2InstanceToAWSAccountRel = EC2InstanceToAWSAccountRel()

For node, relationship, and schema details, see the add-node-type and add-relationship skills.

2b. Replace load_* functions
python
# Before
def load_ec2_instances(neo4j_session, data, region, current_aws_account_id, update_tag):
    ingest_instances = """
    UNWIND $instances_list AS instance
    MERGE (i:AWSEC2Instance {id: instance.id})
    ON CREATE SET i.firstseen = timestamp()
    SET i.instanceid = instance.InstanceId,
        i.state = instance.State,
        i.lastupdated = $update_tag
    WITH i
    MATCH (owner:AWSAccount {id: $aws_account_id})
    MERGE (owner)-[r:RESOURCE]->(i)
    ON CREATE SET r.firstseen = timestamp()
    SET r.lastupdated = $update_tag
    """
    neo4j_session.run(ingest_instances, instances_list=data, aws_account_id=current_aws_account_id, update_tag=update_tag)


# After
def load_ec2_instances(neo4j_session, data, region, current_aws_account_id, update_tag):
    load(
        neo4j_session,
        EC2InstanceSchema(),
        data,
        lastupdated=update_tag,
        AWS_ID=current_aws_account_id,
    )

If you genuinely need a hand-written write query during the refactor, replace neo4j_session.run(...) with run_write_query() so the write benefits from Cartography's managed transaction + retry handling.

2c. Replace cleanup_* functions
python
# Before
def cleanup_ec2_instances(neo4j_session, common_job_parameters):
    run_cleanup_job("aws_import_ec2_instances_cleanup.json", neo4j_session, common_job_parameters)


# After
def cleanup_ec2_instances(neo4j_session, common_job_parameters):
    GraphJob.from_node_schema(EC2InstanceSchema(), common_job_parameters).run(neo4j_session)
2d. Test continuously

After each chunk, run the integration test. Tests may need minor tweaks for property names that the data model normalises, but they should keep passing.

Step 3 — Cleanup legacy artefacts

Once tests pass, remove the legacy bookkeeping for the nodes you converted.

3a. Remove manual index entries

In cartography/data/indexes.cypher:

cypher
# Remove entries like these — the data model creates indexes automatically
CREATE INDEX IF NOT EXISTS FOR (n:AWSEC2Instance) ON (n.id);
CREATE INDEX IF NOT EXISTS FOR (n:AWSEC2Instance) ON (n.lastupdated);

Only remove indexes for nodes you actually converted.

3b. Remove cleanup job JSONs
bash
rm cartography/data/jobs/cleanup/aws_import_ec2_instances_cleanup.json

Only remove cleanup files for fully-converted modules.

Common refactoring patterns

  • Simple node migration. Most legacy nodes map directly to a node schema.
  • Complex relationships. May need one-to-many (add-node-type skill) or composite-node patterns (add-relationship skill).
  • MatchLinks. Use sparingly — only for connecting two existing node types from separate data sources, or rich relationship metadata. See add-relationship skill.
Show full SKILL.md (276 more words)Show less

Things you may encounter

Multiple intel modules modifying the same nodes
  • Reference by ID only -> simple relationship pattern.
  • Different views of the same entity from different sources -> composite node pattern.

(See add-relationship skill, "Multi-module patterns".)

Legacy test adjustments
  • Update expected property names if the data model changes them.
  • Adjust relationship directions if needed.
  • Remove tests for manual cleanup jobs (data model handles cleanup).
Complex Cypher queries

Break them down: identify what nodes/relationships are being created, map to schemas, then use multiple load() calls if needed.

What NOT to test

Do not explicitly test cleanup unless you have a specific concern. The data model handles complex cleanup automatically and testing it adds boilerplate. Focus tests on data ingestion outcomes.

When to stop and ask

Refactors get hairy. Stop and ask the user when:

  • Legacy Cypher contains business logic that isn't obvious.
  • Relationships don't map cleanly to the data model.
  • Tests fail repeatedly and you cannot resolve them.
  • Multiple modules look interdependent.

Refactoring checklist

  • Integration test exists and passes against the legacy code
  • Data model schemas defined with proper relationships
  • Legacy load_* functions converted to load()
  • Legacy cleanup_* functions converted to GraphJob.from_node_schema()
  • Tests still pass after all changes
  • Manual index entries removed from indexes.cypher
  • Cleanup JSON files removed from cartography/data/jobs/cleanup/
  • No regressions in functionality
  • Commits signed (git commit -s)

Success criteria

A successful refactor:

  1. Preserves all functionality (tests pass).
  2. Uses the data model (no handwritten Cypher for CRUD).
  3. Cleans up legacy artefacts (indexes + cleanup JSONs removed).
  4. Maintains performance (no significant degradation).
  5. Follows the modern-module patterns consistently.

Common issues

See the troubleshooting skill for PropertyRef validation failed, missing relationships, cleanup misbehaviour, and related errors.

© cartography-cncf, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/refactor-legacy of cartography-cncf/cartography.

Open the folder on GitHubat commit e345364

Compare with similar skills

Refactor Legacy next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Refactor Legacy compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Refactor Legacy this skillcartography-cncf/cartography4.1k—~2.5kAutomated safety check: PassApache-2.0
Guidelinesakash-network/node1.1k20 repos~577Automated safety check: PassMIT
Component Refactoringlangflow-ai/langflow155k—~3.5kAutomated safety check: PassMIT
Migrate Core Code to Submodulestinyhumansai/openhuman42k—~2.6kAutomated safety check: PassGPL-3.0
ast-grep Structural Searchcode-yeongyu/oh-my-openagent70k—~3.3kAutomated safety check: PassMIT
Systematic Code Refactoringluongnv89/claude-howto42k—~3kAutomated safety check: PassMIT

Similar skills

  • Guidelines

    akash-network/node

    Behavioral guidelines to reduce common LLM coding mistakes. An agent skill from akash-network/node.

    1.1k GitHub starsUsed in 20 repos~577 tokens
    DevelopmentAuto-check passed
  • Component Refactoring

    langflow-ai/langflow

    Refactor high-complexity React components in Langflow frontend.

    155k GitHub stars~3.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Migrate Core Code to Submodules

    tinyhumansai/openhuman

    Plans and carries out moving non-host-specific code and its tests from the OpenHuman core into vendored tiny submodule libraries, then releases the submodule and re-pins the host.

    42k GitHub stars~2.6k tokensUpdated today
    DevelopmentAuto-check passed
  • ast-grep Structural Search

    code-yeongyu/oh-my-openagent

    Searches and rewrites code by syntax-tree shape across 25 languages with ast-grep, for codemods, structural queries and YAML lint rules, using a Python wrapper script.

    70k GitHub stars~3.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Systematic Code Refactoring

    luongnv89/claude-howto

    Guides refactoring in phases based on Martin Fowler's method: research, test coverage check, planning and small tested steps, with your approval at each phase.

    42k GitHub stars~3k tokensUpdated 9 days ago
    DevelopmentAuto-check passed
  • Codex

    skills-directory/skill-codex

    A skill your agent uses when the user asks to run Codex CLI (codex exec, codex resume) or references OpenAI Codex for code analysis, refactoring, or automated editing

    1.5k GitHub starsUsed in 3 repos~1.8k tokens
    DevelopmentAuto-check passed

More from cartography-cncf/cartography

All 11 skills in this repo
  • Add Node Type

    cartography-cncf/cartography

    Define a new node schema under cartography/models/MODULENAME/, including required properties, sub-resource relationships, extra labels, conditional labels, scoped cleanup, and one-to-many transforms.

    4.1k GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Add Relationship

    cartography-cncf/cartography

    Define a CartographyRelSchema (standard relationship), one-to-many edge, or MatchLink connecting existing nodes.

    4.1k GitHub stars~1.7k tokensUpdated today
    Auto-check passed
  • Analysis Jobs

    cartography-cncf/cartography

    Add a post-ingestion typed analysis job to a Cartography module to enrich the graph after sync.

    4.1k GitHub stars~2k tokensUpdated today
    Auto-check passed
  • Create Module

    cartography-cncf/cartography

    Author a new Cartography intel module end-to-end (entry point, sync GET/TRANSFORM/LOAD/CLEANUP, declarative data model, integration test, schema docs).

    4.1k GitHub stars~2.5k tokensUpdated today
    Auto-check passed
  • Create Rule

    cartography-cncf/cartography

    Author a Cartography security rule (one or more Cypher Facts plus a Pydantic Finding output model) under cartography/rules/data/rules/.

    4.1k GitHub stars~3k tokensUpdated today
    Auto-check passed
  • Enrich Ontology

    cartography-cncf/cartography

    Map a Cartography node into the Ontology system using semantic labels (UserAccount, DeviceInstance, Tenant, Database, ObjectStorage, FileStorage) or canonical nodes (User, Device).

    4.1k GitHub stars~2.4k tokensUpdated today
    Auto-check passed

Categories

Questions about Refactor Legacy

What does Refactor Legacy do?

Convert a legacy handwritten-Cypher Cartography sync (load / cleanup JSON jobs) into the modern declarative data model (load(), GraphJob.fromnodeschema()). Refactor Legacy is an agent skill from cartography-cncf/cartography.fromnodeschema()).

When should I use Refactor Legacy?

Refactor Legacy fits situations like: the user asks to refactor; clean up a legacy intel module; remove a cleanup/.json job tied to an old MERGE query.

How do I install Refactor Legacy in Claude Code?

Run `npx skills add cartography-cncf/cartography --skill refactor-legacy -a claude-code`. Or copy the skill folder (.agents/skills/refactor-legacy in cartography-cncf/cartography) into .claude/skills/refactor-legacy in your project. Claude Code loads it when a task matches its description.

How do I install Refactor Legacy in Codex?

Run `npx skills add cartography-cncf/cartography --skill refactor-legacy -a codex`. Or copy the skill folder (.agents/skills/refactor-legacy in cartography-cncf/cartography) into .agents/skills/refactor-legacy in your project. Codex loads it when a task matches its description.

Can I use Refactor Legacy in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add cartography-cncf/cartography --skill refactor-legacy -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/refactor-legacy, .gemini/skills/refactor-legacy, .github/skills/refactor-legacy and .opencode/skills/refactor-legacy in your project.

What does Refactor Legacy need to run?

Going by SKILL.md and its folder, Refactor Legacy needs the command-line tools its instructions call (git). Our summary lists: Python 3.

Does Refactor Legacy access the network?

SKILL.md contains no URLs. Its commands use git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Refactor Legacy safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Refactor Legacy use?

Refactor Legacy is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Refactor Legacy use?

About 2.5k tokens (SKILL.md is roughly 9.9k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Refactor Legacy?

Skills that share tags, products or a category with Refactor Legacy: Guidelines (akash-network/node, 1.1k stars), Component Refactoring (langflow-ai/langflow, 155k stars), Migrate Core Code to Submodules (tinyhumansai/openhuman, 42k stars) and ast-grep Structural Search (code-yeongyu/oh-my-openagent, 70k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Refactor Legacy?

cartography-cncf (a GitHub organization) maintains it in cartography-cncf/cartography, which has 4,128 GitHub stars. The repository holds 11 skills in this directory. The repository was last updated on October 9, 2026.

Source: cartography-cncf/cartography on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.