<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Manuel Bruña</title>
    <description>The latest articles on DEV Community by Manuel Bruña (@tecnomanu).</description>
    <link>https://dev.to/tecnomanu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F938087%2Fadc3c6af-233f-4eb1-90c8-37af70ebe3f2.jpeg</url>
      <title>DEV Community: Manuel Bruña</title>
      <link>https://dev.to/tecnomanu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tecnomanu"/>
    <language>en</language>
    <item>
      <title>A Local Admin Panel Still Needs Auth in APX</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Wed, 05 Aug 2026 12:04:02 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-local-admin-panel-still-needs-auth-in-apx-4n1n</link>
      <guid>https://dev.to/agentprojectcontext/a-local-admin-panel-still-needs-auth-in-apx-4n1n</guid>
      <description>&lt;h1&gt;
  
  
  A Local Admin Panel Still Needs Auth in APX
&lt;/h1&gt;

&lt;p&gt;A local admin panel should feel convenient, not anonymous.&lt;/p&gt;

&lt;p&gt;That boundary matters for APC and APX.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps project meaning in the repo through &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent files, skills, and other committed artifacts. APX is the daily-use runtime and tooling layer. It exposes that project through a daemon, CLI, web admin, pairing flow, and local state under &lt;code&gt;~/.apx/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because APX owns runtime state, it also has to protect it.&lt;/p&gt;

&lt;p&gt;That is why the web admin in APX does not treat &lt;code&gt;localhost&lt;/code&gt; like a permission model.&lt;/p&gt;

&lt;p&gt;At first glance, a local-only UI can look harmless. If the browser and daemon are on the same machine, it is tempting to assume the panel can just trust every request. But the panel can read projects, sessions, messages, MCPs, config, and other runtime-only data. APC keeps portable project context in the repository, but APX keeps operational state outside the repo for a reason. That state still needs an access boundary.&lt;/p&gt;

&lt;p&gt;APX handles this with a small bootstrap path instead of making the whole HTTP surface public.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/host/daemon/api/shared.js&lt;/code&gt;, auth is bearer-token based. Data routes require &lt;code&gt;Authorization: Bearer ...&lt;/code&gt; unless they are on a short allowlist. The important exception is &lt;code&gt;/admin/web-token&lt;/code&gt;, which is intentionally unauthenticated only so the local admin bundle can bootstrap itself. The comments are explicit: &lt;code&gt;/admin/web-token&lt;/code&gt; is for the same-origin admin panel, and that endpoint performs its own localhost checks.&lt;/p&gt;

