Instruction file imported from hijera/foxxy-agent (
.cursor/rules/core-modules.mdc). Copyright stays with the author.
Core modules (sketch)
internal/acp- ACP RPC server, session lifecycle from editors.internal/agent- tool loop and LLM turns.internal/session- session manager and mode (agent/plan/docs/ask/debug).internal/config- YAML and flags.internal/mcp- MCP clients and transports, the merged server list, and the workspace trust gate. A project-local<cwd>/.foxxycode/mcp.jsonarrives with the checkout, soTrustGate(gate.go) is the single decision point between that list and a spawn or an outbound connection; it re-checks immediately before the transport opens. Approvals live in<home>/mcp-trust.jsonkeyed by canonical workspace and bound to a digest of the command-bearing declaration (trust.go). Never reachConnect/Probearound the gate for a configuration-derived server. Seedocs/features/mcp.md.internal/tools- filesystem, shell, todo, MCP merge, etc. Shell also owns the background task family (run_commandbackground: trueplusbackground_list/background_output/background_wait/background_stop/background_reap), backed byinternal/bgtask. Seedocs/features/background-tasks.md.internal/bgtask- process-wide, session-scoped pool for work that outlives a tool call. A task is whatever aRunnerstarts (CommandRunnerfor shell commands) or whatever aLaunchFunchands toPool.Launch: that is how a subagent run becomes aKindAgenttask, withSpec.Agent/Snapshot.Agent{name, session_id}naming the child session. One scheduling path (start) servesStart,AdoptandLaunch; do not add a second scheduling mechanism or status surface.internal/subagents- subagent definitions (markdown + YAML frontmatter,definition.go: aliases, bounds, SHA-256 digest,EffectiveTools/NarrowPermissionMode/ResolveTimeoutSeconds), the loader (loader.go:subagents.dirsprecedence, canonical scopesbuiltin/user/project,denynever reads project dirs), the trust receipts for project-scope files (trust.go:TrustStoreat<home>/subagents-trust.json,Decide, keyed by canonical workspace + name + digest undersubagents.project_trust), the process-wideLimiter(refuses, never queues), and the catalog (catalog.go:BuildCatalog,PromptBlock,WriteListing). Pure decisions only: no sessions, no loop.internal/agent/subagent.goapplies them (spawn hook, permission relay, report) andinternal/session/subagent.goowns child sessions (ordinarysess_ids, bundles nested under<parent>/subagents/,ErrSubagentReadOnly,DeleteSessionTree). Approval surfaces:foxxycode agents list|trust|untrust,POST /foxxycode/subagents/{name}/trust|untrust. Seedocs/features/subagents.md.Pool.Adopttakes over a foreground command that outlived its timeout instead of killing it, sharing the single scheduling path withStart.internal/hooks- operator lifecycle hooks: commands that read one JSON document on stdin at a point of a session and answer with an exit code plus optional JSON (definition.go: Claude Code's file shape, handler fields,Parse;matcher.go: exact-list-or-regex matchers with tool-name aliases such asBash->run_command;loader.go:hooks.files, canonical scopesuser/project,denynever reads project files,Source.Runnable;trust.go:TrustStoreat<home>/hooks-trust.json, receipts keyed by canonical workspace + workspace-relative file + digest underhooks.project_trust,Loader.WithStore;catalog.go:BuildCatalog,FindSource,WriteListing;runner.go: payload, sequential execution, timeouts and process groups viainternal/platform, the exit-code contract,Outcomemerging with the most restrictive decision winning). Pure decisions only: no sessions, no loop.internal/agent/hooks.goapplies them:PreToolUsebefore the permission gate andPostToolUse/PostToolUseFailureafter the tool inexecuteToolCall,UserPromptSubmit(reject, or context into the## Hook contextprompt block) andStop(follow-up submitted as a[Stop hook]user message, capped byhooks.stop_loop_limit) in the loop,PreCompact(veto) /PostCompactinCompactSession,SubagentStart(refuse, or context into the child's task) /SubagentStopinsubagent.go,Notification(permission_prompt) before the permission prompt;internal/session/hooks.gofiresSessionStartfrom the manager and persists its context ashookContext. Project-scope files followhooks.project_trustlike MCP declarations and subagent definitions; a held file is reported once per session as anotice-level UI log row. Approval surfaces:foxxycode hooks list|trust|untrust,GET /foxxycode/hooks,POST /foxxycode/hooks/trust|untrust. Seedocs/features/hooks.md.internal/skills- skill loading, enable/disable (loader.go,disabled.go), and remote install from repos / agents-standard marketplaces (remote.go,manifest.go,plugin.go:Sync/SyncSource(all or one source),AvailablePlugins/InstallPlugin(the Settings search and its per-skill install),AddSource,RemoveRemote/DeleteSkill(delete any on-disk skill; bundled = read-only viaSkillReadonly),ListSources,RemoveSource,CheckUpdates,UpdateSkill; a shallowinternal/gitws.Cloneinto a temp dir on every sync, http(s) clone and manifest URLs behind thewebfetchSSRF guard, materialized into${FOXXYCODE_HOME}/skillswith a.remote.jsonlockfile that records each skill's installedversion). Marketplace pluginversion(andSKILL.mdfrontmatterversion) are surfaced byInstalledVersionand drive update detection (compareVersions). Default dirs:~/.agents/skills(global, shared withnpx skills/npx skillsbd),~/.foxxycode/skills(foxxycode-specific, also where synced skills land),${CWD}/.foxxycode/skills(project-local;${CWD}is the session workspace, which HTTP resolves throughX-FoxxyCode-Session-ID). Remote sources are listed inskills.sourcesand fetched only on demand. Management parity across the CLI (foxxycode skills add|sync|remove,foxxycode plugin marketplace list|add|remove|sync,foxxycode plugin install|remove|enable|disable|list), the built-in/pluginchat command (internal/agent/plugin_command.go, deterministic like/compact; shared dispatcherskills.RunPluginCommand/MarketplaceStatusinplugin.go), HTTP (/foxxycode/skills/*), and the Settings → Skills UI. Seedocs/features/skills.md.internal/rules- rules catalog: one provider per root (factory.go:.foxxycode/rules, the shared.agents/rulesas systemagents-dir,.cursor/rules,.claude/rules,.codex/rules, the top-level.foxxyrules/.foxyrulesroots as systemfoxxycode(foxxyrules.go: a single file or a directory), plus the operator's own${FOXXYCODE_HOME}/rulesas systemuser-DefaultFactory(home)adds it, andDiscoveraccepts an absolute provider root for it; nestedAGENTS.mdfiles have no provider,agents.goreads them on demand throughAgentsForPathsfor the folders a tool enters and never walks the tree), dedupe by file name with precedence foxxycode > agents-dir > cursor > claude > codex > agents > user, the dialect picked by extension inmarkdown.go(.mdc= Cursordescription/globs/alwaysApply, default manual;.md= Claude Codepaths, unconditional without them; a header is read as YAML first, then by a lenient line reader because Cursor's ownglobs: **/*.gois not valid YAML), doublestar glob matching anchored atRule.Root(MatchGlob), activation (select.go:MatchAutoforfile://context andSelectMentionedfor@name;scope.go:MatchScopedfor filesystem tool-call paths against globs and nestedAGENTS.mdsubtrees) and thefoxxycode rules listtable (list.go:RenderCatalog).LoadProjectDocs(home, cwd)reads the agent home'sAGENTS.mdandDESIGN.mdfirst, above the workspace's own pair, with nothing inconfig.yamlnaming them, andAgentsForPathsreads the same pair (preambleFiles) for a folder a tool enters;RenderPromptreports the paths it embedded, sointernal/session/instructions_load.go(theinstructions.filesreader:${FOXXYCODE_HOME},${CWD},~and absolute entries) never sends the same file twice. Seedocs/features/rules.md.
Prefer extending these over growing cmd/ or duplicating logic in external/.
References
@architecture.mdc