Claude was blocked from writing files, using git/gh, and fetching
web content because only a few Bash patterns were pre-approved.
Add Edit, Write, WebFetch, git, gh, sed, and python3 to the
allowed_tools list.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
The claude-code-action needs id-token: write to fetch an OIDC token.
The claude-cross-repo job was missing its permissions block entirely,
causing it to fail with "Could not fetch an OIDC token".
Co-Authored-By: Claude Opus 4.5 <[email protected]>
## Summary
- Move build/env/DB setup out of the GitHub Actions workflow into an
on-demand script (`packages/twenty-utils/setup-dev-env.sh`) that Claude
invokes only when needed
- Add Nx/build cache restore/save steps to speed up repeated runs
- Add `allowed_tools` so Claude can run the setup script and common dev
commands (nx, jest, yarn)
- Add `PG_DATABASE_URL` env var via `settings` for the postgres MCP
server
- Remove unnecessary `actions: read` permission grant
- Document the lazy setup pattern in CLAUDE.md
This makes read-only tasks (code review, architecture questions, docs)
fast by skipping the ~2min build/setup overhead, while still letting
Claude run tests and builds when it needs to.
## Test plan
- [ ] Comment `@claude what is the architecture of the backend?` —
should answer fast without running setup
- [ ] Comment `@claude run the twenty-server unit tests` — should call
setup script first, then run tests
- [ ] Verify cross-repo dispatch still works
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.5 <[email protected]>
## Summary
- Add `--model opus` to `claude_args` in both the direct and cross-repo
Claude jobs
## Test plan
- [ ] Merge and trigger @claude — verify it reports running Opus 4.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <[email protected]>
## Summary
- Add `repository_dispatch` trigger to `claude.yml` so `@claude`
mentions in `twentyhq/core-team-issues` get forwarded here
- New `claude-cross-repo` job: builds a prompt from the dispatch
payload, runs Claude Code against the twenty codebase, and posts a link
back to the source issue
- Switch both jobs to use `claude_code_oauth_token` instead of
`anthropic_api_key`
A companion workflow (`claude-dispatch.yml`) was pushed to
`twentyhq/core-team-issues` to send the dispatches.
## Test plan
- [x] Dispatch workflow in core-team-issues triggers successfully
(tested via issue #2194)
- [ ] After merge, verify `repository_dispatch` triggers the
`claude-cross-repo` job in twenty
- [ ] Verify Claude responds and posts a link back to the source issue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <[email protected]>
## 🤖 Installing Claude Code GitHub App
This PR adds a GitHub Actions workflow that enables Claude Code
integration in our repository.
### What is Claude Code?
[Claude Code](https://claude.com/claude-code) is an AI coding agent that
can help with:
- Bug fixes and improvements
- Documentation updates
- Implementing new features
- Code reviews and suggestions
- Writing tests
- And more!
### How it works
Once this PR is merged, we'll be able to interact with Claude by
mentioning @claude in a pull request or issue comment.
Once the workflow is triggered, Claude will analyze the comment and
surrounding context, and execute on the request in a GitHub action.
### Important Notes
- **This workflow won't take effect until this PR is merged**
- **@claude mentions won't work until after the merge is complete**
- The workflow runs automatically whenever Claude is mentioned in PR or
issue comments
- Claude gets access to the entire PR or issue context including files,
diffs, and previous comments
### Security
- Our Anthropic API key is securely stored as a GitHub Actions secret
- Only users with write access to the repository can trigger the
workflow
- All Claude runs are stored in the GitHub Actions run history
- Claude's default tools are limited to reading/writing files and
interacting with our repo by creating comments, branches, and commits.
- We can add more allowed tools by adding them to the workflow file
like:
```
allowed_tools: Bash(npm install),Bash(npm run build),Bash(npm run lint),Bash(npm run test)
```
There's more information in the [Claude Code action
repo](https://github.com/anthropics/claude-code-action).
After merging this PR, let's try mentioning @claude in a comment on any
PR to get started!
---------
Co-authored-by: Claude Sonnet 4.5 <[email protected]>
## Summary
- **Fix junction relation toggle not being saved**: The form schema
wasn't tracking the `settings` field, so changes to
`junctionTargetFieldId` weren't marked as dirty
- **Add type-safe documentation paths**: Generate TypeScript constants
from `base-structure.json` to prevent broken documentation links
- **Create many-to-many relations documentation**: Step-by-step guide
for building many-to-many relations using junction objects
- **Update `getDocumentationUrl`**: Now uses shared constants from
`twenty-shared` for base URL, default path, and supported languages
## Key Changes
### Junction Toggle Fix
- Added `settings` field to the form schema in
`SettingsDataModelFieldRelationForm.tsx`
- Fixed the toggle to properly merge settings when updating
`junctionTargetFieldId`
### Type-Safe Documentation Paths
- New constants in `twenty-shared/constants`:
- `DOCUMENTATION_PATHS` - All 161 documentation paths as typed constants
- `DOCUMENTATION_SUPPORTED_LANGUAGES` - 14 supported languages
- `DOCUMENTATION_BASE_URL` / `DOCUMENTATION_DEFAULT_PATH`
- Generator script: `yarn docs:generate-paths`
- CI integration: Added to `docs-i18n-pull.yaml` workflow
### Documentation
- New article:
`/user-guide/data-model/how-tos/create-many-to-many-relations`
- Updated `/user-guide/data-model/capabilities/relation-fields.mdx` with
Lab warning and link
## Test plan
- [ ] Verify junction toggle saves correctly when enabled/disabled
- [ ] Verify documentation link opens correct localized page
- [ ] Verify `yarn docs:generate-paths` regenerates paths correctly
## Summary
This PR reduces clutter at the repository root to improve navigation on
GitHub. The README is now visible much sooner when browsing the repo.
## Changes
### Deleted from root
- `nx` wrapper script → use `npx nx` instead
- `render.yaml` → no longer used
- `jest.preset.js` → inlined `@nx/jest/preset` directly in each
package's jest.config
- `.prettierrc` → moved config to `package.json`
- `.prettierignore` → patterns already covered by `.gitignore`
### Moved/Consolidated
| From | To |
|------|-----|
| `Makefile` | `packages/twenty-docker/Makefile` (merged) |
| `crowdin-app.yml` | `.github/crowdin-app.yml` |
| `crowdin-docs.yml` | `.github/crowdin-docs.yml` |
| `.vale.ini` | `.github/vale.ini` |
| `tools/eslint-rules/` | `packages/twenty-eslint-rules/` |
| `eslint.config.react.mjs` |
`packages/twenty-front/eslint.config.react.mjs` |
## Result
Root items reduced from ~32 to ~22 (folders + files).
## Files updated
- GitHub workflow files updated to reference new crowdin config paths
- Jest configs updated to use `@nx/jest/preset` directly
- ESLint configs updated with new import paths
- `nx.json` updated with new paths
- `package.json` now includes prettier config and updated workspace
paths
- Dockerfile updated with new eslint-rules path
Since tests are now run in the pre-merge queue with the latest main
version, they need not to be run again when merged into main, it would
be the exact same thing
I have set a
[rule](https://github.com/twentyhq/twenty/settings/rules/11470513) to
require `ci-e2e-status-check` to pass before merging. The problem is,
before merging, ci-e2e-tests are skipped (as we only want them to run
right before merging), so ci-e2e-status-check evaluates to `passed`,
which is re-used by the merge queue, even though we have a trigger for
e2e-tests in the merging queue phase.
The attempt to fix this is to give a different name to
`ci-e2e-status-check` in the merge queue phase (now being named
`ci-e2e-merge-queue-check`), and it is this status we should require in
the rule.
## Summary
This PR introduces a Skills system for AI agents, inspired by the [Agent
Skills specification](https://agentskills.io/specification).
## Changes
### Backend
- **SkillEntity**: New database entity with migration for storing skills
- **V2 Sync Mechanism**: Implemented FlatSkill, builders, validators,
and action handlers following the v2 flat entity pattern
- **Standard Skills**: Pre-defined skills (workflow-building,
data-manipulation, dashboard-building, metadata-building, research,
code-interpreter, xlsx, pdf, docx, pptx)
- **GraphQL API**: CRUD operations for skills with proper guards and
permissions
- **Workspace Cache**: Integrated skills into the workspace cache system
### Frontend
- **Skills Table**: Searchable table in AI settings showing all skills
- **Skill Form**: Create/edit page with Label (primary), Description,
and Content (markdown editor)
- **API Name**: Following existing patterns, name is derived from label
with advanced settings toggle for custom API names
- **Standard vs Custom**: Standard skills are read-only, custom skills
can be edited/deleted
## Key Design Decisions
- Skills are stored in the database (Salesforce-like approach) rather
than files
- Name is derived from Label by default (isLabelSyncedWithName pattern)
- Skills reference functions/files via @ mentions in markdown content
rather than explicit relations
- Standard skills are synced from code, custom skills are created via UI
## Screenshots
Skills table and form UI follow existing settings patterns.
## Testing
- [x] Lint passes
- [x] Typecheck passes
- [ ] CI tests
## Problem
The `front-sb-test` jobs were sometimes failing with:
```
Error: EEXIST: file already exists, mkdir './storybook-static/images/icons/android'
```
## Root Cause
1. `front-sb-build` builds storybook and saves NX cache (but NOT
`storybook-static/` folder)
2. `front-sb-test` restores NX cache - NX thinks build is done, but
`storybook-static/` doesn't exist
3. `storybook:serve:static` depends on `storybook:build`, so NX re-runs
the build
4. Race condition in Storybook's file copy causes EEXIST error
The `storybook-static` folder was **never** included in the cache paths
- I verified this by checking git history back to when the save-cache
action was created.
## Solution
Add `storybook-static` to the `additional-paths` for both save and
restore cache steps. This ensures the built storybook is properly cached
and restored, eliminating the need for a rebuild during tests.
This PR presents an attempt to increase the speed of the tests to run,
by using the same front-end built for Front and E2E CIs. It implied
merging front and E2E in one CI, but allowed to still have two different
status, and to have E2E run even if no front files have changed.
Also now using depot to build FE.
<img width="270" height="546" alt="image"
src="https://github.com/user-attachments/assets/d9eccc62-4494-4102-ad4e-241fec4bd4ea"
/>
Created by Github action
Pulls the latest documentation translations from Crowdin for all
supported languages:
- French (fr)
- Arabic (ar)
- Czech (cs)
- German (de)
- Spanish (es)
- Italian (it)
- Japanese (ja)
- Korean (ko)
- Portuguese (pt)
- Romanian (ro)
- Russian (ru)
- Turkish (tr)
- Chinese (zh-CN)
---------
Co-authored-by: github-actions <[email protected]>
## Summary
The Crowdin GitHub Action was failing at ~54% progress with the error:
> Failed to build translation. Please contact our support team for help
## Root Cause
The build was attempting to process all target languages configured in
Crowdin, including languages not supported by Mintlify (as defined in
`supported-languages.ts`). Some of these unsupported languages had
translation issues causing the build to fail.
## Fix
Added the `download_language` parameter to the Crowdin GitHub Action to
restrict downloads to only the languages supported by Mintlify:
- fr, ar, cs, de, es, it, ja, ko, pt, ro, ru, tr, zh-CN
## Testing
Verified via Crowdin API that builds succeed when specifying only these
supported languages, while the full build fails.
In this PR,
- current basic E2E tests are fixed, and some were added, covering some
basic scenarios
- some tests avec been commented out, until we decide whether they are
worth fixing
The next steps are
- evaluate the flakiness of the tests. Once they've proved not to be
flaky, we should add more tests + re-write the current ones not using
aria-label (cf @lucasbordeau indication).
- We will add them back to the development flow
# Introduction
In this pullrequest have been migrated to the flat standard entities:
Role, Agent and RoleTargets.
## What happens
- Removed createStandardMorph tool util in favor of dynamic typing of
`createMorphOrRelationStandardField`
- Implemented a command to remove standard agents and their role that
has been removed in https://github.com/twentyhq/twenty/pull/16513 also
added a default role target to data manipulator role to the only
remaining agent
- Implemented an agent deleteMany service handler
- moves applicationRoleId to application entity
- add new `APPLICATION` FieldActorSource and `APPLICATION`
JwtTokenTypeEnum value
- create a new token with applicationId when executing a function
- when applicationId is in token, check for application.defaultRole
permissions
-use twenty-shared types in `twenty-sdk/application`
- create a new import from generate called "Twenty" that you can use
directly without having to set TWENTY_API_KEY AND TWENTY_API_URL (keep
metadata or core parameter only)
- provide to serverless unique one time BEARER TOKEN to run it
Result
<img width="977" height="566" alt="image"
src="https://github.com/user-attachments/assets/e78428a0-5b13-4975-aa13-58ee3b32450c"
/>
<img width="910" height="596" alt="image"
src="https://github.com/user-attachments/assets/6ec72bf5-7655-4093-a45e-ad269595a324"
/>
<img width="741" height="568" alt="image"
src="https://github.com/user-attachments/assets/7683944c-fd79-4417-8fb2-8e4815cc112f"
/>
@charlesBochet had a conversation with Felix and he said we don't need
to spend time upgrading `zapier-platform-core` and `zapier-platform-cli`
since `twenty-zapier` will be deprecated anyway, making those packages
irrelevant.
I have updated tmp to a safer version elsewhere using `yarn up tmp
--recursive`. Also added `yarn.lock` to both server and front ci.
The massive changes in `yarn.lock` were introduced by
`zapier-platform-cli` version 17x - not sure if they caused those
breaking changes, but if they did and we still want update
zapier-related packages, I will take that up in another PR.
This fixes#15156
Issue:
Restore and Destroy buttons not appearing in action menu for deleted
records until the record detail view is opened.
Cause:
The record index/table view queries only fetched fields that were
visible as table columns
The [deletedAt] field (along with [createdAt] and [updatedAt]) was not
included in these queries since it's not a visible column
The action menu logic checks [selectedRecord?.deletedAt] to determine if
a record is deleted and which actions to display
Without the [deletedAt] field in the record store, the action menu
couldn't detect deleted records
Opening the detailed view would fetch all fields (including
[deletedAt]), which is why the buttons would appear afterward
Solution
Modified [useRecordsFieldVisibleGqlFields] to always include the
standard fields ([createdAt], [updatedAt], [deletedAt]) in record index
queries, regardless of column visibility. This ensures the action menu
can immediately detect deleted records
---------
Co-authored-by: Félix Malfait <[email protected]>
Co-authored-by: Félix Malfait <[email protected]>
## Problem
CI workflow started timing out on October 14, 2025 after commit
`d750df7fff` removed the trailing newline from `.env.example`.
## Root Cause
When `.env.example` lacks a trailing newline:
```bash
# Last line without newline
# CLICKHOUSE_URL=...twenty
```
And CI runs:
```bash
echo "NODE_PORT=3002" >> .env
```
Result:
```bash
# CLICKHOUSE_URL=...twentyNODE_PORT=3002 ← Commented out!
```
Server starts on default port 3000 instead of 3002, health check fails.
## Fix
1. **Restore trailing newline** to `.env.example`
2. **Make all CI `.env` operations robust** by adding `echo "" >> .env`
before appending
3. **Simplified `set_env_var`** function to always add newline first
Now works regardless of whether template files have trailing newlines.
## Files Changed
- 6 CI workflow files
- 1 .env.example file
## Problem
The concurrency rules in CI workflows were cancelling in-progress test
runs even on the main branch. This caused inconsistent check counts when
multiple commits were pushed in quick succession.
## Solution
Updated `cancel-in-progress` in all CI workflows to be conditional:
- **On main branch**: Tests run to completion (no cancellation)
- **On feature branches**: Tests are cancelled when new commits are
pushed (saves CI resources)
## Changes
Modified 11 workflow files to use:
```yaml
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
```
This ensures every commit to main gets fully tested while maintaining
efficiency on feature branches.
# Introduction
Fixed the build dependency leading to twenty-server start failing before
building,
Removed redundant steps
Make everything run on test db
# Introduction
Defining very first basis of the twenty-cli e2e testing env.
Dynamically generating tests cases based on a list of applications names
that will be matched to stored twenty-apps and run install delete and
reinstall with their configuration on the same instance
We could use a glob pattern with a specific e2e configuration in every
apps but right now overkill
## Notes
- We should define typescript path aliasing to ease import devxp
- parse the config using a zod object
## Some vision on test granularity
Right now we only check that the server sent back success or failure on
below operation. In the future the synchronize will return a report of
what has been installed per entity exactly. We will be able to snapshot
everything in order to detect regressions
We should also be testing the cli directly for init and other stuff in
the end, we could get some inspiration from what's done in preconstruct
e2e tests with an on heap virtual file system
## Conclusion
Any suggestions are more than welcomed !
close https://github.com/twentyhq/core-team-issues/issues/1721