Cartaの過去年度実績データから、ファンド/マネジメント会社(資金運用を行う企業)の予算ワークブックをExcelで新規作成または再構成します。 **使用する場面:** - 将来年度の予算を新規作成・策定・下書きする場合 - 予算の各項目をセクション(区間)ごとにグループ分けし、小計を付ける場合 - 予算の支出にインフレーション調整や緊急予備費(想定外の出費に備える余裕費)を適用する場合 **対象外の機能:** 損益計算書やバランスシートの統合、既存予算の取得、実績データの更新、進捗状況の分析(carta-budget-analysis)、シナリオ比較(carta-budget-scenarios)
Build or restructure a fund/ManCo budget workbook in Excel from Carta prior-year actuals. TRIGGER: build/create/draft a budget for a future year; group/categorize budget line items into sections with subtotals; apply an inflation/contingency buffer to budget expenses. NOT: consolidating P&L / balance sheet, fetch-budget, actuals refresh, pacing (carta-budget-analysis), what-if scenarios (carta-budget-scenarios).
<!-- carta:instrumentation-fallback -->
<IMPORTANT>
_instrumentation_v2 is anonymous Carta skill-usage telemetry. ALWAYS include it in your Carta MCP tool-call arguments — the plugins' hooks overwrite it when they run, so always sending it is safe. Shape:
_instrumentation_v2: {"skills": ["<plugin>:<skill>", ...], "model": "<model-id>"}
skills is cumulative for the session: list every Carta skill loaded so far, not only the one driving this call. Namespace each entry "plugin:skill" and keep them oldest-first, with the most recently used skill last. List only Carta skills (carta-cap-table:*, carta-crm:*, carta-investors:*) — never skills from non-Carta plugins.
</IMPORTANT>
[PATTERN carta-writing-style v0.0.2] [PATTERN etiquette v0.0.6] [PATTERN text v0.0.8] [PATTERN tables v0.0.12] [PATTERN carta-watermark v0.0.10] [PATTERN base v0.1.0]
Entry point for building a new budget. The skill routes to one of four
references in references/ based on user intent.
Inlined here because the Carta CLI session-start hook does not run inside Claude for Excel. Audience is an accountant.
ACCOUNT_TYPE, EFFECTIVE_DATE), UUIDs, raw JSON, SQL, or gate labels.X,XXX, negatives (X,XXX), totals bolded — using the resolved currency's symbol, not always $ (derive the currency from the data, never default to USD; see Hard rules).0 for a match, 2,000 for a gap, in the resolved currency.<citation:Sheet!Range>) in
Claude for Excel mode, and a file:// path in Claude Code / Cowork mode.
Never both.AskUserQuestion. Never
render the options as a bare code-fenced markdown list. The
AskUserQuestion tool is in allowed-tools; use it. Bare-text
menus render inline in Claude for Excel, which breaks the chooser UI
and forces the user to type the number.Build / create / generate / draft a budget for a future year ("build a 2026 budget", "draft from last year's actuals", "make me a 2026 budget for <entity>").
Also covers restructuring an existing budget in the workbook:
references/reorganize-categories.mdreferences/inflation-buffer.mdcarta-fetch-actualscarta-budget-analysiscarta-budget-scenarioscarta-consolidating-pnlcarta-consolidating-balance-sheetExecute all gates silently. Do not narrate tool calls, intermediate results, or status updates. Only speak at explicit decision points: Gate 0.5 (if runtime is ambiguous), Gate 1 (destination chooser), Gate 2 (parameter gate), Gate 5 (approval), and Gate 7 (next-step menu).
Do NOT output any of the following between gates:
carta_sandbox."Mandatory telemetry beacon — run this before any skip-gate check: If <SERVER> and <ENTITY_UUID> are already in context, call mcp__<SERVER>__set_context(firm_id=<ENTITY_UUID>, _instrumentation={"plugin": "carta-investors", "skills": ["carta-create-budget"]}) as your very first action. Do not skip this even when all data is already available — it records this skill invocation. If either is unknown, it fires in Gate 0 below.
Before Gate 0, check whether these context variables are already set from an earlier budgeting skill call in the same session:
<SERVER> — connected Carta MCP server prefix<ENTITY_NAME> — the resolved entity name<ENTITY_UUID> — the resolved entity UUID<RUNTIME> — excel-addin or local-fileIf all four are in context: skip Gates 0 and 0.5 entirely. In Gate 2, pre-fill the entity and skip asking for it — ask only for budget_year, window, and other budget parameters. Proceed from Gate 1.
If any is missing (fresh session or cold invocation): run Gates 0 and 0.5 in order, then continue from Gate 1.
Do not ask "which firm?" or "which runtime?" when those are already established from the skill the user just ran.
Scan the tools available in the conversation for any matching mcp__*__welcome. Extract the server identifier — the middle segment between the first and last __. Examples: mcp__carta__welcome → carta, mcp__claude_ai_Carta__welcome → claude_ai_Carta.
If none found: tell the user no Carta MCP is connected and stop.
If exactly one found: call mcp__<SERVER>__welcome(_instrumentation={"plugin": "carta-investors", "skills": ["carta-create-budget"]}) to verify. This is <SERVER>.
If multiple found: ask the user which to use via AskUserQuestion. Default to carta (production) if present.
Don't call any other mcp__<SERVER>__* tool before welcome — every other command is gated and will return a reminder.
<SERVER> is resolved only after welcome returns successfully. Do not call any other mcp__<SERVER>__* tool before welcome — every other command is gated behind it and will return a reminder instead of executing. This means list_contexts, set_context, and all DWH commands must be in a separate message that comes after welcome returns — never in the same parallel message.
The Carta MCP exposes three top-level tools: welcome, fetch, set_context. List contexts via fetch(command="contexts:list", …) — never a direct list_contexts top-level tool.
If the user named a firm:
mcp__<SERVER>__list_contexts(firm_name="<entity>", _instrumentation={"plugin": "carta-investors", "skills": ["carta-create-budget"]}). Do not use call_tool for list_contexts — call the granular tool directly with _instrumentation as shown.AskUserQuestion to disambiguate.mcp__<SERVER>__set_context(firm_id=<FIRM_UUID>, _instrumentation={"plugin": "carta-investors", "skills": ["carta-create-budget"]}). Do not use call_tool for set_context — call the granular tool directly with _instrumentation as shown. Do not skip this step — DWH queries scope to the active context. Proceeding without set_context means queries may return data for the wrong entity.DWH param-name traps:
dwh:execute:query takes sql:, NOT query:.dwh:get:table_schema takes table_name:, NOT table:.format accepts "ndjson" and "markdown". Not "csv".If no firm was named, defer to Gate 2.
Set <RUNTIME>:
excel-addin — references to "this workbook" / "the open spreadsheet" / open tab without a file path.local-file — user supplied a file path (~/Downloads/Budget.xlsx) or asked to "create a new file" / "write to disk".AskUserQuestion: "Are you working in Excel via Claude for Excel, or with a local .xlsx (Claude Code / Cowork)?"Branches by <RUNTIME>.
If <RUNTIME> is excel-addin:
Empty-workbook shortcut: if the active workbook has one sheet, maxRows == 0, no other tabs (typically a fresh Book1.xlsx/Sheet1), skip the chooser. Announce the rename in one sentence — "I'll use the empty workbook you have open and rename Sheet1 to Budget <year>." — then proceed. The chooser only exists to protect non-empty state.
Otherwise, use AskUserQuestion:
Where should I put the new budget?
Budget <year>.If the user has no workbook open at all, default to "brand new workbook" without asking.
If <RUNTIME> is local-file:
Use AskUserQuestion:
Where should I write the budget file?
Budget <year>).If the user gave a path in the original prompt, skip the choice and use that path.
Done when: the write destination is locked. Store <DESTINATION>
(open workbook + tab in add-in mode, or .xlsx path + sheet name in
local-file mode) for Gates 5–7.
In one AskUserQuestion call, ask for every parameter the prompt
didn't already specify (do not drip-feed):
contexts:list was ambiguous or the user didn't name one.budget_year — required, e.g. 2026.prior_year — default budget_year − 1.start_month / end_month, default 01 / 12.monthly (default) | quarterly | annually.all enabled (default) or a list of GL codes.account_lookback_years — default 3.Budget <budget_year>.If a sheet with that name already exists, ask whether to overwrite or append a suffix.
Call read_skill with the matching file_path before doing anything else in this gate. Do not reconstruct the layout or query logic from memory — the file must be in your context before you write any code.
| Phrase in user's prompt | Call |
|---|---|
| "from last year's actuals", "based on 2025 actuals", "from prior actuals", no qualifier | read_skill(file_path="references/from-prior-actuals.md") |
| "use the template", "fill in this template", "Carta template" | read_skill(file_path="references/from-template.md") |
| "add a line for <something not in CoA>", "I expect to spend $X on <new category>" | read_skill(file_path="references/from-recommendation.md") |
| "by department", "by reporting tag", "sliced by <dimension>", "by sub-account" | read_skill(file_path="references/slice-by-tag.md") |
| "group / categorize / organize line items into categories", "add category subtotals" | read_skill(file_path="references/reorganize-categories.md") |
| "add a 5% inflation buffer", "apply a contingency buffer", "pad expenses by X%" | read_skill(file_path="references/inflation-buffer.md") |
Do not ask the user which mode — infer from their original prompt. Follow the loaded file. The last two operate on an existing budget tab in the workbook rather than building from scratch — skip the prior-actuals fetch when the budget is already present.
Present the proposed budget as a preview table — one row per account, no collapsing sections into a single summary row. If there are 35 accounts, the table has 35 data rows plus section subtotal rows.
| Section | Line Item | GL Code | Prior-Year Total | Proposed Budget Total | Source |
|---|
Source values: DWH actual / trailing-avg / fallback-zero /
user-supplied / low-confidence — sparse history.
If any rows are flagged low-confidence — sparse history, call them
out above the table:
⚠ N line items have less than 6 months of history in the lookback window — their proposed amounts are best-effort. Review these before approving.
Output the preview table above as a normal conversation message. Then call AskUserQuestion immediately after — the question field must be a single short sentence; never include preview content inside it.
question: "Approve writing this budget?"header: "Approval"multiSelect: falseoptions:
label: "Approve and write the budget" / description: "Writes the budget to the destination chosen in Gate 1. ← recommended"label: "Edit — change a parameter (year / window / accounts / sheet name)"label: "Cancel"The ← recommended marker goes inside the description field of option 1, not as a suffix on the label. Do not write "Approve and write the budget ← recommended" as the label.
If the user picks Edit, return to Gate 2 with their feedback. Wait for explicit approval before writing.
Hard rule: no workbook-write tool (Excel-add-in cell write, execute_office_js that mutates state, write_workbook.py, or any equivalent) runs before this gate's AskUserQuestion returns the user's explicit "Approve and write" choice. If you catch yourself about to call a workbook-write tool without that approval recorded, stop and run this gate first.
Before calling execute_office_js with state-mutating code, setValues, write_workbook.py, or any other workbook-write tool, look back at your tool history. Find the most recent AskUserQuestion you sent. Does its answer literally include "Approve and write"? If NO, Gate 5 did not pass — send the Gate 5 approval menu now (preview table + 3-option AskUserQuestion) and wait for the explicit answer.
Do not interpret upstream answers as approval. A Gate 2 parameter response, a Gate 0.5 runtime answer, or any prior AskUserQuestion whose answer is not literally "Approve and write" does NOT clear this gate. Approval is the answer to the specific Gate 5 question — nothing else counts.
Restructure paths clear this gate the same way. The categorize-line-items and inflation-buffer paths (references/reorganize-categories.md, references/inflation-buffer.md) collect their own input first (the category mapping, or the buffer %), then present the standard Gate 5 pre-build review — a preview of the restructured tab plus the 3-option AskUserQuestion whose answer is "Approve and write". That "Approve and write" answer is what clears this check; the mapping/buffer confirmation alone does not.
Branches by <RUNTIME>. Writes two tabs — Budget <budget_year> (primary, hardcoded budget values) and <prior_year> Actuals (reference, hardcoded actuals). No Provenance tab.
Before writing a single cell, call both of these in the same message (parallel reads):
read_skill(file_path="references/from-prior-actuals.md") — layout, header band, column widths, section order, summary rows.read_skill(file_path="references/branding-and-header.md") — verbatim brand block JS and cell-comment API.Do not reconstruct either spec from memory. The files must be in your context before you generate any execute_office_js or write_workbook.py code.
<RUNTIME> is excel-addinGate 6 requires AT LEAST four separate execute_office_js calls. The most common failure mode is bundling cell writes + formatting + logo into one writeSheet(...) function — the model writes the cells, returns, and forgets the logo. Do not combine Step 6a and Step 6b into a single office.js block.
execute_office_js. Return.Budget <budget_year>. One execute_office_js with the verbatim brand block below.<prior_year> Actuals. Another execute_office_js with the same brand block, targeting the other tab.CartaLogo exists.Returning from Call 1 does NOT finish Gate 6. Returning from Call 2 does NOT finish Gate 6 — every tab needs its own logo call, and the verification call must come last.
Step 6a — write the cells. Use the Excel add-in's runtime cell-write tools with the accounting currency format for the resolved currency (see Hard rules). Do not call freeze_panes. For each low-confidence — sparse history account, attach a cell comment to the column-A label cell — see references/branding-and-header.md for the verbatim sheet.comments.add(...) pattern. Never change row fill / font color / border.
Step 6b — brand both tabs (DO NOT SKIP). Immediately after the cell writes — same Gate 6, before any summary text — embed the Carta lockup on every tab the skill just wrote.
For each tab the skill just wrote, run the verbatim brand block from references/branding-and-header.md — one execute_office_js per tab. Substitute <TAB_NAME>; do not paraphrase the JS. Asset access uses blobs.getText("assets/powered_by_carta.b64.txt") — NOT Read, NOT shell find. The unlock-set-relock dance preserves aspect ratio.
Step 6c — verify branding ran (REQUIRED, observable). Before proceeding to Gate 7, run this verification block as a separate execute_office_js call:
const tabs = ["Budget <budget_year>", "<prior_year> Actuals"];
const result = {};
for (const tabName of tabs) {
const sheet = context.workbook.worksheets.getItem(tabName);
sheet.shapes.load("items/name");
await context.sync();
result[tabName] = sheet.shapes.items.map(s => s.name);
}
return result;
The result must show CartaLogo in every tab's shape list. If any tab returns [] or its shape list lacks CartaLogo, you have skipped Step 6b for that tab — re-run the brand block for that tab and re-verify. Do not start Gate 7 summary text until this verification returns CartaLogo on every tab. The verification call itself is observable evidence; without it in your tool history, Gate 6 is not complete.
<RUNTIME> is local-fileBuild a single JSON operations payload that writes the cells AND
adds the logo on both tabs, then apply it in one shot. Branding is
part of the same payload — do not split it across two uv run calls,
do not leave it for "after the user reviews", do not defer it to a
follow-up step.
uv run "${CLAUDE_PLUGIN_ROOT}/scripts/write_workbook.py" --stdin <<'JSON'
{
"workbook_path": "<DESTINATION>",
"create_if_missing": true,
"operations": [
/* …all the cell-write ops for Budget <budget_year> and <prior_year> Actuals… */
{
"op": "add_image",
"sheet": "Budget <budget_year>",
"path": "${CLAUDE_PLUGIN_ROOT}/skills/carta-create-budget/assets/powered_by_carta.png",
"anchor": "E1",
"rows": 3
},
{
"op": "add_image",
"sheet": "<prior_year> Actuals",
"path": "${CLAUDE_PLUGIN_ROOT}/skills/carta-create-budget/assets/powered_by_carta.png",
"anchor": "E1",
"rows": 3
}
]
}
JSON
No freeze_panes op. Every set_format op for currency uses the locale-token format from the Hard rules section. For each low-confidence — sparse history account, include a set_comment op (see branding-and-header.md for the JSON shape). Response includes one add_image entry per tab with status: "ok"; status: "missing" means the asset path didn't resolve — fix it before moving on.
Budget values are hardcoded numbers. Subtotals, Total Income, Total Expenses, Net Operating Income use =SUM(...) formulas so totals recompute when the user edits a budget cell.
Done when: both tabs are populated AND both carry a CartaLogo shape (Excel) or an add_image op with status: "ok" (local-file).
Gate 7 precondition (DO NOT SKIP). Before sending the summary text below, scan your tool history. Three anchors MUST be present in that order:
AskUserQuestion whose answer included "Approve and write" — Gate 5 approval.sheet.shapes.addImage(base64) call for each tab the skill wrote (one per tab) — Gate 6b branding.execute_office_js whose result showed CartaLogo on every tab — Gate 6c verification.If any anchor is missing, you have skipped a gate. Do NOT write "Carta logo placed at..." in the summary when no shapes.addImage call appears in your tool history — that's hallucinating completion. STOP, go back, run the missing gate, then return here.
Restructure-path carve-out. The categorize-line-items and inflation-buffer paths (references/reorganize-categories.md, references/inflation-buffer.md) modify an existing, already-branded tab and do not run the brand block — they require only anchor 1 (the "Approve and write" response). Skip anchors 2 and 3 for these paths; do not add a second logo to a tab that already has one. (Only if the restructure rebuilt the tab from scratch and CartaLogo is gone do you re-run the brand block and re-verify.)
One or two sentences confirming what got written, with a clickable link to the result.
If <RUNTIME> is excel-addin:
Wrote Budget 2026 with 47 line items across 4 sections, and the source actuals on the 2025 Actuals tab. Carta logo placed at the top of column E on both tabs. Two lines (Salaries, LOC interest) flagged for review — see the Source column in the preview I showed you above.
If <RUNTIME> is local-file:
Wrote
Budget 2026(47 line items across 4 sections) plus a2025 Actualsreference tab tofile:///path/to/<budget-workbook>.xlsx, both branded with the Carta logo at the top of column E. Two lines (Salaries, LOC interest) flagged for review — see the Source column in the preview I showed you above.
Flag negative-NOI months in the summary. If any monthly Net Income figure in the written sheet is negative, surface the count:
"⚠ N of 12 months show negative NOI in this projection — review the lumpy revenue/expense lines before locking the budget."
Don't bury this in a table. The user needs to see it in prose so they can decide whether to revise before sending the workbook downstream.
The next-step menu MUST be a single AskUserQuestion call with the options below as options entries. Never render them as a numbered markdown list, a bulleted list, or inline prose — bare-text menus break the chooser UI in Claude for Excel and force the user to type the number. The ← recommended marker goes inside the description field of one option, not as a suffix on the label.
Call AskUserQuestion with these exact parameters:
question: "What would you like to do next?"header: "Next step"multiSelect: falseoptions: the four label + description pairs above (place ← recommended in the description field of the recommended option, NOT in the label)DO NOT render the menu as inline markdown text, a numbered list, a bulleted list, or closing prose. If your response is about to contain 1. ..., 2. ..., 3. ..., 4. ... as a list at the end of the summary instead of an AskUserQuestion tool call, you have failed this gate — back up and invoke the tool.
Mark one option ← recommended based on context — option 1 by default, option 2 if the budget year is already in progress, option 3 if the user mentioned cash pressure.
When the user selects an option, immediately invoke the corresponding skill via Skill('<skill-name>') BEFORE doing any work. Do not freelance the output — load the downstream skill's SKILL.md so its gates, layout spec, branding rules, and approval flow apply. Routing:
| Option | Skill to invoke |
|---|---|
| 1 — Refresh actuals against this budget | Skill('carta-investors:carta-fetch-actuals') |
| 2 — Run a pacing analysis | Skill('carta-investors:carta-budget-analysis') |
| 3 — Model a what-if scenario | Skill('carta-investors:carta-budget-scenarios') |
| 4 — I'm done | No invocation; close cleanly |
For queries > 50 rows, request format: "ndjson" and bucket the result into a blob before working with it. Pasting large results triggers context_snip and compresses earlier gate checks. Use "markdown" only for ≤50-row previews.
fetch("dwh:execute:query", …) directly — never a generic external-DWH connector. Filter by FUND_NAME = '<entity>' (never FIRM_NAME ILIKE). Use AMOUNT (never the base-currency variant — NULL in many datasets). Sign-flip revenue: CASE WHEN LEFT(ACCOUNT_TYPE,1) = '4' THEN -AMOUNT ELSE AMOUNT END. Preserve reversal entries as-is.=SUM(...) formulas so totals recompute when the user edits.welcome, or the currency on the actuals data); if it can't be resolved, ask the user. The A4 band reads Amounts in <resolved_currency>.$ (renders as system symbol on non-US locales):
[$$-en-US]#,##0.00_);([$$-en-US]#,##0.00);"-"[$€-x-euro2]#,##0.00_);([$€-x-euro2]#,##0.00);"-"[$£-en-GB]#,##0.00_);([$£-en-GB]#,##0.00);"-"[$CA$-en-CA]#,##0.00_);([$CA$-en-CA]#,##0.00);"-"<prior_year> Actuals tab.range.merge(true) destroys trailing cell values — never merge over a row that already holds sub-headers; insert a new row first."Jan 2026" auto-coerces to a date serial. Prefix with ' to force text, or write a real date with numberFormat: "mmm yyyy".style = "Continuous", then weight = "Thin". Never style: "Thin".CartaLogo shape (Excel) or add_image op with status: "ok" (local-file) before Gate 7 summary runs. Use the bundled assets in this skill's assets/ — never link to another plugin's assets..xlsx — the helper returns a "sheet exists" status; surface it to the user.Source: the Carta DWH journal-entries table. If column names are needed, look up the table via the Carta MCP DWH schema command once at Gate 0.
Never auto-retry. Always surface the failure and let the user decide.
contexts:list returns no firm → echo name, ask for spelling. Don't silently near-match.low-confidence, surface count, let user decide.Budget 2026 (2)), or cancel..xlsx.McpAuthError, "tool not available") → prefix mismatch, NOT auth. Re-run refresh_mcp_connectors, probe the matching prefix's welcome. Never tell the user to re-auth without verifying first.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。