Relocation planner
Free, open-source Claude Code Agent Skills for personal finance — FIRE planning, rent-vs-buy, tax optimization & gain-harvesting, equity comp, retirement income (pensions/annuities, bond ladders), debt & student loans, relocation, and self-employed/business-owner planning. Powered by the public planfi MCP (no auth). Not financial advice.
npx -y skills add KameronKales/planfi-skills --skill relocation-plannerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Compare retirement relocation / state-tax arbitrage by orchestrating the public planfi MCP — how much a move (e.g. CA→TX/FL) saves in state income tax, property tax, estate tax, and cost of living — plus model the messy transition year you actually move in (part-year-resident apportionment, source-based wage/equity sourcing, the resident-state credit for taxes paid to the other state, reciprocity, and the 183-day residency test).
SKILL.md
12.8 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
relocation-planner
A thin orchestration layer over the planfi MCP (https://ai.planfi.app/mcp/free). All math + financial logic live server-side. This skill only gathers inputs and calls the tools — it does not compute anything locally, carries no business logic, math, or defaults, and is read-only (it never changes the user's data). The server is the source of truth.
Step 0 — Make sure the planfi tools are connected
This skill uses these tools (may be namespaced, e.g. mcp__planfi__generate_financial_plan):
analyze_relocation, analyze_multi_state_part_year_tax (the transition-year / part-year split), plus optional generate_financial_plan (to mint a plan_id for chaining + a share_url).
Use whichever name your environment exposes (bare or mcp__planfi__-prefixed); below they are written bare.
If they're NOT available, tell the user to connect the MCP, then continue:
claude mcp add --transport http planfi https://ai.planfi.app/mcp/free
Try free, then add your key. The command above adds the free connector —
https://ai.planfi.app/mcp/free(no key needed). Once you create an API key, add a new connector with the MCP url —https://ai.planfi.app/mcp— and authorize it with your key.
(On claude.ai: add a custom connector pointing at https://ai.planfi.app/mcp/free.)
Access — free for personal use. The planfi MCP is free to try (a small monthly allowance, no key needed). Heavy automated abuse forced us to add limits — but it stays free for personal use: email [email protected] and we'll send you a free API key, no charge. (Companies and commercial use have paid plans.) To use a key, pass it as an
Authorization: Bearer pft_…header in your MCP client config.
Step 1 — Gather inputs (prefer a plan_id)
Ask only for what the user's question needs. Every input has a sensible server default, so the
tools run cold — but the cleanest path is to mint a plan_id first and chain off it:
- Optional but recommended: call
generate_financial_planwith whatever household model you have (earners' age + salary, stockscurrent_value+monthly_contribution, plus any account balances / spend the user volunteered). CAPTURE the returnedplan_idand theshare_url. Pass{ plan_id }toanalyze_relocation(which takes aplan_idplus inlineoverrides) to derive figures from the saved plan. - Or run cold: pass
analyze_relocationits raw inputs directly. Onlyfrom_stateandto_stateare required; everything else is defaulted server-side.
Engine facts to bake in: all dollars are today's (real) dollars; all decimals are fractions (24% →
0.24, 5% →0.05); tax brackets/limits are approximate ~2026 values (noted in each tool'sdisclosures).
Step 2 — Route by intent
- "Should I move from <state A> to <state B> in retirement?" / "How much would relocating to TX/FL/NV save me?" / "Is leaving California worth it?" →
analyze_relocation- REQUIRED:
from_state,to_state(2-letter codes). - Recommended (each defaults server-side if omitted, reported in
assumed_defaults[]):annual_retirement_income(pension / IRA / 401k withdrawals / RMD / interest — the state-taxable ordinary income; default 0),social_security_income(default 0),annual_capital_gains(annual realized long-term gains; default 0),annual_spend(living spend at cost-of-living index 100 — drives the COL delta; default 0),real_estate_value(home value for property-tax comparison; default 0),current_age(default 50),life_expectancy(default 90 — current_age→life_expectancy sets years in retirement),filing_status(single|married_joint, defaultsingle). - Other optional fields:
liquid_assets,mortgage_principal(informational; default 0),estimated_growth_rate(real rate, default 0.05),tax_year(default 2026),plan_id(+ inlineoverrides) to derive figures from a saved plan. - Returns:
annual_after_tax_deltaandlifetime_after_tax_delta(positive = the move saves),estate_tax_delta,total_lifetime_advantage, aheadline_recommendation+recommendation_reason, andfrom_breakdown/to_breakdownline items (state income tax, property tax, COL). - State income tax is computed by the shared engine (
state-tax.ts): progressive bracket tables for all 50 states + DC, with first-class single and married-filing-jointly (MFJ) brackets — sofiling_statusbranches every state (no-income-tax states report $0). Brackets are server-side; there is no user-supplied flat-rate field.
- REQUIRED:
Shared bracket engine —
n/a (shared engine: state-tax.ts). The full 50-state + DC single/MFJ progressive bracket tables (with per-state surtaxes) live in one shared engine module (state-tax.ts), the same one the broadertax-optimizerskill uses — no CA/NY/MA-only special-casing, no per-tool flat-rate fallback. For Roth-conversion rooms, gain-harvesting headroom, or multi-year tax timing alongside the move, use thetax-optimizerskill (it wraps the sameanalyze_relocationtool plus the full tax toolset).
Feed it into the forecast (not just a comparison):
generate_financial_plannow accepts arelocationobject directly as a plan input — modeled as retire-and-relocate, the annual state-tax + cost-of-living savings reduce the portfolio-funded spend from the move age, so the move shows up in net worth, FIRE %, and Monte-Carlo backtesting. Useanalyze_relocationfor the headline from→to delta; passrelocationinto the plan to see its effect on the whole household forecast.
intent → analyze_multi_state_part_year_tax
"I moved from CA to TX mid-year, how do I file two state returns?" / "part-year resident tax" / "how do I split my income between two states the year I moved?" / "my RSUs vested after I moved states — which state taxes them?" / "do I get credit for taxes paid to my old state?" / "183-day residency test" / "am I a statutory resident?" / "reciprocity between PA and NJ" / "I'm a remote worker taxed in two states this year"
Always CALL
analyze_multi_state_part_year_taxfor these — do not answer from general knowledge / quote rules of thumb from memory. When the user gives the move date and income, run it and lead with its real output.analyze_relocationdeliberately models a full year in each state and excludes the messy transition year; this tool IS that transition year — day-count apportionment, source-based sourcing of wages/equity/gains, the resident-state credit for taxes paid to the other state, reciprocity, and the 183-day/domicile statutory-residency test. Whenever the user is describing the year of the move itself (two part-year returns, income straddling the line, equity vesting across the move, claiming the other-state credit), this is the tool — never hand-compute the apportionment or the credit.
- REQUIRED:
old_state,new_state(2-letter codes),days_in_old_state,days_in_new_state(residency days — these split the year and have no server default; the tool needs the move date). - Server-defaulted and reported in
assumed_defaults[]if omitted:filing_status(single|married_joint, defaultsingle),wages(default 0),total_workdays(default 260),equity_vest_value/capital_gains/deferred_comp/other_ordinary_income(default 0),capital_gains_realized_while_old_resident(default false → new-resident sourcing),deferred_comp_source_state(old|new, defaultold),reciprocity(default false),domicile_in_old_state(default false),tax_year(default 2026). - Source-based sourcing inputs (optional; fall back to a residency-day split when omitted):
wages_workdays_in_old_state(workdays in the old state — sources wages to where work was performed),equity_workdays_old_state_grant_to_vest+equity_total_workdays_grant_to_vest(allocate an RSU grant→vest window straddling the move),old_state_flat_rate/new_state_flat_rate(flat-rate fallback for a tableless state). - Returns: per-state
residencyStatus(part-year-resident | nonresident | statutory-resident) withresidencyDeterminations[](basis:183-day|domicile|reciprocity|part-year), income apportioned to each state,oldStateTax/newStateTax,doublyTaxedIncome,residentStateCredit(the credit for taxes paid to the other state, limited to the resident-state tax on the doubly-taxed income),combinedStateTax,naiveFullYearSingleStateTax, andnetVsNaive(positive ⇒ the part-year split beats a naive single-state assumption). - Shared engine —
n/a (shared engine: state-tax.ts). Every per-state full-year bracket computation reuses the same 50-state + DC single/MFJ progressivestate-tax.tsengine thatanalyze_relocationand thetax-optimizerskill use — no per-tool flat-rate special-casing, no re-declared brackets. For the underlying equity-vest sourcing mechanics (grant→vest workday allocation, ISO/RSU treatment) cross-reference theequity-comp-plannerskill; for Roth-conversion rooms or multi-year tax timing around the move, thetax-optimizerskill.
Example (FICTIONAL — illustrate the call shape):
analyze_multi_state_part_year_tax({
old_state: "NY", new_state: "CA",
days_in_old_state: 120, days_in_new_state: 245,
wages: 160000, wages_workdays_in_old_state: 120, total_workdays: 240,
equity_vest_value: 100000, equity_workdays_old_state_grant_to_vest: 300,
equity_total_workdays_grant_to_vest: 600, filing_status: "single"
})
// → NY part-year-resident + CA year-end resident; ~80k wages NY-sourced;
// residentStateCredit = min(NY tax on the doubly-taxed slice, CA marginal on it);
// combinedStateTax + netVsNaive vs assuming a full year all in CA
Example (FICTIONAL — illustrate the call shape):
analyze_relocation({
from_state: "CA", to_state: "TX",
annual_retirement_income: 90000, social_security_income: 40000,
annual_capital_gains: 0, annual_spend: 70000, real_estate_value: 600000,
current_age: 60, life_expectancy: 90, filing_status: "married_joint"
})
// → annual_after_tax_delta ≈ +$18,000/yr (move saves), lifetime ≈ +$540k, + estate-tax delta
Step 3 — Surface the result
- Lead with the headline dollar figure / decision the tool returns.
- Read back
assumed_defaults[]—analyze_relocationreturns a structuredassumed_defaults[]array of{ field, assumed_value, note }for every input you omitted (e.g.annual_retirement_income,social_security_income,current_age,filing_status). Surface these so the user can correct any silent default, then re-call with the corrected values. disclosures.key_assumptions— a SEPARATE array of static prose strings (engine conventions, e.g. which states use bracket tables). Optional context; the per-call assumptions live inassumed_defaults[]above.disclosures.not_advice— a boolean (alwaystrue); relay that this is a planning estimate, not financial advice.next_actions[]— each{ tool, why, prefilled_args }. Foranalyze_relocationthese point toanalyze_advanced_taxesandanalyze_estate_exposure(and only when aplan_idwas passed are the args prefilled with it). Follow these server-suggested chains rather than guessing the next call.share_url—analyze_relocationemits ashare_urlwhen you pass aplan_id(and the plan resolves with the household).generate_financial_planalways returns one. Offer it so the user can open the full interactive plan on planfi.app.
Recommended call sequence (typical session)
- (optional)
generate_financial_plan→ captureplan_id+share_url. - Route by intent to the relevant specialist tool(s) above, passing
{ plan_id }. - Surface headline +
assumed_defaults[]+next_actions+share_url. - Follow
next_actions[]chains on demand.
Notes
- All decimals are fractions; all dollars are today's (real) dollars.
- Reuse the
plan_idacross the session — don't re-send the full model each call. analyze_relocationemits a structuredassumed_defaults[](read these back to the user) and ashare_urlwhen called with aplan_id. Run it cold (justfrom_state+to_state) and it still returnsassumed_defaults[]for everything it defaulted.- Not financial advice. Planning estimates only (approximate ~2026 brackets/limits where tax applies).