* manifest: add access_policies key and guided access-policies command doc
Adds the access_policies config key — a JSON array of allow/deny
statements that supersedes disabled_features and can scope a rule to
documents by Purview sensitivity label. The build script recognizes
the key (warn-only shape check for a JSON array), manifest.md documents
it alongside disabled_features, and a new access-policies command walks
the admin through fetching label GUIDs, choosing statements, and the
matching rules to explain before shipping.
* Validate access_policies statement structure; document grammar and slugs
The build script now parses access_policies and warns on each statement
that fails the grammar — bad effect, unknown resource or identifier type,
an operator the identifier type does not support (a GUID takes only
equals | exists), an empty identifiers array, a blank action slug. These
are the shapes the add-in drops silently, so the build is the only place
they get caught; an unparseable value is fatal.
Docs: add a statement-grammar reference and the full feature-slug list to
access-policies.md, sync the disabled_features table in manifest.md with
all four slugs, add the missing access_policies field to bootstrap.md,
and fix the parent-label prefix example to include the " - " separator.
* Add read-only add-in data export; harden cache-clear scripts
Chat history, skills, MCP registrations and memory live only in browser
storage on the user's machine. Add export-addin-data.{sh,ps1} to copy them
before a rebuild, and fix the cache-clear scripts that sit next to them.
clear-addin-cache.sh matched the add-in ID case-sensitively, but Office names
the wef file with whatever casing the manifest <Id> carried. A lowercase GUID
reported "already clear" and exited 0, sending admins to the folder-wide wipe
that destroys chat history on Windows. Match case-insensitively, and make a
miss print NOT cleared and exit non-zero on both platforms.
clear-addin-cache.ps1 never parsed on Windows PowerShell 5.1: em dashes in a
BOM-less .ps1 are decoded as ANSI into mojibake containing a quote, which
terminates a string mid-file. All .ps1 files are now pure ASCII, and check.py
rejects non-ASCII bytes in a .ps1 without a UTF-8 BOM.
Also:
- export: parse the port out of WebKit's binary origin file. Dropping it made
two origins on the same host collide in one export folder, silently
overwriting the first.
- export: include localStorage, which holds settings, the inference config,
and the onboarding/terms flags.
- export: exporting nothing while --out was given now exits non-zero, so
"export then wipe" cannot treat an empty backup as success.
- export: a failed database copy no longer aborts the run; paths containing
an apostrophe work.
- export.ps1: clear the destination before Copy-Item -Recurse, which nested
instead of refreshing on a re-run; add -IncludeAll for stores whose names
compaction has hidden; scan uncompressed LevelDB files first.
- clear.ps1: require a GUID for -Id, since Remove-Item -Path expands wildcards;
escape value names for Remove-ItemProperty.
- clear.sh: scan Outlook too, and guard flags that take a value.
- Document why replacing or reinstalling a manifest never moves the data.
Verified on macOS against live add-in data, and on a Windows host against
Windows PowerShell 5.1.
* Export Windows localStorage as the whole per-profile store
localStorage holds the settings, the inference/customer config, and the
onboarding + terms-accepted flags -- none of it in IndexedDB -- so an export
without it left a rebuilt machine re-doing onboarding.
Chromium keeps one LevelDB per profile shared by every origin, so it cannot be
filtered down to one add-in. Copy it whole rather than drop it, once per Office
account, beside that account's origin folders. It therefore also contains other
origins' settings: the size is printed on every run including the argument-less
preview, the help text says so plainly, and the folder can simply be deleted
from the export if a data policy forbids it.
- Copy to a scratch name and swap only on success. Deleting the destination
first meant a locked LOCK file (Office still running) left the export with
neither the new copy nor the previous good one. A failure is now counted and
reported as INCOMPLETE with a non-zero exit, matching the macOS script.
- Drive the copy off the unique profile list instead of the per-store loop, so
a profile whose only store fails the origin-name parse keeps its settings.
- Report in list mode too, matching macOS -- the argument-less run is
advertised as printing what it found.
- .SYNOPSIS/.DESCRIPTION no longer claim only Claude's data is copied.
- Correct the export-data doc: the export tree is relabelled for readability,
not a path mirror, so it cannot be copied back verbatim.
Verified on a Windows host against Windows PowerShell 5.1: copied once per
profile, flat on re-run, real LevelDB contents present, disclosed in list mode
without writing anything.
* manifest: add gateway_auth_source=entra param + Entra app registration docs (incl. GCC High)
- build-manifest.mjs: recognize gateway_auth_source; require entra_scope (→ graph_client_id, entra_sso=1); warn if paired with gateway_token; drop stale 'graph_client_id is Outlook-only' note
- manifest.md: new 'Use the Entra token as your gateway credential' section with a consolidated Entra app registration checklist (SPA redirect URI, Expose an API, admin consent, v2 tokens, gateway-side validation) and a GCC High/DoD subsection (portal.azure.us, .us issuer/JWKS)
* manifest.md: list both NAA redirect URIs (brk-multihub + https fallback)
The checklist only listed the https://.../msal-redirect.html SPA fallback. Desktop Office and Outlook web use the NAA broker, which requires brk-multihub://pivot.claude.ai registered as SPA — without it sign-in fails with AADSTS50011. Both are needed: brk-multihub for NAA, https for the Excel/Word/PPT Office-Web fallback where the NAA bridge isn't injected. Also pointed the earlier 'Bring your own Entra app' prose at the checklist instead of duplicating (incompletely).
* Split Entra app registration into commands/entra-app.md
manifest.md now documents what the params do; entra-app.md documents how to register the app (redirect URIs, per-use-case permissions table, admin consent, token version, backend validation, GCC-High/DoD, troubleshooting). Linked from every manifest.md section that needs your own app: graph_client_id, entra_scope, gateway_auth_source, sovereign clouds.
* docs(claude-for-msft-365-install): sovereign-cloud support via graph_cloud enum
The Outlook add-in now supports GCC-High, DoD, and 21Vianet tenants via a
single graph_cloud manifest parameter (global | us-gov-high | us-gov-dod |
china) that maps to fixed Graph + Entra endpoint pairs — no admin-supplied
URLs. Teach the install plugin about it:
- commands/manifest.md: per-tenant graph_cloud table; DoD must always set it
(shares an authority host with GCC High); non-global clouds require a BYO
graph_client_id; the enum also governs Word/Excel/PowerPoint Entra SSO.
- scripts/build-manifest.mjs: register graph_cloud and hard-fail on
unrecognized values or a non-global cloud without graph_client_id,
mirroring the add-in's load-time checks so admins see the error at build
time instead of an AADSTS code after deployment. Param building extracted
into an exported buildParams() for testability.
- scripts/build-manifest.test.mjs: node:test suite — default query string
unchanged, all enum values accepted, bad values and the removed URL params
rejected.
- .github/workflows/plugin-validate.yml: run the test suite on every PR.
* Drop manifest script tests — graph_cloud validation is two inline checks
The marketplace loader rejected 9 of 20 plugins on sync:
- 29 vertical-plugin SKILL.md sources had no YAML frontmatter — the
skill name/description sat in the body as a bare `description:` line
after the `# Title` H1. Synthesized proper `--- name/description ---`
frontmatter (name = skill dir, description = the existing body text),
matching the loading skills (e.g. fund-admin/accrual-schedule). Agent
bundles re-synced via scripts/sync-agent-skills.py (12 copies).
- 4 hooks/hooks.json were `[]`; the loader requires a JSON object.
Changed to `{ "hooks": {} }` — the form investment-banking already
uses and that synced clean.
- partner-built/spglobal defined the `spglobal` MCP server both inline
in plugin.json and in .mcp.json (identical). Dropped the inline copy;
.mcp.json is the canonical location.
scripts/check.py: OK — 80 files, 0 issues.
Co-authored-by: Jake Marsh <jakemarsh@anthropic.com>
* fix(ci): cache claude binary dir, not just the dangling symlink
~/.local/bin/claude is a symlink into ~/.local/share/claude/versions/<v>.
Caching only the symlink restored a dangling link on a cache hit, so
`claude` failed with exit 127. Cache the versioned dir too and bump the
cache key (-v2) to discard the broken saved entry.
* docs(claude-for-msft-365-install): add update + bootstrap sections, debug command row
fix(plugins): hooks.json must be {"hooks": {}} not []; add plugin-validate CI
The empty-array hooks.json in private-equity, financial-analysis,
equity-research and wealth-management caused those plugins to fail to
load ("Hook load failed: expected object, received array"). Replace [] with
the minimal valid {"hooks": {}} object in all four.
Add a plugin-validate workflow that runs the official `claude plugin
validate` over the marketplace manifest and every plugin on each PR and
push, so a malformed manifest fails CI instead of reaching users. The
CLI is installed from the official binary channel and cached, keyed on a
pinned version, so a warm cache skips the download entirely.
* feat(repo): plugin version-bump hook + CI backstop, fix install docs/remote
* docs(claude-in-office): add Wef registry + wef-folder sideload (Windows + macOS) for local debugging
* ci: use actions/checkout@v4 instead of pinned SHA
* docs(claude-in-office): scope sideload cleanup to the specific manifest, not the wef folder
* docs(claude-in-office): scope cache-clear to wef contents with guards, not rm -rf of caches/wef dirs
* docs(claude-in-office): target cache-clear by add-in Id, leave other add-ins in wef untouched
* feat(claude-in-office): add clear-addin-cache scripts (mac/win), ID-targeted, dry-run by default
* fix(claude-in-office): Windows sideload cleanup is registry-based, ID-first; direct edits (no office-addin-dev-settings); document deployed-cache caveat
* docs(claude-in-office): clarify surgical per-ID deletion of local/sideloaded manifests is safe; MS warning applies only to the deployed cache
* feat(claude-in-office): add sideload-addin scripts (mac/win), ID-derived, dry-run by default; debug.md points to script pair
* feat(claude-in-office): sideload installs directly (drop dry-run); dry-run stays only on destructive clear-addin-cache
* docs(claude-in-office): make the post-clear app restart an explicit step, not a buried line
The add-in now accepts entra_scope as a comma/whitespace-separated list and
no longer requires a URI-shaped value (Entra validates scope syntax, not the
build script). Update the docs and the build-manifest validation to match:
- build-manifest.mjs: entra_scope pattern relaxed to any non-blank string;
the graph_client_id pairing check is unchanged.
- manifest.md: document the multi-scope list syntax and the same-resource
constraint; clarify the build script enforces the pairing, not the format.
- bootstrap.md: note scp is a space-delimited list with multiple scopes.
- debug.md: add a Silent SSO / Entra token failures troubleshooting section
(AADSTS50194, entra_scope-without-graph_client_id, silent-then-popup).
build-manifest.mjs now takes a host argument (office | outlook). The
outlook host fetches manifest-outlook-3p.xml, which uses Microsoft's
MailApp schema and cannot share a file with the TaskPaneApp manifest
Excel/Word/PowerPoint use.
- URL_SLOTS regexes are now /g so all three Outlook taskpane URL entries
(FormSettings + V1_0 + V1_1 Resources) receive the config params, not
just the first match.
- New graph_client_id key for orgs that bring their own Entra app for
Microsoft Graph instead of consenting to Anthropic's multi-tenant app.
- aws_* keys with the outlook host fail fast: Bedrock is not currently
supported for Outlook.
- consent.md gains the Outlook Graph admin-consent URL (Mail.ReadWrite,
Calendars.Read, People.Read, User.Read, offline_access) and the
own-Entra-app alternative.
- manifest.md and setup.md document the host arg, the per-host file
split, and route admins to the consent step before generating the
Outlook manifest.
- Move verticals from repo root into plugins/vertical-plugins/ and partner
plugins into plugins/partner-built/
- Add 10 named, self-contained agent plugins under plugins/agent-plugins/
(Pitch Agent, Market Researcher, Earnings Reviewer, Model Builder,
Meeting Prep, GL Reconciler, Month-End Closer, Statement Auditor,
Valuation Reviewer, KYC Screener) — each bundles its own skills so it
installs standalone
- Add managed-agent-cookbooks/ (one per agent) with subagent isolation
and steering examples for /v1/agents deployment
- Add fund-admin and operations verticals so the finance-ops/onboarding
agents ship real domain skills
- Add scripts/ (check.py manifest lint, sync-agent-skills.py,
deploy-managed-agent.sh, orchestrate.py reference loop,
test-cookbooks.sh)
- Add .github/workflows/secret-scan.yml (gitleaks + internal-ref grep)
- Tighten agent tool grants to declared MCPs only — no Bash, WebFetch,
or undeclared mcp__* references in any agent
- Add not-investment-advice disclaimer to README
- Rename claude-in-office to claude-for-msft-365-install (content
unchanged)
Adds the new `otlp_resource_attributes` key (comma-separated k=v, same
format as OTEL_RESOURCE_ATTRIBUTES) to:
- build-manifest.mjs KEYS validator
- manifest.md / bootstrap.md telemetry sections
- update-user-attrs.md key table
Paired with anthropics/office-agent OA-336.
JSON object of extra HTTP headers the add-in attaches to every request
it sends to the configured gateway. Lets enterprise gateways receive
accounting or routing tags without a header-injecting proxy in front.
- build-manifest.mjs: KEYS validator entry
- manifest.md / bootstrap.md / update-user-attrs.md: documented with
example and reserved-header list
Adds examples/python-bootstrap/: a ~80-line FastAPI reference for the
bootstrap endpoint. Validates the Entra ID token, reads oid/groups from
claims, parses X-Claude-User-Agent for the Office host, and returns
skills + mcp_servers via a first-match RULES table in config.py.
Includes mint_dev_token.py (loopback-only RS256 dev tokens),
get_tenant_id.py, requirements.txt, and README.
Also documents the X-Claude-User-Agent request header and recommended
CORS preflight (Allow-Headers: Authorization, X-Claude-User-Agent, *)
in commands/bootstrap.md.
Add azure_resource_name and azure_api_key to the build-manifest KEYS
table so admins can bake Foundry config into the add-in manifest.
Document the Foundry path in setup.md and the keys table in manifest.md.
Adds gateway_api_format (anthropic | bedrock | vertex) to the config key
set so admins can deploy against gateways exposing Bedrock InvokeModel
or Vertex rawPredict pass-through routes instead of /v1/messages.
- build-manifest.mjs: KEYS entry with /^(anthropic|bedrock|vertex)$/
- setup.md: gateway wizard asks for API format; vertex => also capture
gcp_project_id + gcp_region; Step 6 smoke test now has three
format-specific curls (path + body shape differ per format)
- manifest.md / update-user-attrs.md / bootstrap.md: docs for the key
Adds mcp_servers to the recognized KEYS table so admins can bake an
org-wide MCP server list into the manifest URL. Documents the key in
commands/manifest.md alongside the other cross-cutting keys, with a
shell-quoted example and a pointer to bootstrap.md for the full schema
and per-user delivery.
Adds a new section to the /debug skill covering how to attach browser
devtools to the add-in WebView on both platforms. The macOS recipe
includes the three-gate sequence (defaults write, Safari Develop menu,
Sonoma Privacy & Security allowlist) plus the gotcha that Office updates
silently reset the defaults-write flag. Windows covers both WebView2
(right-click or Edge DevTools Preview) and the IE11/Trident legacy path
via IEChooser.exe.
Also adds a triage table row so admins asking 'how do I see the console'
route here directly.
Adds bootstrap_expires_at to the bootstrap endpoint response example
and explains it enables proactive config refresh — the add-in re-calls
the endpoint before expiry. Epoch seconds or milliseconds, auto-detected.
Explains the x-api-key vs Authorization: Bearer choice in the Gateway
section of setup.md, adds the key to manifest.md's per-cloud table, and
updates the Step 6 smoke-test curl with the alternate header form.
Adds gateway_auth_header to the KEYS table so admins can configure
which header carries the gateway token. Accepts "x-api-key" (default)
or "authorization" (sends Authorization: Bearer <token>).
Pairs with add-in support for the same key in CustomerConfig.
Consent is only required when entra_sso=1 (Bedrock or per-user config).
Gateway and Vertex with org-wide config skip it. Updates setup.md flow
and consent.md to reflect this.
Migrated from anthropics/office-agent. Provides /setup, /manifest, /consent,
/update-user-attrs, and /debug commands for M365 admins provisioning the
Claude Office add-in with direct cloud access (Vertex AI, Bedrock, or an
LLM gateway).
Portfolio-wide AI opportunity scanner for operating partners. Ingests
quarterly materials across portcos, runs a go/wait gate on each
(data ready? owner? 30-day pilot?), ranks quick wins by EBITDA impact,
and surfaces replays that hit multiple companies at once.
Substring matching checked 'T' before 'thousand', so 't' matched inside
'thousand' and returned the 1e12 multiplier instead of 1e3. Sort keys by
length descending so longer, more specific units always win.
- Rewrite competitive-analysis: cleaner prose, explain-the-why over imperatives
- Rename check-deck -> ib-check-deck with the same rewrite treatment
- Add deck-refresh: updates figures across an existing deck without rebuilding,
with a four-phase workflow (get data -> find all -> approve -> execute)