workspace/¶
Workspace/home-directory management for ~/.sygen.
Files¶
paths.py: immutableSygenPaths+resolve_paths()init.py: workspace init pipeline, zone copy rules, rule sync, runtime notice injectionrules_selector.py: auth-aware RULES template selection/deployment + stale file cleanupcron_tasks.py: create/list/delete cron-task foldersskill_sync.py: cross-tool skill sync and bundled-skill syncloader.py: safe file readers
SygenPaths¶
Important runtime paths:
sygen_home:~/.sygen(default)workspace:~/.sygen/workspaceconfig_path:~/.sygen/config/config.jsonsessions_path:~/.sygen/sessions.jsonnamed_sessions_path:~/.sygen/named_sessions.jsonenv_file:~/.sygen/.envtasks_registry_path:~/.sygen/tasks.jsonchat_activity_path:~/.sygen/chat_activity.jsonstartup_state_path:~/.sygen/startup_state.jsoninflight_turns_path:~/.sygen/inflight_turns.jsoncron_jobs_path:~/.sygen/cron_jobs.jsonwebhooks_path:~/.sygen/webhooks.jsonlogs_dir:~/.sygen/logscron_tasks_dir:~/.sygen/workspace/cron_taskstasks_dir:~/.sygen/workspace/tasksapi_files_dir:~/.sygen/workspace/api_filesskills_dir:~/.sygen/workspace/skills(per-agent skills)global_skills_dir:~/.sygen/skills(global skills, shared across all agents)bundled_skills_dir: package_home_defaults/workspace/skills
init_workspace() order¶
- migrate legacy
workspace/tasks -> workspace/cron_tasks sync_bundled_skills(paths)_sync_home_defaults(paths)- ensure required directories
_ensure_sandbox_hook(paths)— sub-agents only; installs.claude/file_sandbox.py+settings.jsonRulesSelector(paths).deploy_rules()ensure_task_rule_files(paths.cron_tasks_dir)sync_rule_files(paths.workspace)_smart_merge_config(paths)_clean_orphan_symlinks(paths)sync_skills(paths)
Idempotent by design (called from multiple startup paths).
Directory creation note:
workspace/api_files/is not in_REQUIRED_DIRS; it is created lazily on first API upload viaprepare_destination(...).workspace/tasks/is part of_REQUIRED_DIRSand always created (used by sharedTaskHubtask folders).- sub-agent homes do not create
logs/by default; all agents write to the main home log file~/.sygen/logs/agent.log.
Zone copy rules (_walk_and_copy)¶
Zone 2 (always overwritten)¶
CLAUDE.md,AGENTS.md,GEMINI.md.pyfiles in:workspace/tools/cron_tools/workspace/tools/webhook_tools/workspace/tools/agent_tools/workspace/tools/task_tools/
Special case:
- when copying a template
CLAUDE.md, init also writes mirroredAGENTS.mdandGEMINI.mdin same target dir.
Zone 3 (seed once)¶
- all other files: copied only when missing.
Skipped template files (handled by RulesSelector):
RULES.mdRULES-claude-only.mdRULES-codex-only.mdRULES-gemini-only.mdRULES-all-clis.md
RULES deployment (rules_selector.py)¶
Template variants:
RULES.mdRULES-claude-only.mdRULES-codex-only.mdRULES-gemini-only.mdRULES-all-clis.md
Variant selection:
all-cliswhen 2+ providers are authenticatedcodex-onlywhen only Codexgemini-onlywhen only Gemini- otherwise
claude-only
Deployment outputs per authenticated provider:
- Claude ->
CLAUDE.md - Codex ->
AGENTS.md - Gemini ->
GEMINI.md
Cleanup removes stale provider files for unauthenticated providers, except inside workspace/cron_tasks/ (user-owned task rules).
Rule sync (sync_rule_files)¶
Recursive mtime-based sync for:
CLAUDE.mdAGENTS.mdGEMINI.md
Per directory:
- pick newest existing file
- copy to outdated existing siblings
- missing siblings are generally not created, except task-folder backfill via
ensure_task_rule_files(...)
Background watcher: watch_rule_files(workspace, interval=10s).
Watcher detail per cycle:
ensure_task_rule_files(cron_tasks_dir)backfills missing provider rule files in existing task folders.sync_rule_files(workspace)propagates newest content to older sibling rule files.
Runtime environment injection¶
inject_runtime_environment(paths, docker_container=...) appends two sections to each existing workspace rule file (CLAUDE.md, AGENTS.md, GEMINI.md):
## Multi-Agent Identity(main/sub-agent context + communication hints)- Docker mode notice (
/sygenmount) - host mode warning (no sandbox)
Duplicate prevention: injection is skipped when either marker already exists (## Multi-Agent Identity or ## Runtime Environment).
Sub-agent sandbox hook (_sandbox/file_sandbox.py)¶
Each sub-agent workspace gets a PreToolUse hook deployed into ~/.sygen/agents/<name>/workspace/.claude/ on every init:
file_sandbox.py— bundled hook source (read viaimportlib.resourcesfromsygen_bot.workspace._sandbox).settings.json— Claude CLI hook registration with matcherRead|Edit|Write|MultiEdit|NotebookEdit|Grep|Globand commandpython3 .claude/file_sandbox.py.
_ensure_sandbox_hook runs only when sygen_home.parent.name == "agents" (i.e. a path of the form ~/.sygen/agents/<name>/). Main agent is skipped.
Runtime behavior: the hook resolves the agent name from SYGEN_AGENT_NAME (injected by cli.executor._build_subprocess_env), reads additional_directories from ~/.sygen/_secrets/agents.json, and blocks (exit 2 + stderr) file-tool calls whose resolved target is outside <workspace> ∪ cwd ∪ additional_directories. Bash and other tools pass through. Pre-1.3.45 installs fell back to resolving the agent via cwd, which could be bypassed by cd into an allowlist directory — since 1.3.46 the env var is authoritative.
On init, any legacy sandbox_paths.json (empty stub from the first sandbox iteration) is removed.
Cron task folders (cron_tasks.py)¶
create_cron_task(...) creates:
cron_tasks/<safe_name>/
CLAUDE.md # only if Claude authenticated
AGENTS.md # only if Codex authenticated
GEMINI.md # only if Gemini authenticated
TASK_DESCRIPTION.md
<safe_name>_MEMORY.md
scripts/
Rule file selection is based on which provider rule files exist in the parent cron_tasks/ directory (deployed by RulesSelector during workspace init). Falls back to CLAUDE.md when no parent rule files are found.
Path traversal protection is enforced for create/delete operations.
sync_rule_files() itself only updates already-existing rule files by mtime. Missing task-folder rule files are created by ensure_task_rule_files(...) in init and watcher cycles.
Skill sync summary¶
sync_skills() syncs between per-agent and global Sygen scopes and the external CLI skill homes:
~/.sygen/workspace/skills(per-agent, main) /~/.sygen/agents/<name>/workspace/skills(per-agent, sub-agent)~/.sygen/skills(global, shared across agents)~/.claude/skills~/.codex/skills~/.gemini/skills
Default mode uses symlinks/junctions. Docker mode uses managed directory copies (.sygen_managed) so paths resolve inside container namespace.
See docs/modules/skill_system.md for scope semantics and the merged REST API.
Loader helpers¶
read_file(path) -> str | Noneread_mainmemory(paths) -> str