Triggered when the user wants to create, open, switch, move, delete, or rename OpenLoaf's "project" entity. Typical phrasings: "new project", "add ~/code/foo", "list all projects". **Not for**: reading/writing files inside a project (→ use Read/Edit/Write directly), discussing "project planning / requirement docs" (→ answer directly), routine Git operations (→ `Bash`).
69
83%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
| Tool | Responsibility | Read-only |
|---|---|---|
ProjectQuery | Query project tree / single project details (mode: list / get) | Yes |
ProjectMutate | Create / update / move / delete projects (action: create / update / move / remove) | No |
Read / Glob / Grep | Read and search files within a project (always available) | Yes |
Edit / Write | Edit / create files within a project (always available) | No |
Bash | Run commands at the project root (Git, etc., always available) | No |
Loading:
Read/Glob/Grep/Edit/Write/Bashare core tools and always available;ProjectQuery/ProjectMutatemust be activated withToolSearch(names: "ProjectQuery,ProjectMutate")before calling to load their schemas.
User wants to operate on files
├─ Already in a project context? → Use file tools directly
└─ Not in a project context?
├─ Explicitly wants to create a project → ProjectMutate { action: "create" }
└─ Casual "help me write a script" → System auto-creates a temporary project (see below)list — Project tree + flat list: ProjectQuery { mode: "list" }
get — Single project details (omit projectId to use the current context): ProjectQuery { mode: "get" }
ProjectMutate { action: "create", title: "Q2 Marketing", folderName: "q2-marketing", icon: "📊", enableVersionControl: true }Pointing to an existing directory — When user provides a bare path, you must convert it to a file:// protocol URI:
/Users/user/code/repo → you pass rootUri: "file:///Users/user/code/repo"~/my-project → first expand ~, then build file:///Users/user/my-projectfolderName (disk-unfriendly characters cause problems)true, suitable for code projectsfalse (avoid meaningless Git init)false (repo already has .git)update: ProjectMutate { action: "update", projectId: "xxx", title: "New Name", icon: "🚀" }
move: ProjectMutate { action: "move", projectId: "xxx", targetParentProjectId: "parent-id" } (null = move to top level)
remove: ProjectMutate { action: "remove", projectId: "xxx" } — only unregisters the record, does not touch files on disk. The user's code and data are irreversible; disk contents are under the user's sovereignty.
When a user requests file operations in a global conversation (not a project context), the system automatically creates a temporary project under ~/.openloaf/temp/, transparent to the user.
| Attribute | Formal Project | Temporary Project |
|---|---|---|
| Creation | ProjectMutate { action: "create" } | Auto-created by the system |
| Disk location | User-specified or default directory | ~/.openloaf/temp/{sessionId}/ |
| Lifecycle | Manually removed by user | Can be promoted to formal project, or cleaned up with the session |
Exploring a project: ProjectQuery { mode: "get" } → Glob { pattern: "**/*" } → Grep → Read
Creating a project: ProjectQuery { mode: "list" } → ProjectMutate { action: "create", ... } → Write initial files → Bash to install dependencies
Malformed rootUri — Must use the file:// protocol, e.g., file:///Users/user/project; bare paths are not allowed. The cross-platform URI standard requires the protocol prefix; bare paths will fail to parse. Remember: three slashes (file:///) = protocol file:// + root path /. If the user wants to access a disk path outside the project directory, guide them to create a new project pointing to that directory — the sandbox cannot cross boundaries.
Confusing remove with deletion — remove only unregisters and does not touch disk, preventing accidental deletion of user code. If the user truly wants to delete files on disk, they must explicitly use Bash rm -rf.
Forgetting to query first — Before mutating, run ProjectQuery to confirm the projectId and current structure. projectIds are randomly generated; guessing and passing one will operate on the wrong project.
a1ab5be
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.