&lt;p&gt;The allowlist stays narrow on purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/health&lt;/code&gt; stays public for liveness checks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/pair/*&lt;/code&gt; stays open so a fresh device can bootstrap a token.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/admin/web-token&lt;/code&gt; stays open so the local browser can fetch its bearer.&lt;/li&gt;
&lt;li&gt;Static assets and known SPA routes can load without a token, but data GETs do not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point is the important hardening step.&lt;/p&gt;

&lt;p&gt;Older daemon designs often used prefix denylists and accidentally leaked new data routes when somebody forgot to register them. APX goes the other direction. In the auth middleware, unknown extension-less GET routes are treated as protected by default. Only static files and known client-router paths pass before the token is present.&lt;/p&gt;

&lt;p&gt;The tests make this concrete.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tests/health-auth.test.js&lt;/code&gt; checks that &lt;code&gt;/projects&lt;/code&gt; rejects missing or wrong bearer tokens, while &lt;code&gt;/assets/app-abc123.js&lt;/code&gt; and &lt;code&gt;/settings&lt;/code&gt; can load without getting blocked by the auth wall. &lt;code&gt;tests/security-hardening.test.js&lt;/code&gt; adds regression coverage for routes like &lt;code&gt;/plugins&lt;/code&gt; and &lt;code&gt;/skills&lt;/code&gt;, asserting that they now require a token even though they are GET endpoints.&lt;/p&gt;

&lt;p&gt;So the web panel opens in two phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The browser loads the shell and assets.&lt;/li&gt;
&lt;li&gt;The panel fetches &lt;code&gt;/admin/web-token&lt;/code&gt; and uses that bearer for actual API calls.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The docs describe the same flow. On the local machine, the panel fetches its token automatically from &lt;code&gt;/admin/web-token&lt;/code&gt;. On another device, &lt;code&gt;apx pair web&lt;/code&gt; prints a URL with a &lt;code&gt;#token=...&lt;/code&gt; fragment so the paired browser can authenticate without exposing the full daemon publicly by default.&lt;/p&gt;

&lt;p&gt;That design fits the APC/APX split well.&lt;/p&gt;

&lt;p&gt;APC should stay portable, reviewable, and repo-owned. It should not need to encode browser auth rules. APX should own runtime concerns such as daemon auth, paired devices, local sessions, and route protection. If those concerns leak back into APC, the project contract gets polluted with machine-local policy. If APX ignores them, the runtime becomes too trusting.&lt;/p&gt;

&lt;p&gt;So the practical rule is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APC defines project context.&lt;/li&gt;
&lt;li&gt;APX exposes runtime surfaces.&lt;/li&gt;
&lt;li&gt;Every runtime surface still needs an access boundary, even on localhost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A local admin panel is still an admin panel.&lt;/p&gt;

&lt;p&gt;APX gets that right by keeping the portable layer clean and putting authentication exactly where the runtime belongs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>APX Should Assemble Context, Not Dump APC Into Every Prompt</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Tue, 04 Aug 2026 12:04:23 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/apx-should-assemble-context-not-dump-apc-into-every-prompt-3fid</link>
      <guid>https://dev.to/agentprojectcontext/apx-should-assemble-context-not-dump-apc-into-every-prompt-3fid</guid>
      <description>&lt;h1&gt;
  
  
  APX Should Assemble Context, Not Dump APC Into Every Prompt
&lt;/h1&gt;

&lt;p&gt;A portable context system becomes less useful the moment a runtime treats it like a blob.&lt;/p&gt;

&lt;p&gt;That is the line APC and APX need to keep clear.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It gives a repository durable project meaning through &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent files, skills, and other committed artifacts. APX is the daily-use runtime and tooling layer. Its job is not to shovel all of that into every turn. Its job is to assemble the smallest useful prompt for the current surface and request.&lt;/p&gt;

&lt;p&gt;That distinction matters because prompt assembly is a runtime problem, not a file-format problem.&lt;/p&gt;

&lt;p&gt;If an agent runtime blindly dumps full project context into every prompt, three things usually go wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prompt budgets get wasted on context that does not matter for this turn&lt;/li&gt;
&lt;li&gt;the model gets nudged toward irrelevant instructions&lt;/li&gt;
&lt;li&gt;the portable layer starts getting blamed for runtime bloat it did not cause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;APX avoids that by treating APC as a source of durable context, then selecting pieces deliberately.&lt;/p&gt;

&lt;h2&gt;
  
  
  What APX actually assembles
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;src/core/agent/prompt-builder.js&lt;/code&gt;, &lt;code&gt;buildSuperAgentSystem()&lt;/code&gt; builds the final system prompt as layered blocks instead of one giant static file. The assembled prompt can include role, user context, memory, active threads, channel rules, project guidance, skills hints, lazy tools, voice mode, and final format directives.&lt;/p&gt;

&lt;p&gt;That design matters because different turns need different slices.&lt;/p&gt;

&lt;p&gt;A web-admin session can tolerate longer markdown guidance. A one-shot CLI call should stay tighter. Voice mode is not even treated as its own channel. APX keeps channels as surfaces and layers voice on top as a mode. That avoids fake channel duplication and keeps formatting rules narrower.&lt;/p&gt;

&lt;h2&gt;
  
  
  APC stays durable; APX stays selective
&lt;/h2&gt;

&lt;p&gt;The useful APC lesson here is simple: durable context should exist in the repo, but runtime injection should stay selective.&lt;/p&gt;

&lt;p&gt;APX even caps raw project guidance when it reads &lt;code&gt;AGENTS.md&lt;/code&gt; into a prompt. The project guidance block is size-limited instead of assuming every repository rule file should enter every turn in full. That is exactly the right boundary.&lt;/p&gt;

&lt;p&gt;APC preserves the contract. APX decides how much of that contract belongs in this specific interaction.&lt;/p&gt;

&lt;p&gt;That same pattern shows up in skills.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;buildSkillsHintBlock()&lt;/code&gt; does not preload every skill body. It exposes a catalog hint with slugs and explicitly tells the runtime to load details on demand through &lt;code&gt;list_skills&lt;/code&gt; and &lt;code&gt;load_skill({slug})&lt;/code&gt;. In other words, APC can hold durable skill files, but APX does not pay the full prompt cost unless the current request needs exact syntax.&lt;/p&gt;

&lt;p&gt;That is a better use of both portability and tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why on-demand skill loading matters
&lt;/h2&gt;

&lt;p&gt;This is also why the optional skill inspector in APX is interesting.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/core/agent/skills/inspector.js&lt;/code&gt;, &lt;code&gt;inspectPromptForSkills()&lt;/code&gt; checks whether the feature is enabled, ignores prompts below a floor, refreshes stale indexes in the background, and only then tries to inject matching skill context. If the embedder does not match the saved index, it refuses to mix vector spaces and asks the operator to re-index instead.&lt;/p&gt;

&lt;p&gt;That is not accidental complexity. It is runtime discipline.&lt;/p&gt;

&lt;p&gt;The portable layer says, "These skills exist."&lt;/p&gt;

&lt;p&gt;The runtime layer says, "For this turn, only these parts are worth paying for."&lt;/p&gt;

&lt;p&gt;Without that separation, an APC-compatible project with many skills would quietly punish every request, even simple ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical takeaway
&lt;/h2&gt;

&lt;p&gt;If you are building on APC, resist the urge to equate portability with maximum injection.&lt;/p&gt;

&lt;p&gt;A good APC project should be rich enough that multiple tools can understand it. A good APX runtime should still be strict about what enters the prompt each turn.&lt;/p&gt;

&lt;p&gt;That usually means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep durable project facts in APC&lt;/li&gt;
&lt;li&gt;keep prompt assembly decisions in APX&lt;/li&gt;
&lt;li&gt;load skill bodies only when exact detail matters&lt;/li&gt;
&lt;li&gt;keep channel formatting scoped to the current surface&lt;/li&gt;
&lt;li&gt;treat prompt budget as part of runtime architecture, not as an afterthought&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the deeper reason the pair works well together.&lt;/p&gt;

&lt;p&gt;APC gives the project one portable home for context.&lt;/p&gt;

&lt;p&gt;APX makes that context usable every day by refusing to turn portability into prompt spam.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Added ACP to APX Without Adding a Second Brain</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 03 Aug 2026 13:10:05 +0000</pubDate>
      <link>https://dev.to/tecnomanu/i-added-acp-to-apx-without-adding-a-second-brain-54dl</link>
      <guid>https://dev.to/tecnomanu/i-added-acp-to-apx-without-adding-a-second-brain-54dl</guid>
      <description>&lt;h1&gt;
  
  
  I Added ACP to APX Without Adding a Second Brain
&lt;/h1&gt;

&lt;p&gt;The first time I looked at ACP support for APX, I felt the usual temptation: build a special path for the new protocol, give it its own session store, tune it for IDE behavior, and let it grow into a separate product-shaped thing.&lt;/p&gt;

&lt;p&gt;That would have been a mistake.&lt;/p&gt;

&lt;p&gt;The real lesson for me was simpler: &lt;strong&gt;ACP should be a thin adapter, not a second brain&lt;/strong&gt;. If APX already has a daemon, a super-agent, and a stream of events that describes a turn, then the ACP surface should translate that work, not re-implement it.&lt;/p&gt;

&lt;p&gt;That choice sounds small. It is not. It decides whether a new surface stays cheap to maintain or slowly becomes a fork with better branding.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ACP is doing in APX
&lt;/h2&gt;

&lt;p&gt;APX already knows how to talk to its own daemon. The ACP agent in &lt;code&gt;src/interfaces/acp/index.js&lt;/code&gt; does not start a parallel reasoning engine. It opens a JSON-RPC 2.0 stream on stdio and maps ACP session calls onto the daemon's existing chat stream.&lt;/p&gt;

&lt;p&gt;That is the important part.&lt;/p&gt;

&lt;p&gt;A client calls &lt;code&gt;session/new&lt;/code&gt;, &lt;code&gt;session/prompt&lt;/code&gt;, or &lt;code&gt;session/cancel&lt;/code&gt;. APX does the rest through the same runtime path it already uses elsewhere. The ACP layer is just a translator between one protocol and another.&lt;/p&gt;

&lt;p&gt;In practice, that means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initialize&lt;/code&gt; reports the ACP version and basic capabilities&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;authenticate&lt;/code&gt; is accepted as a no-op because daemon auth stays on the local bearer token&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;session/new&lt;/code&gt; resolves the project from the working directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;session/prompt&lt;/code&gt; streams the prompt into &lt;code&gt;/projects/:pid/super-agent/chat/stream&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;session/cancel&lt;/code&gt; aborts the active turn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is enough.&lt;/p&gt;

&lt;p&gt;The protocol surface can be rich without becoming a second implementation. That distinction matters more than it looks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I did not give ACP its own state machine
&lt;/h2&gt;

&lt;p&gt;I have built enough agent tooling now to know what happens when a surface starts storing its own truth.&lt;/p&gt;

&lt;p&gt;At first it feels convenient. The new client gets fast shortcuts. The code looks localized. You can add a field here, a cache there, maybe one special handler for the IDE case.&lt;/p&gt;

&lt;p&gt;Then the drift begins.&lt;/p&gt;

&lt;p&gt;One session store says the prompt happened.&lt;br&gt;
Another store says it did not.&lt;br&gt;
One adapter thinks cancellation means one thing.&lt;br&gt;
Another adapter thinks it means something slightly different.&lt;br&gt;
By the time you notice, the system is no longer one system.&lt;/p&gt;

&lt;p&gt;So I kept ACP session state minimal. The adapter keeps just enough in memory to make the connection work: session id, conversation history, active turn, and a few counters for updates. No daemon-side ACP session database. No duplicate agent brain. No second source of truth.&lt;/p&gt;

&lt;p&gt;That is boring. It is also easier to reason about.&lt;/p&gt;

&lt;p&gt;The daemon already owns the real work. ACP should not compete with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stream is the contract
&lt;/h2&gt;

&lt;p&gt;The cleanest thing about this design is that ACP listens to the daemon's stream instead of inventing its own event language.&lt;/p&gt;

&lt;p&gt;The mapping is plain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;assistant_text&lt;/code&gt; becomes &lt;code&gt;agent_message_chunk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tool_start&lt;/code&gt; becomes &lt;code&gt;tool_call&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tool_result&lt;/code&gt; becomes &lt;code&gt;tool_call_update&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confirmation_required&lt;/code&gt; becomes an ACP permission round-trip&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;final&lt;/code&gt; becomes the session response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That one-to-one mapping matters because it keeps the adapter honest.&lt;/p&gt;

&lt;p&gt;If the daemon says a tool started, ACP does not re-label it into something fancier. If the daemon ends with a final result, ACP does not hide it behind another layer of interpretation. The client sees the same work, only wrapped in ACP wire shapes.&lt;/p&gt;

&lt;p&gt;I like that because it preserves debugging power. When something goes wrong, I can trace it through the same stream APX already uses. I do not need to ask whether ACP invented a separate failure mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why history stays in the client connection
&lt;/h2&gt;

&lt;p&gt;One subtle choice in the ACP code is that conversation history stays per connection, in memory.&lt;/p&gt;

&lt;p&gt;That might sound like a compromise. For this surface, it is the right one.&lt;/p&gt;

&lt;p&gt;The history exists so the ACP session can feed &lt;code&gt;previousMessages&lt;/code&gt; on the next turn. That lets a client keep context without forcing the daemon to become a session database for every external protocol that touches it.&lt;/p&gt;

&lt;p&gt;It also keeps the adapter narrow. The daemon still owns the real runtime. The ACP client owns its own conversation continuity. APX just bridges the turn.&lt;/p&gt;

&lt;p&gt;That split is useful because ACP clients are not all the same. Some are IDEs. Some are editors. Some are automation surfaces. I do not want APX to guess their long-term memory model for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real reason I wanted ACP at all
&lt;/h2&gt;

&lt;p&gt;I did not add ACP because I wanted another badge on the README.&lt;/p&gt;

&lt;p&gt;I added it because I want APX to reach more surfaces without changing its core shape.&lt;/p&gt;

&lt;p&gt;The CLI is still the CLI.&lt;br&gt;
The daemon is still the daemon.&lt;br&gt;
The web admin is still a local window onto the same runtime.&lt;br&gt;
ACP just lets other clients drive the same super-agent in a language they already speak.&lt;/p&gt;

&lt;p&gt;That is the whole point of APC for me: one project context, many compatible tools. If APX is going to be the runtime layer for that idea, then protocol adapters should be cheap, local, and replaceable.&lt;/p&gt;

&lt;p&gt;A thin ACP bridge gives me that.&lt;/p&gt;

&lt;p&gt;A second brain would not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this changed in my thinking
&lt;/h2&gt;

&lt;p&gt;This work changed how I judge new surfaces.&lt;/p&gt;

&lt;p&gt;Now I ask a few blunt questions before I add anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this surface need its own state, or can it reuse the daemon?&lt;/li&gt;
&lt;li&gt;Is this a translation layer, or am I sneaking in a fork?&lt;/li&gt;
&lt;li&gt;Can I map events one-to-one, or am I inventing new semantics just because I can?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the honest answer starts drifting toward "new brain," I stop and simplify.&lt;/p&gt;

&lt;p&gt;That is not purity for its own sake. It is maintenance math.&lt;/p&gt;

&lt;p&gt;Every extra brain creates another place where bugs can hide. Every thin adapter keeps the system closer to the contract I already trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule I kept
&lt;/h2&gt;

&lt;p&gt;My rule for ACP ended up very close to the rule I keep for APC itself: preserve the contract, do not duplicate the contract.&lt;/p&gt;

&lt;p&gt;APC says the project context should stay portable.&lt;br&gt;
APX says the runtime should stay local.&lt;br&gt;
ACP fits only if it stays a bridge between those ideas and another client, not a new center of gravity.&lt;/p&gt;

&lt;p&gt;So I kept it thin.&lt;/p&gt;

&lt;p&gt;That made the code easier to read.&lt;br&gt;
It made cancellation simpler.&lt;br&gt;
It made debugging less theatrical.&lt;br&gt;
And it kept APX from growing the one thing I did not want to maintain: a second brain pretending to be just another adapter.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>APC Migration Should Classify Context, Not Copy Folders</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 03 Aug 2026 12:04:37 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/apc-migration-should-classify-context-not-copy-folders-2m9i</link>
      <guid>https://dev.to/agentprojectcontext/apc-migration-should-classify-context-not-copy-folders-2m9i</guid>
      <description>&lt;h1&gt;
  
  
  APC Migration Should Classify Context, Not Copy Folders
&lt;/h1&gt;

&lt;p&gt;A good APC migration is not a file move. It is a classification pass.&lt;/p&gt;

&lt;p&gt;That distinction matters because most existing agent folders mix four different things: project rules, agent definitions, runtime state, and private configuration. If you copy all of that into &lt;code&gt;.apc/&lt;/code&gt;, you do not get a portable project contract. You get a portable mess.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It answers one narrow question: what should a compatible agent know when it enters this repository? APX is the daily-use runtime and tooling layer. It reads that contract, installs APC-aware behavior into current tools, and keeps operational state local.&lt;/p&gt;

&lt;p&gt;So when you migrate a project to APC, the job is not "copy &lt;code&gt;.claude/&lt;/code&gt; into &lt;code&gt;.apc/&lt;/code&gt;" or "sync every tool folder into one neutral folder." The job is to separate durable project meaning from runtime residue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should move into APC
&lt;/h2&gt;

&lt;p&gt;The APC side should contain information that stays useful across tools and across sessions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; as the root compatibility and discovery contract&lt;/li&gt;
&lt;li&gt;structured agent definitions under &lt;code&gt;.apc/agents/&amp;lt;slug&amp;gt;.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;reusable instruction blocks under &lt;code&gt;.apc/skills/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;curated project memory in &lt;code&gt;.apc/agents/&amp;lt;slug&amp;gt;/memory.md&lt;/code&gt; only when it is safe for the whole team&lt;/li&gt;
&lt;li&gt;MCP hints in &lt;code&gt;.apc/mcps.json&lt;/code&gt; without embedded secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the material another tool can read tomorrow and still understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should stay out
&lt;/h2&gt;

&lt;p&gt;The tempting mistake is to migrate everything that looks agent-related. That is exactly what APC tries to prevent.&lt;/p&gt;

&lt;p&gt;Raw sessions, transcripts, conversations, message logs, tool traces, caches, and pasted credentials do not belong in &lt;code&gt;.apc/&lt;/code&gt;. They are runtime-owned state. They are often private, noisy, or too temporary to commit.&lt;/p&gt;

&lt;p&gt;That is where APX becomes useful. APX keeps runtime state under &lt;code&gt;~/.apx/projects/&amp;lt;project-id&amp;gt;/&lt;/code&gt; and leaves the repository for durable context only. In other words, APC gives the project a clean contract; APX gives that contract an operational home without pushing local runtime data back into git.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical migration test
&lt;/h2&gt;

&lt;p&gt;When you find a file during migration, ask one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will this still help a different compatible tool, on a different machine, in a later session?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is yes, it probably belongs in APC after curation.&lt;/p&gt;

&lt;p&gt;If the answer is no because it is private, local, ephemeral, or just the full history of one run, keep it out of APC.&lt;/p&gt;

&lt;p&gt;That usually leads to a simple split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep repository-wide rules and stable agent summaries in &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;move structured role detail into &lt;code&gt;.apc/agents/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;move reusable prompts or workflows into &lt;code&gt;.apc/skills/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;extract only durable facts into &lt;code&gt;memory.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;leave raw runtime artifacts where the runtime owns them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this makes APX better too
&lt;/h2&gt;

&lt;p&gt;APX works better when APC stays clean.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;.apc/&lt;/code&gt; contains only durable project meaning, APX can safely teach Codex, Claude Code, and other tools to treat that directory as the context source. It does not need to guess which files are safe to project, commit, review, or share. It can read the project contract from the repo and keep sessions, messages, and machine-local preferences outside it.&lt;/p&gt;

&lt;p&gt;That boundary is the whole point of the pair:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APC makes context portable&lt;/li&gt;
&lt;li&gt;APX makes that portable context usable today&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Migration succeeds when that boundary gets sharper, not blurrier.&lt;/p&gt;

&lt;p&gt;So the next time you convert an agent project, do not ask, "Which folders should I copy?" Ask, "Which facts belong to the project, and which ones belong to the runtime?"&lt;/p&gt;

&lt;p&gt;That is the difference between a neutral contract and another vendor-shaped dump.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Portable Context Does Not Mean Portable Runtimes</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sun, 02 Aug 2026 12:02:11 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/portable-context-does-not-mean-portable-runtimes-15pa</link>
      <guid>https://dev.to/agentprojectcontext/portable-context-does-not-mean-portable-runtimes-15pa</guid>
      <description>&lt;h1&gt;
  
  
  Portable Context Does Not Mean Portable Runtimes
&lt;/h1&gt;

&lt;p&gt;A portable agent project should not pretend every machine can run the same AI CLI.&lt;/p&gt;

&lt;p&gt;That is the distinction APC and APX get right when used together.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps the project contract in the repository: &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/agents&lt;/code&gt;, &lt;code&gt;.apc/project.json&lt;/code&gt;, skills, commands, and MCP hints. Clone the repo somewhere else and that meaning can travel with it.&lt;/p&gt;

&lt;p&gt;APX is the daily-use runtime and tooling layer. It makes that context runnable through a local daemon, CLI, web admin, and bridges to external coding CLIs such as Claude Code, Codex, OpenCode, Aider, Cursor Agent, Gemini CLI, and Qwen Code.&lt;/p&gt;

&lt;p&gt;But those runtimes are not part of APC.&lt;/p&gt;

&lt;p&gt;That matters because a repo can be portable while the machine is not.&lt;/p&gt;

&lt;p&gt;One laptop may have &lt;code&gt;codex&lt;/code&gt; and &lt;code&gt;claude&lt;/code&gt; installed. Another may only have &lt;code&gt;gemini&lt;/code&gt; and &lt;code&gt;ollama&lt;/code&gt;. A CI runner may have none of them. If a system treats runtime availability as if it were durable project context, it starts lying. The repo says one thing, the host can do another, and now every handoff becomes fragile.&lt;/p&gt;

&lt;p&gt;APX avoids that by making runtime detection a local operation.&lt;/p&gt;

&lt;p&gt;The APX runtime docs are explicit: before picking a runtime, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apx &lt;span class="nb"&gt;env &lt;/span&gt;detect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command reports which runtime CLIs, engines, and tools are actually available on the current machine. In other words, APC defines the project, but APX checks the ground truth before execution.&lt;/p&gt;

&lt;p&gt;That is a better boundary than storing runtime assumptions in the repo.&lt;/p&gt;

&lt;p&gt;A practical flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apx &lt;span class="nb"&gt;env &lt;/span&gt;detect
apx run reviewer &lt;span class="nt"&gt;--runtime&lt;/span&gt; codex &lt;span class="s2"&gt;"Review the diff in src/ for regressions"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;codex&lt;/code&gt; is installed, APX can spawn it. If it is not installed, the runtime is missing on that host, regardless of how cleanly the APC files travel.&lt;/p&gt;

&lt;p&gt;This is also why APX separates &lt;code&gt;apx run&lt;/code&gt; from &lt;code&gt;apx exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apx run&lt;/code&gt; delegates to an external runtime binary. APX builds the system prompt, spawns the CLI, captures the output, and stores a session record. The external tool performs the actual model interaction and shell work.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apx exec&lt;/code&gt;, by contrast, stays inside APX and calls a configured engine directly. Different path, different dependency surface, same APC project context.&lt;/p&gt;

&lt;p&gt;That split is useful because it keeps portability honest.&lt;/p&gt;

&lt;p&gt;You can move the same APC project between machines without editing the repository. Then APX can answer a local question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which runtimes are installed here?&lt;/li&gt;
&lt;li&gt;which engines are configured here?&lt;/li&gt;
&lt;li&gt;which toolchain is available here right now?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are runtime questions, not project-contract questions.&lt;/p&gt;

&lt;p&gt;The APX introduction docs make the broader design even clearer: the filesystem is the source of truth for durable project meaning, while sessions, conversations, messages, caches, and other runtime state live under &lt;code&gt;~/.apx/&lt;/code&gt; and never belong in the repo. Runtime availability follows that same philosophy. Installed binaries and local engine setup are machine facts.&lt;/p&gt;

&lt;p&gt;So the practical rule is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APC should describe the project in a way that can survive clone, review, and handoff.&lt;/li&gt;
&lt;li&gt;APX should discover what the current machine can actually execute.&lt;/li&gt;
&lt;li&gt;The repo should not pretend local runtime binaries are portable artifacts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes APC more trustworthy, not less. The project contract stays small and durable. APX handles the messy part: local capability, runtime invocation, and session tracking.&lt;/p&gt;

&lt;p&gt;Portable context is valuable because it avoids vendor lock-in and repeated setup. But portability only works when it stops at the right boundary.&lt;/p&gt;

&lt;p&gt;The project can travel.&lt;/p&gt;

&lt;p&gt;The runtime must still be checked.&lt;/p&gt;

&lt;p&gt;That is why &lt;code&gt;apx env detect&lt;/code&gt; is not a convenience feature. It is the operational guardrail that keeps APC portable and APX honest.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Structured Agent Files Should Own Detail. `AGENTS.md` Should Stay Portable.</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sat, 01 Aug 2026 12:03:00 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/structured-agent-files-should-own-detail-agentsmd-should-stay-portable-4el9</link>
      <guid>https://dev.to/agentprojectcontext/structured-agent-files-should-own-detail-agentsmd-should-stay-portable-4el9</guid>
      <description>&lt;h1&gt;
  
  
  Structured Agent Files Should Own Detail. &lt;code&gt;AGENTS.md&lt;/code&gt; Should Stay Portable.
&lt;/h1&gt;

&lt;p&gt;APC works best when it does two jobs at once without mixing them.&lt;/p&gt;

&lt;p&gt;First job: give every tool one obvious project entrypoint. That is &lt;code&gt;AGENTS.md&lt;/code&gt; at the repo root.&lt;/p&gt;

&lt;p&gt;Second job: give APC-aware tools a cleaner place for structured detail. That is &lt;code&gt;.apc/agents/&amp;lt;slug&amp;gt;.md&lt;/code&gt; next to &lt;code&gt;.apc/project.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That split matters because compatibility and structure are not the same problem.&lt;/p&gt;

&lt;p&gt;In the APC companion spec for &lt;code&gt;AGENTS.md&lt;/code&gt;, the root file is defined as the compatibility-facing contract for agent discovery. It lives at the project root, next to &lt;code&gt;.apc/&lt;/code&gt;, and many tools already know how to find and read it. The same spec also says that when &lt;code&gt;.apc/agents/&amp;lt;slug&amp;gt;.md&lt;/code&gt; exists for the same slug, that structured file should be treated as the authoritative structured definition.&lt;/p&gt;

&lt;p&gt;That is the right boundary.&lt;/p&gt;

&lt;p&gt;If you try to put every detail into &lt;code&gt;AGENTS.md&lt;/code&gt;, the root contract becomes noisy. Long descriptions, custom fields, memory overrides, skill lists, and formatting edge cases all end up in the one file every runtime has to scan first. Portable discovery gets harder exactly because the “simple entrypoint” started acting like a database.&lt;/p&gt;

&lt;p&gt;If you go the other way and drop &lt;code&gt;AGENTS.md&lt;/code&gt; entirely, portability gets worse. A lot of tools can walk up a repo and look for one familiar root file. Fewer tools know your internal structured layout on day one.&lt;/p&gt;

&lt;p&gt;APC avoids that tradeoff by keeping both layers.&lt;/p&gt;

&lt;p&gt;A small root contract can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Agents&lt;/span&gt;

&lt;span class="gu"&gt;## reviewer&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Role**&lt;/span&gt;: Code review
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Model**&lt;/span&gt;: gpt-5
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Skills**&lt;/span&gt;: documentation
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Description**&lt;/span&gt;: Reviews risks, tests, and regressions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is enough for discovery, routing, and a first-pass understanding of the project.&lt;/p&gt;

&lt;p&gt;Then the richer definition can live where APC-aware tooling expects it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.apc/
  project.json
  agents/
    reviewer.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also matches how APX uses the project.&lt;/p&gt;

&lt;p&gt;APX reads &lt;code&gt;AGENTS.md&lt;/code&gt; as project guidance at runtime. In &lt;code&gt;buildProjectAgentsBlock&lt;/code&gt;, it loads the root file, truncates it if needed, and injects it into the prompt as “Project guidance (AGENTS.md)”. That is a strong hint about intended size and purpose: useful startup rules, not an ever-growing dump of agent internals.&lt;/p&gt;

&lt;p&gt;APX also has a dedicated parser for &lt;code&gt;AGENTS.md&lt;/code&gt; sections. It looks for one &lt;code&gt;# Agents&lt;/code&gt; heading, reads each &lt;code&gt;## &amp;lt;slug&amp;gt;&lt;/code&gt; block, and extracts bullet fields like &lt;code&gt;Role&lt;/code&gt;, &lt;code&gt;Model&lt;/code&gt;, &lt;code&gt;Skills&lt;/code&gt;, and &lt;code&gt;Description&lt;/code&gt;. That parser exists because the root contract needs to stay predictable and portable.&lt;/p&gt;

&lt;p&gt;So the practical rule is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put cross-tool discovery in &lt;code&gt;AGENTS.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put structured per-agent detail in &lt;code&gt;.apc/agents/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Keep runtime sessions, conversations, and private state out of both; APX stores those under &lt;code&gt;~/.apx/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gives APC a durable portable layer and gives APX a clean daily-use runtime layer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; stays readable by humans and broadly compatible tools. &lt;code&gt;.apc/agents&lt;/code&gt; stays available for richer APC-native structure. APX can then bridge both without turning either one into the wrong kind of storage.&lt;/p&gt;

&lt;p&gt;Portable projects usually fail from overloading the first file everybody touches. APC gets farther by keeping the index small and the detail where structure belongs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Unknown Telegram Senders Should Stay Guests in APX</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Fri, 31 Jul 2026 12:04:21 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/unknown-telegram-senders-should-stay-guests-in-apx-4lkl</link>
      <guid>https://dev.to/agentprojectcontext/unknown-telegram-senders-should-stay-guests-in-apx-4lkl</guid>
      <description>&lt;h1&gt;
  
  
  Unknown Telegram Senders Should Stay Guests in APX
&lt;/h1&gt;

&lt;p&gt;A Telegram bot should not treat every new message as trusted operator input.&lt;/p&gt;

&lt;p&gt;That sounds obvious, but a lot of agent setups still blur identity, chat membership, and tool access. Someone writes to a bot, the bot answers, and before long the same person can trigger real actions because the runtime never drew a hard line between &lt;strong&gt;conversation&lt;/strong&gt; and &lt;strong&gt;capability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;APX draws that line on purpose.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps the project contract in the repo: &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent definitions, skills, commands, and MCP hints. APX is the daily-use runtime and tooling layer. It reads that project context, runs the agent loop, and handles runtime state such as sessions, messages, approvals, and channel identity outside the repository.&lt;/p&gt;

&lt;p&gt;That trust decision belongs to APX, not APC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guest first, tools later
&lt;/h2&gt;

&lt;p&gt;The APX Telegram identity logic is explicit.&lt;/p&gt;

&lt;p&gt;A contact is keyed by the sender's stable Telegram &lt;code&gt;user_id&lt;/code&gt;, not by &lt;code&gt;chat_id&lt;/code&gt;. That matters because the same person may appear across different chats, while group chats can contain many people. APX stores the person globally and only uses &lt;code&gt;owner_user_id&lt;/code&gt; to mark who owns one specific channel.&lt;/p&gt;

&lt;p&gt;Then it applies a simple rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;channel owner gets &lt;code&gt;owner&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;configured contacts can get a custom role&lt;/li&gt;
&lt;li&gt;unknown senders become &lt;code&gt;guest&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last step is the important one.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;resolveAllowedTools()&lt;/code&gt;, APX gives the owner &lt;code&gt;"*"&lt;/code&gt;, reads tool allowlists from &lt;code&gt;telegram.roles&lt;/code&gt; for known roles, and otherwise returns an empty list. In other words, guests fail closed. They can talk to the bot, but they do not get tool power just because they found the chat.&lt;/p&gt;

&lt;p&gt;That is a better default than optimistic trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this split matters
&lt;/h2&gt;

&lt;p&gt;A Telegram conversation has two separate questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;who is this person?&lt;/li&gt;
&lt;li&gt;what may this person trigger?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a runtime collapses those into one step, it tends to over-grant. "Known enough to answer" quietly becomes "known enough to act."&lt;/p&gt;

&lt;p&gt;APX does not do that.&lt;/p&gt;

&lt;p&gt;The relationship block that feeds the model prompt is also strict. For a guest sender, APX tells the model it is talking to a guest with no permissions and instructs it to ask politely who they are. That keeps the social flow natural without pretending the model can grant access on its own.&lt;/p&gt;

&lt;p&gt;So there are really three layers working together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;runtime identity resolution&lt;/li&gt;
&lt;li&gt;prompt context about that identity&lt;/li&gt;
&lt;li&gt;tool allowlist enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That combination is what makes the behavior safe instead of merely friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small example
&lt;/h2&gt;

&lt;p&gt;Imagine a fresh project bot pinned to one APX project.&lt;/p&gt;

&lt;p&gt;The first private message on an owner-less channel can claim ownership. After that, another sender writing to the same bot is not promoted just because the conversation is private. APX records that person as a guest.&lt;/p&gt;

&lt;p&gt;If you later want that contact to do more, you assign a role in APX config or through the web admin, where each role maps to a concrete tool list such as &lt;code&gt;call_agent&lt;/code&gt; or &lt;code&gt;list_tasks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means the trust upgrade is deliberate and reviewable.&lt;/p&gt;

&lt;p&gt;Notably, APX does &lt;strong&gt;not&lt;/strong&gt; grant power because a username looks familiar, because a user joined the chat, or because the model decided the person "seems legit." The runtime owns the permission boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APC should stay out of it
&lt;/h2&gt;

&lt;p&gt;This is not durable project context. It is live runtime policy.&lt;/p&gt;

&lt;p&gt;APC should describe the project, its agents, its skills, and other repo-owned context that can travel across machines and runtimes. It should not commit transient channel trust or personal messaging access into the project contract.&lt;/p&gt;

&lt;p&gt;Telegram roles, ownership claims, and sender registration depend on who is operating the bot right now. That is machine-local, runtime-managed state. APX is the right home for it.&lt;/p&gt;

&lt;p&gt;This boundary is easy to miss, but it matters.&lt;/p&gt;

&lt;p&gt;If APC stored this kind of messaging trust directly, portability would get worse and accidental exposure would get easier. By keeping APC portable and APX responsible for channel identity, the project contract stays clean while the runtime stays cautious.&lt;/p&gt;

&lt;p&gt;That is the real design point: APC says what the project means. APX decides who, through Telegram, gets to do anything with it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>APX Keeps One Core So APC Can Reach Every Surface</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Thu, 30 Jul 2026 12:04:50 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/apx-keeps-one-core-so-apc-can-reach-every-surface-15en</link>
      <guid>https://dev.to/agentprojectcontext/apx-keeps-one-core-so-apc-can-reach-every-surface-15en</guid>
      <description>&lt;h1&gt;
  
  
  APX Keeps One Core So APC Can Reach Every Surface
&lt;/h1&gt;

&lt;p&gt;A lot of agent tools quietly split into separate products.&lt;/p&gt;

&lt;p&gt;The CLI has one behavior. The web panel grows another. Telegram gets a simplified bot loop. Voice gets its own prompt stack. A desktop helper starts reimplementing the same decisions again.&lt;/p&gt;

&lt;p&gt;That architecture looks fast at first, but it usually creates drift.&lt;/p&gt;

&lt;p&gt;APC and APX avoid that split on purpose.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps the durable project contract in the repository: &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent files, skills, commands, and MCP hints. APX is the daily-use runtime and tooling layer. It reads that context, runs the agent loop, and exposes it through surfaces like CLI, web, desktop, routines, and Telegram.&lt;/p&gt;

&lt;p&gt;The key detail is this: APX tries to keep &lt;strong&gt;one core agent loop&lt;/strong&gt; instead of building a different brain for every surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;The APX architecture decision record is explicit about the split: &lt;code&gt;src/core/&lt;/code&gt; holds shared logic, &lt;code&gt;src/host/&lt;/code&gt; holds long-running daemon processes, and &lt;code&gt;src/interfaces/&lt;/code&gt; holds user-facing surfaces.&lt;/p&gt;

&lt;p&gt;That is not just folder cleanup.&lt;/p&gt;

&lt;p&gt;It means the important behavior lives once.&lt;/p&gt;

&lt;p&gt;The prompt builder, model routing, tool loop, memory broker, lazy tool activation, and judge loop belong in &lt;code&gt;core/&lt;/code&gt;. The daemon adapts that logic to HTTP, plugins, and runtime processes. CLI, web, desktop, and other interfaces stay thin.&lt;/p&gt;

&lt;p&gt;That design protects APC too.&lt;/p&gt;

&lt;p&gt;If every surface started inventing its own prompt rules and its own reading of project context, APC would stop being a portable contract and become a vague suggestion interpreted differently by each entry point. A portable context layer only works when the runtime keeps interpretation consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concrete example from APX
&lt;/h2&gt;

&lt;p&gt;In APX, &lt;code&gt;runSuperAgent()&lt;/code&gt; lives in &lt;code&gt;src/core/agent/super-agent.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That single function assembles relevant memory, active thread context, lazy tool state, model routing, confirmation handling, and the optional judge loop before calling the shared agent runner.&lt;/p&gt;

&lt;p&gt;Then multiple surfaces call into that same logic.&lt;/p&gt;

&lt;p&gt;The code graph shows inbound calls from the daemon API, desktop plugin flow, Telegram reply path, routines, code mode, and subagent execution. That is exactly the point: different surfaces, same core behavior.&lt;/p&gt;

&lt;p&gt;The system prompt assembly follows the same rule. &lt;code&gt;buildSuperAgentSystem()&lt;/code&gt; in &lt;code&gt;src/core/agent/prompt-builder.js&lt;/code&gt; layers identity, memory, channel context, project index, project agent context, skills, and voice-mode rules into one composed system prompt. The surface can pass channel metadata, but it does not fork the whole prompt model.&lt;/p&gt;

&lt;p&gt;So when APC project context changes, APX does not need five separate implementations to catch up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What thin surfaces buy you
&lt;/h2&gt;

&lt;p&gt;This approach has three practical benefits.&lt;/p&gt;

&lt;p&gt;First, behavior stays aligned. If the core agent loop learns a new safety rule or memory rule, web and Telegram do not lag behind the CLI.&lt;/p&gt;

&lt;p&gt;Second, new surfaces get cheaper. Adding a desktop voice shell or browser admin is mostly adapter work if the core already knows how to read APC context, route models, and run tools.&lt;/p&gt;

&lt;p&gt;Third, bugs become easier to reason about. When one surface behaves strangely, you can ask whether the problem is in the shared core or only in the adapter. That is much clearer than debugging five near-copies of the same runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APC depends on this discipline
&lt;/h2&gt;

&lt;p&gt;APC should stay small, portable, and repo-owned. It should define what the project means, not how every transport invents its own execution semantics.&lt;/p&gt;

&lt;p&gt;APX is where execution semantics belong.&lt;/p&gt;

&lt;p&gt;But if APX let each surface grow a separate runtime brain, the result would still damage portability. The same &lt;code&gt;AGENTS.md&lt;/code&gt; and &lt;code&gt;.apc/&lt;/code&gt; files would lead to different agent behavior depending on whether you came in through CLI, desktop, web, or Telegram.&lt;/p&gt;

&lt;p&gt;That would make APC weaker, even if APC itself stayed clean on disk.&lt;/p&gt;

&lt;p&gt;So the real win is not only that APX has many interfaces. The win is that those interfaces stay thin enough to share one interpretation layer.&lt;/p&gt;

&lt;p&gt;APC carries the project contract.&lt;br&gt;
APX carries the execution machinery.&lt;br&gt;
Keeping one core inside APX is what lets that contract survive contact with daily use.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Security Risk Grades Are Not Permission Modes in APX</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Thu, 30 Jul 2026 11:29:16 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/security-risk-grades-are-not-permission-modes-in-apx-m0f</link>
      <guid>https://dev.to/agentprojectcontext/security-risk-grades-are-not-permission-modes-in-apx-m0f</guid>
      <description>&lt;h1&gt;
  
  
  Security Risk Grades Are Not Permission Modes in APX
&lt;/h1&gt;

&lt;p&gt;A permission toggle answers one question: &lt;strong&gt;may this tool run?&lt;/strong&gt; It does not answer a second one that matters just as much: &lt;strong&gt;how dangerous is this exact action right now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is why APX keeps &lt;strong&gt;permission mode&lt;/strong&gt; and &lt;strong&gt;security-risk grading&lt;/strong&gt; as two separate runtime controls.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It gives the project one neutral contract in the repo: &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent files, MCP hints, skills, and other durable context. APX is the daily-use runtime and tooling layer. It reads that contract, runs the agent loop, and keeps runtime decisions like approvals, sessions, and message logs outside the repository.&lt;/p&gt;

&lt;p&gt;This topic belongs on the APX side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two gates, two different jobs
&lt;/h2&gt;

&lt;p&gt;APX supports three permission modes for the super-agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;total&lt;/code&gt;: run tools without confirmation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;automatico&lt;/code&gt;: APX decides automatically&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permiso&lt;/code&gt;: only allow-listed tools run directly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gate is about &lt;strong&gt;tool identity&lt;/strong&gt;. A shell tool, file editor, Telegram sender, or MCP call can have a default trust policy before the model even decides what to do.&lt;/p&gt;

&lt;p&gt;APX also has an optional &lt;code&gt;security_risk&lt;/code&gt; layer. When enabled, APX injects a required &lt;code&gt;security_risk&lt;/code&gt; field into each eligible tool schema, and the model must grade the action as &lt;code&gt;LOW&lt;/code&gt;, &lt;code&gt;MEDIUM&lt;/code&gt;, or &lt;code&gt;HIGH&lt;/code&gt; as part of the tool call itself. No second model pass. No separate risk service.&lt;/p&gt;

&lt;p&gt;That gate is about &lt;strong&gt;action severity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those are not the same thing.&lt;/p&gt;

&lt;p&gt;A tool like &lt;code&gt;run_shell&lt;/code&gt; might be harmless for &lt;code&gt;ls src&lt;/code&gt; and dangerous for &lt;code&gt;rm -rf build&lt;/code&gt;. A send tool might be fine for an internal note and risky for an outward message to a real user. Static permission mode cannot see that difference by itself. The risk grade can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this split matters
&lt;/h2&gt;

&lt;p&gt;If you collapse both ideas into one setting, you get a bad tradeoff.&lt;/p&gt;

&lt;p&gt;If the system is too strict, the agent asks for approval on every non-trivial step and stops being useful. If the system is too loose, one trusted tool can do a much riskier action than the user expected.&lt;/p&gt;

&lt;p&gt;APX avoids that by keeping both layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;permission mode decides the baseline policy for a tool&lt;/li&gt;
&lt;li&gt;security-risk grading decides whether &lt;strong&gt;this call&lt;/strong&gt; should stop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most interesting case is &lt;code&gt;total&lt;/code&gt; mode. In APX, the risk gate still acts as a &lt;strong&gt;safety floor&lt;/strong&gt;. Low-friction work runs freely, but a &lt;code&gt;HIGH&lt;/code&gt;-graded action can still require confirmation. That is a better model than all-or-nothing trust, because "I trust this agent" should not mean "I want zero brakes on catastrophic actions."&lt;/p&gt;

&lt;h2&gt;
  
  
  Small example
&lt;/h2&gt;

&lt;p&gt;Imagine the same project agent, the same runtime, and the same shell tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apx permission &lt;span class="nb"&gt;set &lt;/span&gt;total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now compare two actions the model could take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;grep -R TODO src/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm -rf ./tmp/generated-cache&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Permission mode alone sees one tool: shell.&lt;br&gt;
Risk grading sees two different severities.&lt;/p&gt;

&lt;p&gt;That distinction lets APX stay fast on ordinary work without pretending every shell call carries the same blast radius.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APC should not own this
&lt;/h2&gt;

&lt;p&gt;This is exactly the kind of state APC should &lt;strong&gt;not&lt;/strong&gt; carry.&lt;/p&gt;

&lt;p&gt;APC should travel cleanly between repos, machines, and runtimes. A committed project contract should not silently force the same approval behavior everywhere. Approval thresholds, confirmation surfaces, and action gating are runtime policy. They depend on who is running the work, where, and under what level of trust.&lt;/p&gt;

&lt;p&gt;So the repo keeps the durable project context. APX keeps the live control plane.&lt;/p&gt;

&lt;p&gt;That split is the real point: APC tells the runtime what the project is. APX decides how safely that runtime can act today.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Docs Are Part of the Contract in APC and APX</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Thu, 30 Jul 2026 11:28:18 +0000</pubDate>
      <link>https://dev.to/tecnomanu/docs-are-part-of-the-contract-in-apc-and-apx-ebl</link>
      <guid>https://dev.to/tecnomanu/docs-are-part-of-the-contract-in-apc-and-apx-ebl</guid>
      <description>&lt;h1&gt;
  
  
  Docs Are Part of the Contract in APC and APX
&lt;/h1&gt;

&lt;p&gt;I used to treat docs like cleanup.&lt;/p&gt;

&lt;p&gt;Code first. Fix behavior. Then, if time remained, explain what changed.&lt;/p&gt;

&lt;p&gt;That habit works fine until a project gets enough surface area that the docs start acting like a second implementation. At that point, stale prose is not harmless. It is a bug with better grammar.&lt;/p&gt;

&lt;p&gt;APC and APX pushed me into a different rule: &lt;strong&gt;docs are part of the contract&lt;/strong&gt;. Not marketing. Not an afterthought. Contract.&lt;/p&gt;

&lt;p&gt;That sounds obvious until you try to keep a real project honest across multiple surfaces. APC has its spec, its repo-owned context, and its compatibility layer. APX has the runtime, the CLI, the daemon, the web admin, and local state under &lt;code&gt;~/.apx/&lt;/code&gt;. The moment I let one surface drift from another, people and agents start learning two truths about the same system.&lt;/p&gt;

&lt;p&gt;That is the wrong kind of flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I stopped seeing docs as separate work
&lt;/h2&gt;

&lt;p&gt;The turning point was simple: I noticed that every time I let docs lag behind code, I was forcing future me to re-derive the same answer twice.&lt;/p&gt;

&lt;p&gt;Once from the implementation.&lt;br&gt;
Once from the text.&lt;/p&gt;

&lt;p&gt;That is wasteful on a small repo and expensive on a growing one.&lt;/p&gt;

&lt;p&gt;For APC/APX, the cost is worse because the audience is not just humans. Agents read these files too. If the README says one thing and the code does another, the model is not "being clever." It is being misled by my own stale contract.&lt;/p&gt;

&lt;p&gt;So I changed the default.&lt;/p&gt;

&lt;p&gt;If a change alters user-facing behavior, I update the docs in the same pass. If a page explains a workflow, I treat that page like code that can regress. If a command exists in the README, I expect the command to work. If an article says a file lives in &lt;code&gt;.apc/&lt;/code&gt;, it should not actually live somewhere else.&lt;/p&gt;

&lt;p&gt;That rule sounds strict. It is. It also saves time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mirrored-tree rule forced the issue
&lt;/h2&gt;

&lt;p&gt;One of the clearest examples is APC's documentation structure.&lt;/p&gt;

&lt;p&gt;The APX project rules require mirrored locale trees: &lt;code&gt;src/pages/en/&lt;/code&gt; and &lt;code&gt;src/pages/es/&lt;/code&gt; must stay structurally identical and semantically equivalent. Same page, same shape, same keys in &lt;code&gt;_meta.js&lt;/code&gt;, locale-matched internal links.&lt;/p&gt;

&lt;p&gt;That is not extra ceremony. It is a built-in drift detector.&lt;/p&gt;

&lt;p&gt;If I add a page in English and forget the Spanish version, the build should complain. If I rename a section in one locale and leave the other behind, that mismatch is not a translation issue only. It is a contract break.&lt;/p&gt;

&lt;p&gt;This changed how I think about documentation work.&lt;/p&gt;

&lt;p&gt;Before, I thought of translation as a late-stage pass.&lt;br&gt;
Now, I think of mirrored docs as a design constraint.&lt;/p&gt;

&lt;p&gt;The constraint is useful because it makes the system honest. I cannot accidentally say, "the docs are updated," when only one audience got the change. I have to keep both views aligned, which is exactly what a project that talks to tools should demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build output is not just packaging
&lt;/h2&gt;

&lt;p&gt;I also stopped treating the build as a deployment chore.&lt;/p&gt;

&lt;p&gt;A build is where drift gets caught early.&lt;/p&gt;

&lt;p&gt;For APC, the rule is explicit: run &lt;code&gt;npm run build&lt;/code&gt; before calling a docs task done. For APX docs, the same idea appears in a different shape: build the docs site and verify both locale trees render. That is not overhead. That is verification that the contract still compiles.&lt;/p&gt;

&lt;p&gt;I like that framing because it keeps docs in the same mental bucket as code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;source changes happen in the repo&lt;/li&gt;
&lt;li&gt;projections are rendered from that source&lt;/li&gt;
&lt;li&gt;the build checks whether the projection still matches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the same logic I use elsewhere in the project.&lt;/p&gt;

&lt;p&gt;APC is the repo-owned contract.&lt;br&gt;
APX is the runtime that consumes it.&lt;br&gt;
The rendered docs site is another projection.&lt;/p&gt;

&lt;p&gt;If any projection starts inventing its own truth, the system gets harder to trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real bug is not stale prose
&lt;/h2&gt;

&lt;p&gt;The real bug is mismatched behavior.&lt;/p&gt;

&lt;p&gt;A stale README can teach someone the wrong command.&lt;br&gt;
A stale locale page can hide a feature from half the audience.&lt;br&gt;
A stale spec can make an agent infer the wrong boundary between project state and runtime state.&lt;/p&gt;

&lt;p&gt;In APC and APX, these mistakes matter more because the whole point of the project is to make boundaries obvious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;project vs. runtime&lt;/li&gt;
&lt;li&gt;repo truth vs. local truth&lt;/li&gt;
&lt;li&gt;contract vs. execution&lt;/li&gt;
&lt;li&gt;source vs. projection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If docs blur those lines, they are not documenting the system. They are undoing it.&lt;/p&gt;

&lt;p&gt;That is why I now write docs with the same question I use for code: what is the actual source of truth here?&lt;/p&gt;

&lt;p&gt;If I cannot answer that clearly, I should not publish the sentence yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in my workflow
&lt;/h2&gt;

&lt;p&gt;The practical effect is boring, which is exactly why it works.&lt;/p&gt;

&lt;p&gt;Now, when I touch APC or APX, I ask three things right away:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Did behavior change, or only implementation details?&lt;/li&gt;
&lt;li&gt;If behavior changed, which docs need the same change now?&lt;/li&gt;
&lt;li&gt;Does the build prove the docs still match the repo?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That keeps me from doing the usual "fix later" move that creates drift.&lt;/p&gt;

&lt;p&gt;It also makes writing easier. I no longer try to write a polished explanation after the fact. I write the explanation while the change is still fresh, when I can still name the tradeoff that mattered.&lt;/p&gt;

&lt;p&gt;That matters in a project like APX because a lot of the value is in decisions, not just features.&lt;/p&gt;

&lt;p&gt;Why does &lt;code&gt;~/.apx/&lt;/code&gt; exist? Because runtime state should stay local.&lt;br&gt;
Why does &lt;code&gt;AGENTS.md&lt;/code&gt; matter? Because tool-agnostic context needs one shared contract.&lt;br&gt;
Why does the web admin exist? Because it is a window into the same runtime, not a separate product.&lt;/p&gt;

&lt;p&gt;Those are not slogans. They are design decisions. Docs should preserve that exact shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule I keep now
&lt;/h2&gt;

&lt;p&gt;My rule is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If a sentence describes how APC or APX works, that sentence is part of the product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means I have to maintain it with the same care I give code.&lt;/p&gt;

&lt;p&gt;Not because prose is sacred.&lt;br&gt;
Not because docs are pretty.&lt;/p&gt;

&lt;p&gt;Because the project only stays coherent if every surface tells the same story.&lt;/p&gt;

&lt;p&gt;And once I started treating docs that way, APC and APX got easier to reason about.&lt;/p&gt;

&lt;p&gt;Less drift.&lt;br&gt;
Less rework.&lt;br&gt;
Fewer fake truths.&lt;/p&gt;

&lt;p&gt;That is the whole win.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Routine Memory Belongs in APX, Not APC</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sat, 25 Jul 2026 12:04:30 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/routine-memory-belongs-in-apx-not-apc-1e53</link>
      <guid>https://dev.to/agentprojectcontext/routine-memory-belongs-in-apx-not-apc-1e53</guid>
      <description>&lt;h1&gt;
  
  
  Routine Memory Belongs in APX, Not APC
&lt;/h1&gt;

&lt;p&gt;A scheduled routine needs memory sometimes.&lt;/p&gt;

&lt;p&gt;Not project memory. Not agent memory. Not a giant prompt pasted back into itself.&lt;/p&gt;

&lt;p&gt;Just a small durable note that helps the next run continue from the last one.&lt;/p&gt;

&lt;p&gt;That is exactly why routine memory should live in APX runtime state, not in APC.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It should carry the project contract: agent definitions, rules, MCP expectations, and any repo-owned files another compatible tool can safely read after a clone.&lt;/p&gt;

&lt;p&gt;APX is the daily-use runtime and tooling layer. It runs the scheduler, executes the routine, tracks timestamps, logs messages, and stores local operational state.&lt;/p&gt;

&lt;p&gt;Routine memory is operational state.&lt;/p&gt;

&lt;h2&gt;
  
  
  The split already exists in APX
&lt;/h2&gt;

&lt;p&gt;APX already treats the routine definition and the routine memory as two different things.&lt;/p&gt;

&lt;p&gt;The routine definition lives in the repo. The daemon docs describe the scheduler flow clearly: when a routine fires, APX reads its definition from &lt;code&gt;.apc/routines.json&lt;/code&gt;, resolves the handler, runs pre and post commands, and writes updated timestamps.&lt;/p&gt;

&lt;p&gt;But the routine memory file is stored under APX runtime storage, not inside &lt;code&gt;.apc/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the code, &lt;code&gt;src/core/stores/routine-memory.js&lt;/code&gt; defines the path as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;projectStoragePath&amp;gt;/routines/&amp;lt;routineId&amp;gt;/memory.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the APX project layout docs explain what &lt;code&gt;projectStoragePath&lt;/code&gt; means in practice: runtime state lives under &lt;code&gt;~/.apx/projects/&amp;lt;apxId&amp;gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the real split is intentional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.apc/routines.json&lt;/code&gt; says what should run&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.apx/projects/&amp;lt;apxId&amp;gt;/routines/&amp;lt;routineId&amp;gt;/memory.md&lt;/code&gt; stores what happened and what the next run should remember&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That boundary is healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APC is the wrong place
&lt;/h2&gt;

&lt;p&gt;A routine memory file looks small, but it behaves like runtime residue.&lt;/p&gt;

&lt;p&gt;It changes after execution. It may contain temporary observations, last-run facts, partial progress, or notes only useful on one machine at one moment in time.&lt;/p&gt;

&lt;p&gt;If you commit that into APC, several problems show up fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;routine runs start creating noisy git diffs&lt;/li&gt;
&lt;li&gt;teammates inherit machine-local or time-local residue&lt;/li&gt;
&lt;li&gt;CI and local runs can fight over the same memory file&lt;/li&gt;
&lt;li&gt;the repo stops describing intent and starts storing execution leftovers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the same reason APC should not hold sessions, message logs, caches, or daemon state.&lt;/p&gt;

&lt;p&gt;Portable context should tell another runtime how to understand the project.&lt;br&gt;
It should not replay yesterday's routine scratchpad.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why APX is the right place
&lt;/h2&gt;

&lt;p&gt;APX owns the scheduler, so APX should own the scheduler's memory.&lt;/p&gt;

&lt;p&gt;That keeps the lifecycle coherent.&lt;/p&gt;

&lt;p&gt;The same runtime that decides when a routine is due can also keep the routine's notes close to its runs, history, messages, and local artifacts. That makes debugging simpler and keeps the repository clean.&lt;/p&gt;

&lt;p&gt;APX also injects a bounded slice of that memory back into the routine prompt. In &lt;code&gt;routine-memory.js&lt;/code&gt;, &lt;code&gt;readRoutineMemoryForPrompt()&lt;/code&gt; trims the content and caps what enters the prompt. Then the routine runner passes that slice through &lt;code&gt;channelMeta.routineMemory&lt;/code&gt; when a &lt;code&gt;super_agent&lt;/code&gt; routine runs.&lt;/p&gt;

&lt;p&gt;That detail matters.&lt;/p&gt;

&lt;p&gt;The goal is not to turn memory into a second project spec. The goal is to give the routine just enough local continuity to behave well on the next execution.&lt;/p&gt;
&lt;h2&gt;
  
  
  A practical example
&lt;/h2&gt;

&lt;p&gt;Imagine a morning standup routine.&lt;/p&gt;

&lt;p&gt;The definition belongs in APC because the project should own the schedule and the prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"morning-standup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"super_agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"schedule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0 9 * * *"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"spec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Summarize open work and send the update."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the routine memory should stay local to APX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Routine memory - morning-standup&lt;/span&gt;

&lt;span class="gu"&gt;## 2026-07-25&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Yesterday's summary was already sent to Telegram.
&lt;span class="p"&gt;-&lt;/span&gt; Skip duplicate reminder unless task count changed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first file is a portable contract.&lt;br&gt;
The second file is runtime continuity.&lt;/p&gt;

&lt;p&gt;Those are not the same category of data, so they should not live in the same layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small rule, cleaner system
&lt;/h2&gt;

&lt;p&gt;If APC is the repo-owned contract layer, keep routine definitions there.&lt;br&gt;
If APX is the runtime layer, keep routine memory there.&lt;/p&gt;

&lt;p&gt;That gives you a cleaner repository, safer automation, and fewer false assumptions when the same project moves across laptops, teammates, or compatible runtimes.&lt;/p&gt;

&lt;p&gt;Routine definitions should travel.&lt;br&gt;
Routine memory should stay with the runtime that earned it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>APC MCP Hints Should Name Secrets, Not Store Them</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Fri, 24 Jul 2026 12:03:35 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/apc-mcp-hints-should-name-secrets-not-store-them-52pf</link>
      <guid>https://dev.to/agentprojectcontext/apc-mcp-hints-should-name-secrets-not-store-them-52pf</guid>
      <description>&lt;h1&gt;
  
  
  APC MCP Hints Should Name Secrets, Not Store Them
&lt;/h1&gt;

&lt;p&gt;A project can tell tools which MCP servers it expects.&lt;/p&gt;

&lt;p&gt;That does not mean the repository should carry the credentials.&lt;/p&gt;

&lt;p&gt;This is one of the clearest APC and APX boundaries: APC should name the MCP contract, while APX should supply and use secrets at runtime.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It gives a repository one stable place to declare project-owned agent context, rules, skills, and MCP expectations. For MCP, that place is &lt;code&gt;.apc/mcps.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;APX is the daily-use runtime and tooling layer. It reads APC files, merges them with local runtime config, audits conflicts, starts servers, and exposes tools through commands like &lt;code&gt;apx mcp list&lt;/code&gt;, &lt;code&gt;apx mcp run&lt;/code&gt;, and &lt;code&gt;apx mcp check&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you keep those jobs separate, the rule gets simple:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.apc/mcps.json&lt;/code&gt; should describe what the project expects.&lt;br&gt;
It should not contain the secret values needed to satisfy that expectation.&lt;/p&gt;
&lt;h2&gt;
  
  
  What belongs in &lt;code&gt;.apc/mcps.json&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The APC MCP config spec is specific about allowed content. The file may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;server names&lt;/li&gt;
&lt;li&gt;commands and non-secret arguments&lt;/li&gt;
&lt;li&gt;remote MCP URLs when the endpoint itself is part of the project contract&lt;/li&gt;
&lt;li&gt;environment variable names a user must provide locally&lt;/li&gt;
&lt;li&gt;enabled or disabled state when a consumer supports it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes the file portable and reviewable.&lt;/p&gt;

&lt;p&gt;A repository can say, "this project expects a GitHub MCP server" or "this project uses a filesystem MCP rooted here," without leaking anyone's account or machine-local state.&lt;/p&gt;

&lt;p&gt;A safe example looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@modelcontextprotocol/server-github"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GITHUB_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${env:GITHUB_TOKEN}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells every compatible consumer what to wire up, but leaves the actual credential outside the repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should stay out
&lt;/h2&gt;

&lt;p&gt;The same APC spec also draws a hard line around unsafe content. Do not commit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API keys&lt;/li&gt;
&lt;li&gt;bearer tokens&lt;/li&gt;
&lt;li&gt;OAuth refresh tokens&lt;/li&gt;
&lt;li&gt;personal account IDs&lt;/li&gt;
&lt;li&gt;private headers&lt;/li&gt;
&lt;li&gt;credentials embedded in URLs&lt;/li&gt;
&lt;li&gt;generated session IDs&lt;/li&gt;
&lt;li&gt;machine-local absolute paths unless the path itself is intentionally part of the contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason is bigger than secret hygiene.&lt;/p&gt;

&lt;p&gt;If a repository stores literal credentials in &lt;code&gt;.apc/mcps.json&lt;/code&gt;, APC stops being portable context and starts becoming a private runtime dump. That breaks the whole point of APC.&lt;/p&gt;

&lt;p&gt;A clone-safe contract should survive a new laptop, a new teammate, or a different compatible runtime. A real token does not travel safely across any of those boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where APX fits
&lt;/h2&gt;

&lt;p&gt;This is where APX becomes useful instead of redundant.&lt;/p&gt;

&lt;p&gt;APX does not need APC to hold the secret itself. It needs APC to hold the portable hint. Then APX can merge that hint with local runtime state and do the operational work.&lt;/p&gt;

&lt;p&gt;That is why the APX CLI has a dedicated MCP layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apx mcp list
apx mcp check
apx mcp run github search_repositories &lt;span class="s1"&gt;'{"query":"org:agentprojectcontext"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;apx mcp check&lt;/code&gt; is especially relevant here because it audits MCP source files, merge order, and conflicts. In practice, that means APC can stay commit-safe while APX verifies whether the local machine has supplied the missing pieces correctly.&lt;/p&gt;

&lt;p&gt;So the workflow becomes clean:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The repo declares the expected MCP server in &lt;code&gt;.apc/mcps.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The user provides credentials locally through environment variables or runtime-owned config.&lt;/li&gt;
&lt;li&gt;APX reads both layers, audits them, and runs the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is a better split than pushing everything into one file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why naming env vars is enough
&lt;/h2&gt;

&lt;p&gt;Teams sometimes assume that if the repo already names a secret like &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;, they may as well paste the value too.&lt;/p&gt;

&lt;p&gt;That is the wrong conclusion.&lt;/p&gt;

&lt;p&gt;Naming the variable is enough because it preserves the contract without hardcoding ownership.&lt;/p&gt;

&lt;p&gt;The project can say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which variable must exist&lt;/li&gt;
&lt;li&gt;which server consumes it&lt;/li&gt;
&lt;li&gt;which command uses that server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and still let each developer, CI runner, or local daemon provide the value in its own safe way.&lt;/p&gt;

&lt;p&gt;That is exactly how portable context should behave.&lt;/p&gt;

&lt;p&gt;APC keeps the shared project expectation visible in Git.&lt;br&gt;
APX keeps runtime credentials and execution local.&lt;/p&gt;

&lt;p&gt;Small rule, big payoff.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;.apc/mcps.json&lt;/code&gt; names secrets instead of storing them, the repository stays portable, review stays sane, and runtimes like APX can still wire the full MCP stack without leaking private state into the project.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
