Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Overview · janwilmake/agent-codemode · GitHub
Skip to content

Security: janwilmake/agent-codemode

Security

SECURITY.md

Security

What this package does with your credentials

  • It reads them. It never writes, refreshes, rotates or deletes them.
  • It never transmits a token anywhere except to the MCP server that issued it.
  • It never caches a token, on disk or in memory across calls. Every call re-reads the credential store, because Claude Code refreshes on its own schedule and a cached token goes stale silently.
  • It never prints one. agent-codemode servers shows a name, a transport and an expiry — never secret material.
  • An expired token raises a loud error. It never degrades into an empty result.

The thing worth knowing about your machine

This is the part to read before you install anything, including this.

On macOS, Claude Code stores every MCP OAuth token in a single Keychain item — service Claude Code-credentials. That item is readable, without a prompt, by any process running as you that Claude Code itself could have spawned. That includes this package. It also includes every hook you have configured, every MCP server that runs as a local subprocess, every npx package one of those pulls in, and every shell command an agent decides to run.

So: every MCP token you hold — production included — is readable by any process started from a Claude Code session. That is a property of how the credential store works, not something this package introduces. Removing this package does not change it. This package is simply an honest, readable demonstration of it.

Two practical consequences:

  1. Treat your agent's MCP server list as a blast radius. A server you authenticate for convenience is a server any code your agent runs can reach with your identity. If hyre-prod is one npx away from an untrusted postinstall script, that is worth knowing deliberately rather than discovering later.
  2. Prefer read-scoped tokens where the server offers them. Most MCP servers issue one token for everything they can do. Where a server distinguishes scopes, take the narrow one.

Scope of this package's own risk

This package adds no network listener, no daemon, no background process, and no persistent state. It runs, reads a credential, makes one JSON-RPC call to the server that credential belongs to, and exits.

The one capability it adds that you did not already have is convenience — calling those servers without a model deciding to. That is the point, and it is also the thing to be deliberate about: a script with your Linear token can close tickets at 3am with no one reading the diff. Write your gates so that the destructive path is explicit, the way examples/standup.ts keeps sending behind --post.

Reporting a vulnerability

Open a GitHub issue for anything non-sensitive. For something you would rather not post publicly, email jan@wilmake.com.

There aren't any published security advisories