Cartaから管理会社(ManCo)の予算データを取得し、月別金額と小計を含むExcelファイルに書き込みます。 **このスキルは次のような場合に使用:** - Cartaの管理会社予算を取得・インポート・同期する **このスキルは以下の場合には使用されません:** - 実績データの取得(carta-fetch-actualsスキルを使用) - 新しい予算の作成(carta-create-budgetスキルを使用) - 実績データの更新、進捗管理、シナリオ分析、損益計算書、貸借対照表
Pull a ManCo budget from Carta and write it to an Excel workbook with monthly amounts and subtotals. TRIGGER: pull/fetch/import/sync Carta budget for a ManCo. NOT: pull/fetch/get actuals (carta-fetch-actuals), new budgets (carta-create-budget), actuals refresh, pacing, scenarios, P&L, balance sheet.
<!-- 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]
Pulls the budget for a management company directly from Carta via the
fa:list:budgets MCP command and lays it out as a single budget tab in
Excel. Only management companies carry budgets in Carta — funds and
SPVs do not — so the entity picker always lists the ManCo first.
Inlined here because the Carta CLI session-start hook does not run inside Claude for Excel. Audience is an accountant.
fa:list:budgets), UUIDs, raw JSON, or gate labels.X,XXX, negatives (X,XXX), totals
bolded — using the resolved currency's symbol, not always $. The workbook uses the
locale-specific token for the resolved presentation currency, which locks the
display to that currency regardless of the user's Excel locale. Derive the currency
from the data — never default to USD (see Hard rules).<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.Trigger this skill when the user asks for any of the following:
<ManCo>'s <year> budget from Carta"<ManCo> from Carta MCP"carta-create-budget.carta-fetch-actuals.carta-budget-analysis.carta-budget-scenarios.carta-consolidating-pnl. (If the user is
building a P&L and wants the Budget columns filled with Carta data,
carta-consolidating-pnl already integrates this skill's fetch logic in its
Gate 9 — do not duplicate the workflow.)Execute 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 (entity picker — if entity not already in context), Gate 3 (period picker), Gate 5 (approval), and Gate 7 (next-step menu).
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-fetch-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> and <ENTITY_UUID> — the resolved ManCo entity<RUNTIME> — excel-addin or local-fileIf all four are in context: skip Gates 0 and 0.5 entirely, and skip Gate 2 (<ENTITY_UUID> is already locked). Then run the remaining gates in full — do not stop after the period picker: Gate 1 (destination) → Gate 3 (period picker) → Gate 4 (fetch budget from Carta) → Gate 5 (pre-build review) → Gate 6 (write and brand) → Gate 7 (summary). Skipping Gates 4–7 would write empty or stale data without re-fetching.
If any is missing (fresh session or cold invocation): run Gates 0, 0.5, and 2 in order, then continue from Gate 1.
Do not ask "which firm?" when the entity is 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-fetch-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.
Resolve firm: if user named one → mcp__<SERVER>__list_contexts(firm_name="<firm>", _instrumentation={"plugin": "carta-investors", "skills": ["carta-fetch-budget"]}) → disambiguate via AskUserQuestion if multiple → mcp__<SERVER>__set_context(firm_id=<FIRM_UUID>, _instrumentation={"plugin": "carta-investors", "skills": ["carta-fetch-budget"]}). Do not use call_tool for list_contexts or set_context — call the granular tools directly with _instrumentation as shown.
DWH param-name traps: dwh:execute:query takes sql: not query:. dwh:get:table_schema takes table_name: not table:. format accepts "ndjson" / "markdown", not "csv".
If no firm was named, defer to Gate 2.
This skill runs in two runtimes. Detect which one applies before asking where to write:
.xlsx files on disk.See carta-create-budget/SKILL.md Gate 0.5 for the heuristic. If unclear, ask
via AskUserQuestion. Store <RUNTIME> (excel-addin or local-file).
Branches by <RUNTIME>. Before showing any chooser, scan the
destination for an existing budget tab — if one is found, lead with
"update in place" instead of defaulting to a new tab.
A sheet counts as an "existing budget tab" when either is true:
Budget (case-insensitive), e.g.
Budget FY2026, 2026 Budget, MgmtCo Budget.Account in a label
column AND at least 6 month-like headers (Jan, Jan 2026,
2026-01, etc.) in the same row.Stop at the first match — the user can always pick another tab via the "choose a different tab" branch.
If <RUNTIME> is excel-addin:
<EXISTING_BUDGET_TABS>.<EXISTING_TAB_DATA[tab_name]>. Gate 5's
update-in-place matching uses this cached read — no second workbook
read is needed later.If <RUNTIME> is local-file:
Only scan if the user already supplied a workbook path in their prompt (otherwise there's nothing to scan yet — defer detection to the file they pick next).
uv run "${CLAUDE_PLUGIN_ROOT}/scripts/read_workbook.py" \
"<PATH>"
Apply the same heuristic to the JSON output. For each matched tab, store
its full content (all rows) from the read_workbook.py output as
<EXISTING_TAB_DATA[tab_name]> — Gate 5's update-in-place matching reuses
this cached read exactly as in the add-in path; no second read is needed.
If <EXISTING_BUDGET_TABS> is non-empty (excel-addin or local-file with a path):
Use AskUserQuestion:
I see a budget tab already in your workbook (
<existing tab name>). Want me to update it with Carta's data, or write the budget somewhere else?
| # | Option | What happens |
|---|---|---|
| 1 | Update <existing tab name> in place ← recommended |
Refreshes the budget values on the existing tab — same accounts, same row positions; no new tab is created. |
| 2 | Add a new tab | Creates Budget FY<year> alongside the existing tab. |
| 3 | Pick a different existing tab to update | Lists all sheets in the workbook and asks which one. |
| 4 | Cancel | Stops the skill. |
If multiple existing budget tabs are found, list up to 3 of them as
option 1a / 1b / 1c (inside the same AskUserQuestion call) — never
silently pick one.
Update-in-place semantics (option 1):
<EXISTING_TAB_DATA[tab_name]> already read at Gate 1 — do not
re-read the workbook. Identify the label column (the column that
holds account names) and the month columns from that cached data. Treat
any cell where is_formula: true as load-bearing — subtotal / Net
Operating Income / FY-total rows stay formula-driven and are never
overwritten.gl_code or account_name) row already in the
sheet, write the new monthly budget values into the existing month
cells. The tab's row positions, section headers, formulas, and
formatting all stay put.Source: Carta Fund Admin (refreshed <ISO date>) so the user can see
when the values were last pulled.If <EXISTING_BUDGET_TABS> is empty:
Excel add-in runtime — 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 FY<year>." — then proceed. The chooser only exists to protect non-empty state.
Otherwise, use AskUserQuestion with the default options:
Excel add-in runtime:
Where should I put the Carta budget?
Budget FY<year>.Local-file runtime:
Where should I write the budget file?
Budget FY<year>. After loading, re-run the budget-tab detection — if the loaded file has an existing budget tab, jump back to the "update in place" chooser above.If the user gave a path in the original prompt, skip the choice and use that path (but still run the detection on it).
Store <DESTINATION> for Gates 5–7.
Critical: in Carta, only management companies carry budgets. Funds
and SPVs return empty from fa:list:budgets.
Call read_skill(file_path="references/entity-picker.md") before proceeding. Do not reconstruct the picker logic from memory. Summary of the rule:
call_tool({"name": "fa__list__entities", "arguments": {}, "_instrumentation": {"plugin": "carta-investors", "skills": ["carta-fetch-budget"]}}) against the active firm.(LLC|Management|Mgmt|ManCo|Capital, LLC) AND with no Fund /
Partners / SPV qualifier.← recommended), then other entities below it, then a final option
"None of these — let me type the name".AskUserQuestion.If the user already named the entity in their prompt and it resolves to exactly one ManCo, skip the picker. Otherwise always ask.
If a non-ManCo is picked, warn before fetching:
"Heads up — only management companies carry a budget in Carta. If I pull
<entity>, the result will likely be empty. Want me to pick the ManCo instead?"
Done when: <ENTITY_NAME> and <ENTITY_UUID> are locked.
In one AskUserQuestion call, ask for the period the prompt didn't
already specify. Offer smart defaults based on today's date —
compute year, half, and quarter labels dynamically, never copy the
example values below.
What period should I pull the budget for?
Example shape — rendered with today's date = May 2026. Substitute <CURRENT_YEAR> and <CURRENT_QUARTER> at runtime.
| # | Label | Date range |
|---|---|---|
| 1 ← recommended | Full year <CURRENT_YEAR> |
Jan 1 – Dec 31, <CURRENT_YEAR> |
| 2 | H1 <CURRENT_YEAR> (Jan – Jun) |
Jan 1 – Jun 30, <CURRENT_YEAR> |
| 3 | H2 <CURRENT_YEAR> (Jul – Dec) |
Jul 1 – Dec 31, <CURRENT_YEAR> |
| 4 | <CURRENT_QUARTER> <CURRENT_YEAR> |
(computed from today's date) |
| 5 | Custom range — I'll specify start / end month | — |
Always compute the current quarter label and year dynamically from today's date — never hardcode Q2 / 2026 / etc. Drop the H1 row once the current month is past June (H1 is fully in the past then — fold it into "Custom range"). Show the prior year as an option only if the user mentioned it in their prompt.
If the prompt already specified a year or range (e.g. "2026 budget", "H1"), store it directly and skip the question.
Store <BUDGET_YEAR>, <START_DATE> (<YEAR>-<MM>-01), <END_DATE>
(last day of <end_month>).
No tag breakdown available. The budget data from Carta (fa:list:budgets)
contains no reporting dimension — it returns one amount per account per
month. If the user asks for budget broken down by department, project
code, or any other tag, tell them in one sentence — "Carta's stored budget
isn't broken down by tag, so I can only return flat monthly totals." — and
offer to route them to a different skill via AskUserQuestion (never a
bare numbered list — see the UX Rules at the top of this skill).
Call AskUserQuestion with these exact parameters:
question: "Carta's stored budget has no tag dimension. How should I continue?"header: "Tag breakdown"multiSelect: falseoptions:
label: "Continue with the flat budget pull" — description: "No tag dimension; returns one amount per account per month."label: "Build a new tag-sliced budget from journal actuals instead" — description: "← recommended for tag breakdowns. Hands off to carta-create-budget's slice-by-tag mode; uses last year's actuals as the seed."If the user picks option 2, hand off via Skill('carta-investors:carta-create-budget')
with the slice-by-tag routing — that skill's slice-by-tag mode is the
canonical way to produce a budget broken down by reporting tag.
The ← recommended marker goes inside the description field of option 2, not as a suffix on the label. Bare-text numbered lists break the chooser UI in Claude for Excel and force the user to type the number — same rule as every other choice in this skill.
Call read_skill(file_path="references/fetch-budget-data.md") before issuing any MCP calls. Do not reconstruct the fetch contract from memory. Summary of the contract:
call_tool({"name": "fa__list__budgets", ...}) call per month for
every month in the requested window. For a full-year pull this is
exactly twelve calls (Jan 1–31, Feb 1–28/29, …, Dec 1–31). Issue all
twelve in one parallel batch and merge the row lists. If your runtime
limits concurrent tool calls, batch into two groups of six — but never
serialize further. Do not try a single annual or quarterly window
first — the MCP response truncates past ~40 KB and every wider window
the user has been observed needing has hit that cap.Verbatim call template — do not omit fund_uuid. The MCP rejects
the call with "missing required params: ['fund_uuid']" if the param
isn't passed. <ENTITY_UUID> is the UUID locked at the end of Gate 2.
call_tool({"name": "fa__list__budgets", "arguments": {
"fund_uuid": "<ENTITY_UUID>",
"start_date": "<YYYY-MM-01>",
"end_date": "<YYYY-MM-{28|29|30|31}>"
}, "_instrumentation": {"plugin": "carta-investors", "skills": ["carta-fetch-budget"]}})
The param is named fund_uuid for historical reasons but it accepts any
entity UUID returned by fa:list:entities. Pass the ManCo UUID Gate 2
resolved — never an empty value, never a name, never skip the param.
{account_id, account_name, account_type, amount, start_date} into a {account_type → account_name → {month: amount}}
map. Sum if multiple postings hit the same month + account.account_type ascending.Section mapping (by leading digit of account_type, same convention
as the other budgeting skills):
| Prefix | Section |
|---|---|
4xxx |
Income |
5xxx / 6xxx / 7xxx / 8xxx |
Expenses |
1xxx |
Investments / Other |
| anything else | Other |
If the fetched dataset is empty (no rows): stop and tell the user
plainly — "I didn't find any budget rows in Carta for <ENTITY> for
<BUDGET_YEAR>. Common causes: the entity isn't a ManCo, or no budget
has been loaded into Carta yet for that year." Offer to retry against a
different entity or year.
Done when: the budget dataset is loaded into the
account_type → account_name → {month: amount} map and tagged by
section.
Branches by the Gate 1 write mode (new-tab, overwrite-tab,
new-workbook, or update-in-place).
new-tab, overwrite-tab, new-workbook)Present a plain-English preview before any write:
Ready to write Carta's 2026 budget for
Example Capital, LLC— please review.
- Source: Carta Fund Admin (live)
- Entity: Example Capital, LLC (ManCo)
- Period: Jan 2026 – Dec 2026
- Income accounts: 1
- Expense accounts: 47
- Sheet to write:
Budget FY2026in<DESTINATION>- Projected FY totals: Income <CCY>13,788,809 · Expenses <CCY>8,530,121 · Net Operating Income <CCY>5,258,689
update-in-place)Run the match step first (see Gate 1's "Update-in-place semantics") and classify every row:
Preview shape:
Ready to refresh
Budget FY2026in your open workbook with Carta's 2026 budget forExample Capital, LLC.
- Source: Carta Fund Admin (refreshed live)
- Existing tab:
Budget FY2026- Existing rows to refresh: 41 line items
- Cells to update: ~492 monthly amounts (excluding formula subtotals)
- Carta rows missing from your sheet: 6 line items (would be inserted if you approve)
- Sheet rows missing from Carta: 2 line items (will be left untouched)
Line item Old monthly avg New monthly avg Source Software (7005) $23,000 $25,000 Carta refresh … … … …
Account in Carta but missing from your sheet Section Projected FY Leased employee — guaranteed payments (7051) Operating Expenses $2,675,004 Investor relations — events (7203) Operating Expenses $12,504
If there are Carta rows missing from the sheet, ask via
AskUserQuestion whether to insert them (above the right section
subtotal, per the same logic as
references/fill-budget-columns.md step 4) or
skip them this run.
Output the preview 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?" (Mode A) / "Approve refreshing in place?" (Mode B)header: "Approval"multiSelect: falseoptions:
If Edit, return to the right gate. Wait for explicit OK 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" or "Approve and refresh"? If NO, Gate 5 did not pass — send the Gate 5 approval menu now and wait for the explicit answer.
Do not interpret upstream answers as approval. A Gate 2 entity-pick response, a Gate 3 year-range answer, or any prior AskUserQuestion whose answer is not literally "Approve and write" / "Approve and refresh" does NOT clear this gate. Approval is the answer to the specific Gate 5 question — nothing else counts.
execute_office_js calls (excel-addin runtime)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 the cell-write call with the brand block in a single office.js block.
execute_office_js. Return.sheet.shapes.addImage(...)).CartaLogo exists.Returning from Call 1 does NOT finish Gate 6. The verification call must come last and must appear in your tool history.
Branches by the Gate 1 write mode. Before any write, call read_skill(file_path="references/branding-and-header.md"). Do not reconstruct the brand block or header band from memory — the file must be in your context before you generate any execute_office_js or write_workbook.py code. It defines the reserved 4-row metadata band (A1 entity / A2 descriptive title like "2026 Budget (from Carta Fund Admin)" / A3 source / A4 other context), Carta logo placement (column E, rows 1–3 height), the blobs.getText("assets/...") asset-loading pattern for Excel add-in (NOT Read), and the cell-comment pattern for any flagged rows. The tab is not "written" until it carries a CartaLogo shape.
This is the no-new-tab path. Apply the matched changes from Gate 5 directly to the existing tab:
write_cell (or the add-in equivalent)
for every (existing row × month) pair where Carta returned a value.
Hardcoded numbers, never formulas. Preserve every other cell on the
tab — labels, GL codes, section headers, formula subtotals, FY total
formulas, formatting.is_formula: true). The tab's =SUM(...) subtotals, Total Income,
Total Expenses, and Net Operating Income re-evaluate automatically.references/fill-budget-columns.md step 4.
After insertion, rewrite the affected section subtotal
=SUM(...) formulas so the new rows are included. Match the
formatting of neighboring rows (currency format, font, no fill).Source: Carta Fund Admin (refreshed <ISO date>).Budget FY<year>.Skip the layout section below — the tab already has its layout. Jump to Gate 7.
new-tab, overwrite-tab, new-workbook)Layout (4-row metadata band per branding-and-header.md):
| Row | Content |
|---|---|
| A1 | <ENTITY_NAME> — bold, size 10 |
| A2 | <BUDGET_YEAR> Budget (from Carta Fund Admin) — bold, size 10 |
| A3 | Source: Carta Fund Admin · fa:list:budgets — italic, size 10 |
| A4 | Amounts in <resolved_currency> — italic, size 10 (derive the currency from the data, never default to USD) |
| Row 5 | blank — breathing room between header band and column headers |
| Row 6 | Column headers starting in column A: Account | Jan <year> | Feb <year> | … | Dec <year> | FY <year> Total — bold, white-on-black, centered. No GL-code / "Account #" column. |
Body — for each section (Income → Expenses → Other), in this order:
Income,
Operating Expenses, Other). No cell borders.account_type.
Column A = account_name, columns B..M = monthly amounts (hardcoded
numbers). The GL code (account_type) is used only to sort and
section the rows — it is not written as a column.=SUM(<section_range>) per monthly column and for column N.After the last section:
Total Income — bold, top thin border, sums all Income subtotals.Total Expenses — bold, top thin + bottom medium border, sums all
Expense subtotals.Net Operating Income — bold, top thin + bottom medium border,
=<Total Income> - <Total Expenses> per monthly column and for column N.
Set numFmt="@" on the column-A label if it contains a slash.Column N = =SUM(B<row>:M<row>) for every account, subtotal, and total row.
Currency format (every numeric cell) — use the locale-specific token for the resolved currency, never a bare $ or "$" (renders in system locale on non-US installs):
[$$-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);"-"Recalc + column widths (excel-addin): the last statements in the cell-write execute_office_js block, in this order — never a separate call:
context.application.calculationMode = Excel.CalculationMode.automatic;
context.workbook.application.calculate(Excel.CalculationType.full); // else =SUM cells stay 0 → render as "-" until edit+Enter
sheet.getRange("A:A").format.columnWidth = 180; // account-name column — fixed; prevents long names driving it too wide
sheet.getRange("B:N").format.autofitColumns(); // size amounts (B:M) + FY total (N) to REAL values (after recalc → no ####)
await context.sync();
Force the recalc before the autofit: without it the =SUM(...) subtotals / Total / NOI cells sit at 0 and the accounting format shows - (the user then has to edit+Enter each one); and autofitting before the recalc sizes the amount columns to the dash, so the real figures overflow as ####. In local-file mode, add a set_column_width op on column A (width 160), then an autofit_columns op over B:N. Do not call freeze_panes.
Column-width anti-pattern: Do NOT call autofitColumns() on a header-only range like B1:N1 — header rows are often empty at write time, leaving the amount columns too narrow for 5+ digit currency (####). Always autofit the full amount span (B:N) after the data is written. Full recipe: carta-create-budget/references/from-prior-actuals.md §6.
If <RUNTIME> is excel-addin: write via the Excel add-in's
runtime cell-write tools, applying the same number format.
If <RUNTIME> is local-file: build a JSON operations payload and
apply it:
uv run "${CLAUDE_PLUGIN_ROOT}/scripts/write_workbook.py" --stdin <<'JSON'
{
"workbook_path": "<DESTINATION>",
"create_if_missing": true,
"operations": [ ... ]
}
JSON
After running the brand block from branding-and-header.md, run this verification as a separate execute_office_js call before proceeding to Gate 7:
const tabs = ["<TAB_NAME_WRITTEN_THIS_RUN>"]; // substitute the actual tab name(s)
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 the brand block for that tab — re-run it and re-verify. Do not start Gate 7 summary text until this verification returns CartaLogo on every tab. The verification call is observable evidence; without it in your tool history, Gate 6 is not complete.
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" or "Approve and refresh" — Gate 5 approval.sheet.shapes.addImage(base64) call for the tab the skill wrote/modified — Gate 6 branding.execute_office_js whose result showed CartaLogo on the tab — Gate 6 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.
One or two sentences confirming what got written. Wording branches on the Gate 1 write mode.
If <RUNTIME> is excel-addin:
Wrote Budget FY2026 for Example Capital, LLC — 1 income account, 47 expense accounts, source Carta Fund Admin (live). FY total: Income <CCY>13,788,809 · Expenses <CCY>8,530,121 · Net Operating Income <CCY>5,258,689.
If <RUNTIME> is local-file:
Wrote
Budget FY2026for Example Capital, LLC tofile:///path/to/budget.xlsx— 1 income account, 47 expense accounts, source Carta Fund Admin (live). FY total: Income <CCY>13,788,809 · Expenses <CCY>8,530,121 · Net Operating Income <CCY>5,258,689.
If <RUNTIME> is excel-addin:
Refreshed Budget FY2026 in place with Carta's 2026 budget for Example Capital, LLC — 492 cells updated across 41 line items, 6 new rows inserted (Operating Expenses), 2 sheet rows left untouched (no Carta budget for those accounts). Refreshed FY total: Income <CCY>13,788,809 · Expenses <CCY>8,530,121 · Net Operating Income <CCY>5,258,689.
If <RUNTIME> is local-file:
Refreshed
Budget FY2026infile:///path/to/budget.xlsxwith Carta's 2026 budget for Example Capital, LLC — 492 cells updated, 6 new rows inserted, 2 sheet rows left untouched. Refreshed FY total: Income <CCY>13,788,809 · Expenses <CCY>8,530,121 · Net Operating Income <CCY>5,258,689.
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.
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 — Build the P&L with this budget pre-filled | Skill('carta-investors:carta-consolidating-pnl') |
| 2 — Refresh actuals against this budget | Skill('carta-investors:carta-fetch-actuals') |
| 3 — Run a pacing analysis | Skill('carta-investors:carta-budget-analysis') |
| 4 — I'm done | No invocation; close cleanly |
fa:list:budgets without fund_uuid — MCP rejects with "missing required params: ['fund_uuid']". Pass <ENTITY_UUID> (locked at end of Gate 2) as params["fund_uuid"].fa:list:budgets returned.carta-create-budget.)welcome, or the currency on the budget data); if it can't be resolved, ask the user. The A4 band reads Amounts in <resolved_currency>. Use the locale-specific format token — never a bare $ (renders as system symbol on non-US locales): USD [$$-en-US], EUR [$€-x-euro2], GBP [$£-en-GB], CAD [$CA$-en-CA].Worksheet.position in a separate context.sync(), never in the same statement as worksheets.add(). Create and activate first: const sh = sheets.add(name); sh.activate(); await context.sync();.range.merge(true) discards trailing cells. Insert a new row first.' or use numberFormat: "mmm yyyy" on a real date.style = "Continuous" then weight = "Thin". Never style: "Thin".references/branding-and-header.md for every tab. Rows 1–4 reserved, logo at column E, blobs.getText("assets/...") for asset access.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.fa:list:entities returns no ManCo → surface full entity list, let user pick. Flag that picked entity may not have a budget.fa:list:budgets returns empty → "No budget rows in Carta for <entity> <year>. Likely the entity isn't a ManCo, or no budget loaded yet." Offer retry.=SUM) → refresh lines, ask whether to recompute subtotals. Default to leaving alone if no reply..xlsx.McpAuthError) → prefix mismatch, NOT auth. Re-run refresh_mcp_connectors, probe matching prefix's welcome. Never tell user to re-auth without verifying.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。