The SwapCore + Flock integration brings together intelligent financial management and real-time team communication so you can automate workflows, manage payments, and collaborate without switching platforms. No more juggling tools or missing updates. With this integration, every payment, invoice, or financial alert flows directly into your Flock workspace keeping your team aligned, informed, and moving faster.
Generative AI in a development pipeline sounds dangerous only until you understand exactly where the boundaries are. ShipifyAI is designed so that the AI has exactly the permissions it needs to do its job, and not a single permission more. This article describes the four pillars that make up the security model.
The first guarantee is that the AI cannot see your other secrets, because the worker runs on a dedicated, isolated machine that does not contain them. The second is that the AI does not modify your Jira directly, because every Jira operation goes through the ShipifyAI backend with a strict whitelist of allowed actions. The third is that the AI cannot push to the default branch, because GitHub branch protection rules and the limited scope of the GitHub PAT make it impossible. The fourth is that the AI is not even given the structural ability to push to the default branch, because we do not rely on the AI behaving well, we make it incapable of misbehaving.
The principle is simple. The worker, meaning the ShipifyAI CLI together with Claude Code, should not run on your laptop and should not run on a machine that holds any of your other credentials. The right environment is a dedicated container, an LXC instance, or a separate VM. It should be a clean system without your personal configuration, restarted on a regular schedule so that any temporary state is cleared.
What the machine must contain is exactly the runtimes the worker needs. That means Node.js, Python, Claude Code, the ShipifyAI CLI, and Git. It means the project's toolchain, which is installed during the clone process. And it means the tokens that ShipifyAI provides for one project, namely the GitHub PAT, the Jira credentials, and the Slack token. Nothing else.
What the machine must not contain is anything that gives access to other systems. The user home directory should not contain SSH keys, because those would let the AI reach other repositories or other servers. It should not contain AWS, GCP, or Azure credentials, because those would expose production cloud resources. It should not contain a kubeconfig pointing at a production cluster, because that would expose the running infrastructure. It should not contain `.env` files from other projects, because those would expose Hygraph keys, Stripe keys, OpenAI keys, SendGrid keys, and any other application secret you have ever stored locally. It should not contain a logged-in browser session or saved cookies, because those would give access to admin panels. And it should not contain a 1Password CLI session, a `pass` store, or any other secret manager, because that would be a single bridge to all your other credentials.
A practical setup is a slim Alpine-based Docker container with Node.js, Python, Git, Claude Code, and the ShipifyAI CLI, running as a non-privileged user, started with `docker run --rm` so that nothing persists across runs, and configured through environment variables so that no secret is ever written to disk. After the container exits there is no leftover state on the host.
This is the foundation that makes the recommended Claude configuration safe. With `allowAll` enabled at the Claude layer, the AI can run any shell command it wants, but the machine simply does not have anything dangerous to operate on. A spurious `cat ~/.aws/credentials` returns no such file. The security boundary is at the system layer, not at the AI layer, and that boundary holds even if the AI is fully trusted to do whatever it considers useful.
The architecture is intentional. The AI never has the Jira API token. The token lives encrypted in the ShipifyAI database and is decrypted only by the backend. Every change to your Jira board, every status transition, and every comment is performed by the backend in response to a structured signal from the worker. The AI reports, the backend acts.
The signals are narrow. The worker can report that a task description is unclear, in which case the backend moves the task to the Incomplete column and adds a comment with the `[AI GENERATED]` prefix and the reason. It can report that work is starting, in which case the backend moves the task to In Progress. It can report that work is finished and a pull request is open, in which case the backend moves the task to In Review and posts a Slack notification. It can report that a command was blocked by the allowList, in which case the backend posts a Slack notification asking for approval.
What the AI cannot do is everything else. It cannot create new tasks. It cannot delete tasks. It cannot move a task backward, since transitions are one-way through Ready, In Progress, In Review, and Incomplete. It cannot change the assignee, the priority, the sprint, or the story points. It cannot post comments without the `[AI GENERATED]` prefix. It cannot perform arbitrary transitions, because the backend enforces a whitelist.
The consequence is that even if a prompt injection embedded in a task description tried to convince the AI to close every task in a sprint as Done, the AI would have no tool to do it. At worst it would send a false report to the backend, which would still only execute one of the small set of allowed actions on the legitimate task it is operating on. The blast radius of any single prompt injection is one task and one comment.
This is also why the Claude configuration article warns against connecting an MCP server to Jira or GitHub on the worker machine. Such an MCP would bypass the backend and give the AI direct API access to your project tracker, which would undo the guarantee in this section. If you want this guarantee, do not plug Jira or GitHub MCP servers into the worker.
This is one of the most common fears, and it is solved by three independent layers. Each layer alone would suffice. Together they form a deep defence.
The first layer is GitHub branch protection on the default branch, configured in the repository settings. The protection should require a pull request before merging, require at least one approval, dismiss stale approvals when new commits are pushed, require code owner review where applicable, require status checks to pass, require branches to be up to date before merging, require conversation resolution, restrict who can push, and refuse to allow bypassing these rules. With this configuration, every attempt to push directly to the default branch is rejected by GitHub itself, before the request even reaches your repository's history.
The second layer is the scope of the GitHub Personal Access Token. The PAT given to ShipifyAI should be a fine-grained token restricted to the single repository the worker operates on. Its permissions should grant Read and write to Contents and to Pull requests, Read-only to Metadata and Workflows, and nothing else. In particular it should not have the Administration scope, because Administration would let the token bypass branch protection by editing the rules. With this scope, even if the AI somehow tried to disable protection, the GitHub API would refuse.
The third layer is the convention of the `[AI GENERATED]` prefix combined with a human review. Every pull request the AI opens has the prefix in its title. Every such pull request requires a human reviewer to approve it before merge. This is an organisational layer rather than a technical one, but it adds a second pair of eyes on every change that lands on the default branch.
Concretely, when the AI runs `git push origin main` the response from GitHub is a refusal with the protected branch error code. When it runs `git push --force origin main` the response is the same refusal, plus the PAT does not have force push privileges anyway. When it tries to merge a pull request through the API with administrator override, the PAT does not have admin rights, so the API refuses. When it tries to edit the branch protection rules to weaken them, the PAT does not have the required scope. The defence is layered, redundant, and structural.
There is a fourth layer too, although it is treated as belt-and-braces rather than as the primary defence. Even with `allowAll` enabled at the Claude layer, the deny list in the project's `.claude/settings.json` should still block `git push origin main`, `git push --force`, and a literal `rm -rf` against the root. These are cheap to keep, hard to need, and they make forensics easier if something ever does go wrong.
The third pillar describes the layers that make a push attempt fail. The fourth pillar goes further and says that we do not rely on layers that could in principle be misconfigured. We design the system so that the AI never receives the capability in the first place.
The backend never hands the worker a token capable of pushing to the default branch. The PAT validation step at project creation time verifies the scope and refuses to store a token that has overly broad permissions. The CLI itself only operates on a fresh feature branch with a name derived from the Jira task identifier. Push operations target only that branch. The default Claude settings shipped in the starter skill pack include a deny list that explicitly blocks pushes to the default branch and force pushes. Every commit the AI makes carries the `[AI GENERATED]` prefix, which makes any historical anomaly trivially auditable.
Security on the default branch therefore rests on multiple independent layers, each of which is sufficient on its own. GitHub branch protection is technical and authoritative. The PAT scope is technical. The CLI's internal logic is technical and lives on our side. The Claude deny list is technical and lives on the worker. The required pull request review is organisational. Even if any single layer is removed by accident, the others continue to hold.
The AI does see your source code, because it must clone the repository to work on it. It sees the contents of `CLAUDE.md`, the skill files in `.claude/skills`, and the contents of `.claude/settings.json`. It sees the body of the Jira task it is acting on, including any comments. During the active session it holds the GitHub PAT in memory, because it needs the token to push the feature branch.
The AI does not see your Jira API token, because that token is used only by the backend. It does not see other projects on your ShipifyAI account, because the worker is bound to one project at a time. It does not see other repositories on GitHub, because the PAT is fine-grained and scoped to one repository. It does not see your ShipifyAI account password, the 2FA secret, or the backup codes. It does not see the contents of your inbox, your calendar, or any cloud storage account.
The lifecycle of the GitHub PAT during an active session is constrained. The backend decrypts the PAT from the database, transmits it over HTTPS to the CLI, and the CLI keeps it only in memory. The CLI sets up a one-shot Git credential helper for the duration of the session so that Git itself can read the token without it being written to disk. When the CLI exits, the in-memory copy is gone and no file containing the token is left behind on the worker machine.
After the initial setup it is worth running a small audit pass to confirm everything is configured as intended. Inspect the branch protection rules on the default branch through the GitHub API and confirm that pull requests, approvals, status checks, and bypass restrictions are set as expected. Inspect the PAT scope and confirm the absence of administrative or destructive scopes. Inspect the worker filesystem and confirm there are no SSH keys, AWS credentials, or unexpected `.pem` files. Inspect `~/.claude/settings.json` on the worker and confirm the deny list contains pushes to the default branch and force pushes.
If you want even stronger isolation, several upgrades are available. An egress firewall on the worker can reduce outgoing traffic to the small set of domains the worker actually needs, namely the GitHub API, your Atlassian site, the Slack API, the Anthropic API, the ShipifyAI backend, and the package registries you depend on. A read-only filesystem for everything outside the project working directory can prevent any accidental writes elsewhere. Seccomp or AppArmor profiles can block syscalls the worker does not need. A regular rotation of the GitHub PAT, taking advantage of fine-grained tokens that support automatic expiry, ensures that any leak has a bounded lifetime. And the activity log endpoint exposed by the ShipifyAI backend gives you a continuous audit trail of every action the worker has reported.
The four guarantees of the ShipifyAI security model are that the AI cannot read your other secrets because the worker is isolated and does not hold them, the AI cannot modify your Jira directly because the backend acts on its behalf with a whitelist, the AI cannot push to the default branch because of branch protection and PAT scope, and the AI does not even have the structural capability to push to the default branch because every layer of the system is designed to refuse. Security here does not rely on trusting the AI. It relies on the fact that even an untrusted worker has no tools with which it could cause harm.
The configuration article explains how to generate properly scoped tokens for each integration. The Claude configuration article explains the deny list and the isolation model in operational detail. The control article covers the operational side of safety, namely how a human takes over from the AI when needed.