Workspace Sync & Share
TF Code integrates deeply with your ToothFairyAI workspace. Two commands move agents and skills between the two sides:
tfcode sync— the pull (downstream). Downloads your workspace's coder agents, agent skills, functions, and prompts into a local cache so Build and other agents can use them.tfcode agent share— the push (upstream). Uploads a local agent (and the skills it references) to your workspace as acoderagent.
They are exact mirrors of each other: sync pulls, share pushes.
Setup
Both commands use the active profile's credentials.
# Configure credentials (creates a profile)
tfcode setup
# Validate
tfcode validate
# Switch profile if you have more than one workspace
tfcode profile prod
Pass --profile <name> (or -p <name>) to either command to target a specific profile without switching:
tfcode sync --profile prod
tfcode agent share foo --profile prod
Sync (pull / downstream)
tfcode sync
tfcode sync --force # force a full re-sync
tfcode tools list # list what was synced
Sync calls your workspace API to read:
/agent/list→ coder agents/function/list→ agent_skill / api_function tools/prompt/list→ prompts
and caches the result to disk (.tfcode/tools.json, or .tfcode/tools-<profile>.json for non-default profiles).
The synced coder agents and agent skills then appear at runtime as read-only agents and skills (tagged [TF-synced] in the /agents dialog and the agent tool). They are merged with your local agents — a local agent with the same name takes precedence.
| Source | Editable? |
|---|---|
Local .tfcode/agent/*.md | Yes (agent tool, agent create/update/delete) |
| TF-synced (from sync) | Read-only (cannot be edited or deleted locally) |
Share (push / upstream)
Upload a local agent to your workspace as a coder agent.
# Create (or update) the agent "frontend-coder" + its referenced skills
tfcode agent share frontend-coder
# Target a specific profile
tfcode agent share frontend-coder --profile prod
# Preview what would be uploaded without making changes
tfcode agent share frontend-coder --dry-run
# Force-update a same-name workspace agent that has no local tf_agent_id
tfcode agent share frontend-coder --force
What gets uploaded
The command reads the local agent's markdown file from .tfcode/agent/<name>.md or .tfcode/agents/<name>.md and maps the fields:
| Local field | Cloud field | Notes |
|---|---|---|
name | label | |
description | description | |
| body (system prompt) | interpolationString | The "instructions" field |
goals | goals | |
temperature | temperature | |
model | llmBaseModel + llmProvider | Only sent when the provider is toothfairyai / tf |
Referenced skills are uploaded first (as agent_skill functions) and then linked to the agent. TF Code discovers the skills a local agent uses through its permission.skill.* allow rules:
---
permission:
skill:
"frontend-review": allow
---
You are a senior frontend engineer. ...
Each uploaded skill is recorded in a sidecar tf.json next to its SKILL.md, so a later share updates the same skill instead of creating a duplicate.
What is NOT uploaded
TF Code deliberately does not manage the many cloud-only agent fields. All of the following are left at their workspace defaults (never sent): every custom*Instructions field (customGreetingInstructions, customConclusionInstructions, customChartingInstructions, customSummarisationInstructions, customImagesInstructions, customToolingInstructions), plus planningInstructions, reviewInstructions, ragInstructions, voiceInstructions, analyticsInstructions, virtualDesktopInstructions, dynamicModelSelectionInstructions, and every planner / RAG / voice / memory / images / moderation field. Local agents only own the fields in the table above, and we keep it that way.
Create vs update (identity tracking)
agent share decides whether to create or update like this:
- If the local file has a
tf_agent_idfrontmatter, it updates that exact cloud record. This is the round-trip path — pull, edit, push a new version to the same agent your teammates already use. - Otherwise it looks for a workspace coder agent with
label === name:- found → warns and aborts unless
--force(which updates it); - not found → creates a new agent.
- found → warns and aborts unless
- On create, the resulting cloud id is stamped back into the local
tf_agent_idfrontmatter, so future shares keep updating the same record.
After a successful share, agent share re-runs sync so your local cache matches the cloud again.
The full round-trip
workspace (cloud) local disk workspace (cloud)
───────────────────── ────────────── ─────────────────────
coder agent A ─ sync ──▶ tools.json
(read-only, [TF-synced])
│ pull into a local .md
▼
.tfcode/agent/copy-of-a.md
(frontmatter tf_agent_id = A.id)
│ edit prompt / skills
▼
tfcode agent share copy-of-a
── POST /agent/update id=A ──▶ coder agent A (new version)
+ re-sync ◀───────────────────────────┘
Because tf_agent_id is preserved on the local file, sharing an edited copy updates the original cloud agent — teammates pick up the new version without a naming conflict.
Troubleshooting
| Error | Fix |
|---|---|
No profile configured | Run tfcode setup first. |
Local agent "<name>" not found | Create it (tfcode agent create) or add .tfcode/agent/<name>.md. |
already exists ... no local tf_agent_id | The name is taken in the workspace but the local file has no cloud id. Re-run with --force to update, or rename. |
model not uploaded | Only toothfairyai / tf provider models are sent; other providers are left to the workspace default. |