<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://blogs.agntcy.org/drafts/docs-dir-cli-context/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blogs.agntcy.org/drafts/docs-dir-cli-context/" rel="alternate" type="text/html" /><updated>2026-05-13T16:16:13+00:00</updated><id>https://blogs.agntcy.org/drafts/docs-dir-cli-context/feed.xml</id><title type="html">AGNTCY Blogs</title><subtitle>Building infrastructure for the Internet of Agents</subtitle><entry><title type="html">Switching Between Local and Hosted Directory with dirctl Contexts</title><link href="https://blogs.agntcy.org/drafts/docs-dir-cli-context/technical/directory/2026/05/13/dirctl-context-oidc-gateway.html" rel="alternate" type="text/html" title="Switching Between Local and Hosted Directory with dirctl Contexts" /><published>2026-05-13T09:00:00+00:00</published><updated>2026-05-13T09:00:00+00:00</updated><id>https://blogs.agntcy.org/drafts/docs-dir-cli-context/technical/directory/2026/05/13/dirctl-context-oidc-gateway</id><content type="html" xml:base="https://blogs.agntcy.org/drafts/docs-dir-cli-context/technical/directory/2026/05/13/dirctl-context-oidc-gateway.html"><![CDATA[<p>When you work with <a href="https://docs.agntcy.org/dir/overview/">Agent Directory</a>, you often move between two worlds.</p>

<p>On your laptop, you want a fast local Directory server where you can test records, validate metadata, and iterate without needing a cluster. When you are ready to search, publish, or interact with a shared environment, you want the hosted Directory testbed with real authentication at the edge.</p>

<p><code class="language-plaintext highlighter-rouge">dirctl context</code> makes that switch explicit. Instead of remembering a different <code class="language-plaintext highlighter-rouge">--server-addr</code>, <code class="language-plaintext highlighter-rouge">--auth-mode</code>, OIDC issuer, or TLS setting for every command, you can name each Directory target once and then move between them safely.</p>

<!--more-->

<p><strong>TL;DR:</strong> Run a local Directory daemon on <code class="language-plaintext highlighter-rouge">localhost:8888</code>, create a <code class="language-plaintext highlighter-rouge">dirctl</code> config with <code class="language-plaintext highlighter-rouge">local</code> and <code class="language-plaintext highlighter-rouge">prod</code> contexts, authenticate to the hosted testbed with OIDC, and show the active Directory context in your zsh or powerlevel10k prompt.</p>

<h3 id="what-youll-learn">What You’ll Learn</h3>

<p>In this post, you’ll learn:</p>

<ul>
  <li>How to run a local Directory server with <code class="language-plaintext highlighter-rouge">dirctl daemon</code></li>
  <li>How to create a reusable <code class="language-plaintext highlighter-rouge">dirctl</code> client config</li>
  <li>How to switch between local and hosted Directory contexts</li>
  <li>How OIDC authentication works for the hosted testbed</li>
  <li>What <code class="language-plaintext highlighter-rouge">oidc-gateway</code> does in a production-style deployment</li>
  <li>How to show the active Directory context in zsh and powerlevel10k</li>
</ul>

<h2 id="the-workflow-one-cli-two-directories">The Workflow: One CLI, Two Directories</h2>

<p>A typical developer workflow looks like this:</p>

<ol>
  <li>Start a local Directory server on your laptop.</li>
  <li>Push, pull, search, and validate records locally.</li>
  <li>Switch to the hosted testbed.</li>
  <li>Authenticate with OIDC.</li>
  <li>Run the same <code class="language-plaintext highlighter-rouge">dirctl</code> commands against the remote Directory.</li>
</ol>

<p>The commands are familiar in both places. The target and authentication are different.</p>

<pre><code class="language-mermaid">flowchart LR
    developer["Developer laptop"]
    dirctl["dirctl"]
    localDaemon["Local Directory daemon"]
    oidcGateway["oidc-gateway"]
    prodDirectory["Hosted Directory"]
    idp["OIDC provider"]

    developer --&gt; dirctl
    dirctl --&gt;|"local context"| localDaemon
    dirctl --&gt;|"prod context + OIDC token"| oidcGateway
    idp --&gt;|"issuer metadata and JWKS"| oidcGateway
    oidcGateway --&gt;|"authorized request"| prodDirectory
</code></pre>

<p>Without contexts, you can still pass flags manually:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl <span class="nt">--server-addr</span> localhost:8888 search <span class="nt">--name</span> <span class="s2">"*"</span>

dirctl <span class="nt">--server-addr</span> prod.gateway.ads.outshift.io:443 <span class="se">\</span>
  <span class="nt">--auth-mode</span> oidc <span class="se">\</span>
  <span class="nt">--oidc-issuer</span> https://prod.idp.ads.outshift.io <span class="se">\</span>
  <span class="nt">--oidc-client-id</span> dirctl <span class="se">\</span>
  search <span class="nt">--skill</span> <span class="s2">"natural_language_processing"</span>
</code></pre></div></div>

<p>That works, but it does not scale well once you have a local daemon, a staging Directory, a hosted testbed, and maybe a partner environment. Contexts give each target a short name.</p>

<p><code class="language-plaintext highlighter-rouge">dirctl context</code> is available starting with <code class="language-plaintext highlighter-rouge">dirctl</code> v1.4.0, which is planned for an upcoming release. If your local CLI does not recognize the <code class="language-plaintext highlighter-rouge">context</code> command yet, upgrade to v1.4.0 or newer when it is available.</p>

<h2 id="step-1-run-a-local-directory-server">Step 1: Run a Local Directory Server</h2>

<p>For local development, the fastest path is the built-in daemon:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl daemon start
</code></pre></div></div>

<p>The daemon runs a self-contained Directory server in one process. It starts the gRPC API on <code class="language-plaintext highlighter-rouge">localhost:8888</code>, uses SQLite for persistence, and stores records in a local filesystem OCI store. By default, its state lives under:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.agntcy/dir/
</code></pre></div></div>

<p>In another terminal, point <code class="language-plaintext highlighter-rouge">dirctl</code> at the local daemon:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl <span class="nt">--server-addr</span> localhost:8888 search <span class="nt">--name</span> <span class="s2">"*"</span>
</code></pre></div></div>

<p>This local mode is useful for quick experiments because it does not require Docker, Kubernetes, PostgreSQL, or an external registry. For a deeper comparison between the local daemon and Docker Compose deployment modes, see the <a href="https://docs.agntcy.org/dir/dir-deployment-local/">Local Deployment guide</a>.</p>

<h2 id="step-2-create-a-dirctl-client-config">Step 2: Create a dirctl Client Config</h2>

<p>Now let’s stop passing the server address every time.</p>

<p><code class="language-plaintext highlighter-rouge">dirctl</code> looks for reusable client contexts in:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.config/dirctl/config.yaml
</code></pre></div></div>

<p>Create the directory and config file:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> ~/.config/dirctl
<span class="nv">$EDITOR</span> ~/.config/dirctl/config.yaml
</code></pre></div></div>

<p>Start with two contexts: one for the local daemon and one for the hosted testbed.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">current_context</span><span class="pi">:</span> <span class="s">local</span>
<span class="na">contexts</span><span class="pi">:</span>
  <span class="na">local</span><span class="pi">:</span>
    <span class="na">server_address</span><span class="pi">:</span> <span class="s">localhost:8888</span>
    <span class="na">auth_mode</span><span class="pi">:</span> <span class="s">insecure</span>
  <span class="na">prod</span><span class="pi">:</span>
    <span class="na">server_address</span><span class="pi">:</span> <span class="s">prod.gateway.ads.outshift.io:443</span>
    <span class="na">auth_mode</span><span class="pi">:</span> <span class="s">oidc</span>
    <span class="na">oidc_issuer</span><span class="pi">:</span> <span class="s">https://prod.idp.ads.outshift.io</span>
    <span class="na">oidc_client_id</span><span class="pi">:</span> <span class="s">dirctl</span>
</code></pre></div></div>

<p>The shape is intentionally small:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">current_context</code> is the default context used by <code class="language-plaintext highlighter-rouge">dirctl</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">contexts</code> contains named client configurations.</li>
  <li><code class="language-plaintext highlighter-rouge">server_address</code> is the Directory endpoint for that context.</li>
  <li><code class="language-plaintext highlighter-rouge">auth_mode</code> tells <code class="language-plaintext highlighter-rouge">dirctl</code> how to authenticate.</li>
  <li><code class="language-plaintext highlighter-rouge">oidc_issuer</code> and <code class="language-plaintext highlighter-rouge">oidc_client_id</code> are used by <code class="language-plaintext highlighter-rouge">dirctl auth login</code> for OIDC-backed environments.</li>
</ul>

<p>Keep this file focused on configuration, not credentials. Do not paste bearer tokens into the file for normal interactive use. <code class="language-plaintext highlighter-rouge">dirctl auth login</code> stores the cached login token separately, and automation should prefer short-lived tokens from its identity provider.</p>

<h2 id="step-3-use-dirctl-context">Step 3: Use dirctl context</h2>

<p>Once the config exists, inspect it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context list
dirctl context current
dirctl context show
dirctl context validate
</code></pre></div></div>

<p>The most important command is <code class="language-plaintext highlighter-rouge">set</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context <span class="nb">set </span>prod
</code></pre></div></div>

<p>After that, ordinary commands use the <code class="language-plaintext highlighter-rouge">prod</code> context by default:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl search <span class="nt">--skill</span> <span class="s2">"natural_language_processing"</span>
</code></pre></div></div>

<p>You can switch back to your local daemon just as easily:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context <span class="nb">set local
</span>dirctl search <span class="nt">--name</span> <span class="s2">"*"</span>
</code></pre></div></div>

<p>For one command only, use <code class="language-plaintext highlighter-rouge">--context</code>. This is handy when you want to query another Directory without changing your default:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl <span class="nt">--context</span> <span class="nb">local </span>search <span class="nt">--name</span> <span class="s2">"*"</span>
dirctl <span class="nt">--context</span> prod search <span class="nt">--skill</span> <span class="s2">"natural_language_processing"</span>
</code></pre></div></div>

<p>Use <code class="language-plaintext highlighter-rouge">dirctl context show</code> when you want to confirm what will be used. Sensitive values are redacted in the output, so it is safe to copy into a support thread when debugging configuration issues.</p>

<h2 id="step-4-authenticate-to-the-hosted-testbed">Step 4: Authenticate to the Hosted Testbed</h2>

<p>The local daemon is intentionally simple. It usually runs with <code class="language-plaintext highlighter-rouge">auth_mode: insecure</code> because it is bound to your laptop and used for development.</p>

<p>The hosted testbed is different. It sits behind an authentication gateway and expects an authenticated identity. For a human operator, the normal flow is:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context <span class="nb">set </span>prod
dirctl auth login
dirctl auth status
dirctl search <span class="nt">--skill</span> <span class="s2">"natural_language_processing"</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">dirctl auth login</code> starts the OIDC login flow for the active context. Depending on the environment, it can use a browser-based flow, a no-browser flow, or a device flow. Once complete, <code class="language-plaintext highlighter-rouge">dirctl</code> can reuse the cached token for later commands.</p>

<p>Directory supports several authentication modes:</p>

<table>
  <thead>
    <tr>
      <th>Mode</th>
      <th>Best for</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>empty / auto</td>
      <td>Let <code class="language-plaintext highlighter-rouge">dirctl</code> try SPIFFE, then cached OIDC, then local insecure mode</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">oidc</code></td>
      <td>Human login, CI workload identity, and external automation with bearer tokens</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">x509</code></td>
      <td>SPIFFE X.509-SVID clients using mTLS</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">jwt</code></td>
      <td>SPIFFE JWT-SVID or compatible JWT-based service identity</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">tls</code></td>
      <td>Custom PKI and mTLS setups</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">insecure</code> / <code class="language-plaintext highlighter-rouge">none</code></td>
      <td>Local development and testing only</td>
    </tr>
  </tbody>
</table>

<p>For day-to-day use, keep the local context explicit with <code class="language-plaintext highlighter-rouge">auth_mode: insecure</code> and the hosted context explicit with <code class="language-plaintext highlighter-rouge">auth_mode: oidc</code>. That makes the intent obvious when you run <code class="language-plaintext highlighter-rouge">dirctl context show</code>.</p>

<h2 id="what-is-oidc-gateway">What is oidc-gateway?</h2>

<p><code class="language-plaintext highlighter-rouge">oidc-gateway</code> is the edge component that enables users and automation access Directory from outside the cluster using standards-based identity.</p>

<p>In a production-style deployment, the Directory backend can keep its internal trust model focused on SPIFFE/SPIRE while external callers authenticate through OIDC, JWT, or mTLS at the gateway. The gateway verifies the credential, asks an authorization service whether the principal is allowed, and forwards only authorized requests to Directory.</p>

<pre><code class="language-mermaid">sequenceDiagram
    participant User as User or automation
    participant CLI as dirctl
    participant IdP as OIDC provider
    participant Gateway as oidc-gateway
    participant Authz as ext_authz policy
    participant Directory as Directory API

    User-&gt;&gt;CLI: dirctl auth login
    CLI-&gt;&gt;IdP: OIDC login
    IdP--&gt;&gt;CLI: Short-lived token
    CLI-&gt;&gt;Gateway: Directory request + bearer token
    Gateway-&gt;&gt;Gateway: Validate JWT
    Gateway-&gt;&gt;Authz: Check principal and action
    Authz--&gt;&gt;Gateway: Allow
    Gateway-&gt;&gt;Directory: Forward authorized request
    Directory--&gt;&gt;Gateway: Response
    Gateway--&gt;&gt;CLI: Response
</code></pre>

<p>This separation matters. The CLI gets a familiar login experience, operators can integrate with their existing identity provider, and backend services do not need to grow one-off authentication paths for every external client.</p>

<p>With recent <code class="language-plaintext highlighter-rouge">oidc-gateway</code> deployments, operators may expose two hostnames:</p>

<ul>
  <li>An OIDC/JWT hostname for <code class="language-plaintext highlighter-rouge">auth_mode: oidc</code>, cached OIDC login, pre-issued JWTs, and CI workload identity.</li>
  <li>An mTLS hostname for <code class="language-plaintext highlighter-rouge">auth_mode: x509</code> or <code class="language-plaintext highlighter-rouge">auth_mode: tls</code>, where the gateway validates the client certificate.</li>
</ul>

<p>Use the endpoint that matches the credential you send. If you use the OIDC context above, point it at the OIDC/JWT hostname. For operator-level setup, see <a href="https://docs.agntcy.org/dir/directory-oidc-authentication/">OIDC Authentication for Directory</a>.</p>

<h2 id="step-5-show-the-directory-context-in-zsh">Step 5: Show the Directory Context in zsh</h2>

<p>Contexts reduce typing, but they also introduce a new question: which Directory am I pointing at right now?</p>

<p>If you use zsh, you can add a small helper that prints the active <code class="language-plaintext highlighter-rouge">dirctl</code> context. It fails quietly when <code class="language-plaintext highlighter-rouge">dirctl</code> is unavailable or no context is configured.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">function </span>dirctl_context_prompt<span class="o">()</span> <span class="o">{</span>
  <span class="nb">local </span>ctx
  <span class="nv">ctx</span><span class="o">=</span><span class="si">$(</span>dirctl context current <span class="nt">--quiet</span> 2&gt;/dev/null<span class="si">)</span> <span class="o">||</span> <span class="k">return</span>
  <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$ctx</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> print <span class="nt">-r</span> <span class="nt">--</span> <span class="s2">"dir:</span><span class="nv">$ctx</span><span class="s2">"</span>
<span class="o">}</span>
</code></pre></div></div>

<p>You can try it directly:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl_context_prompt
</code></pre></div></div>

<p>If your current context is <code class="language-plaintext highlighter-rouge">prod</code>, it prints:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dir:prod
</code></pre></div></div>

<p>For a simple custom prompt, you can wire it into <code class="language-plaintext highlighter-rouge">PROMPT</code>:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setopt PROMPT_SUBST
<span class="nv">PROMPT</span><span class="o">=</span><span class="s1">'$(dirctl_context_prompt) %~ %# '</span>
</code></pre></div></div>

<p>That is enough to make the active Directory visible before every command.</p>

<h2 id="powerlevel10k-integration">Powerlevel10k Integration</h2>

<p>If you use <a href="https://github.com/romkatv/powerlevel10k">powerlevel10k</a>, define a custom prompt segment in <code class="language-plaintext highlighter-rouge">~/.p10k.zsh</code>:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">function </span>prompt_dirctl_context<span class="o">()</span> <span class="o">{</span>
  <span class="nb">local </span>ctx
  <span class="nv">ctx</span><span class="o">=</span><span class="si">$(</span>dirctl context current <span class="nt">--quiet</span> 2&gt;/dev/null<span class="si">)</span> <span class="o">||</span> <span class="k">return</span>
  <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$ctx</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">||</span> <span class="k">return

  </span>p10k segment <span class="nt">-f</span> 39 <span class="nt">-i</span> <span class="s1">'DIR'</span> <span class="nt">-t</span> <span class="s2">"</span><span class="nv">$ctx</span><span class="s2">"</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Then add <code class="language-plaintext highlighter-rouge">dirctl_context</code> to one of your prompt element arrays:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">typeset</span> <span class="nt">-g</span> <span class="nv">POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS</span><span class="o">=(</span>
  dirctl_context
  status
  command_execution_time
  <span class="nb">time</span>
<span class="o">)</span>
</code></pre></div></div>

<p>Now your prompt shows the active Directory context next to your other session state. When the prompt says <code class="language-plaintext highlighter-rouge">prod</code>, you know commands are going to the hosted testbed. When it says <code class="language-plaintext highlighter-rouge">local</code>, you know you are working against your daemon.</p>

<h2 id="troubleshooting">Troubleshooting</h2>

<h3 id="dirctl-context-current---quiet-prints-nothing"><code class="language-plaintext highlighter-rouge">dirctl context current --quiet</code> prints nothing</h3>

<p>No <code class="language-plaintext highlighter-rouge">current_context</code> is set, or the config file does not exist yet. Create <code class="language-plaintext highlighter-rouge">~/.config/dirctl/config.yaml</code>, then run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context <span class="nb">set local</span>
</code></pre></div></div>

<h3 id="dirctl-context-validate-reports-an-unknown-field"><code class="language-plaintext highlighter-rouge">dirctl context validate</code> reports an unknown field</h3>

<p>The client config parser validates known fields. Check for typos such as <code class="language-plaintext highlighter-rouge">server-addr</code> instead of <code class="language-plaintext highlighter-rouge">server_address</code>, or <code class="language-plaintext highlighter-rouge">authMode</code> instead of <code class="language-plaintext highlighter-rouge">auth_mode</code>.</p>

<h3 id="server_address-is-required"><code class="language-plaintext highlighter-rouge">server_address is required</code></h3>

<p>Every usable context needs a <code class="language-plaintext highlighter-rouge">server_address</code>:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">contexts</span><span class="pi">:</span>
  <span class="na">local</span><span class="pi">:</span>
    <span class="na">server_address</span><span class="pi">:</span> <span class="s">localhost:8888</span>
</code></pre></div></div>

<h3 id="the-local-context-cannot-connect">The local context cannot connect</h3>

<p>Make sure the daemon is running:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl daemon start
</code></pre></div></div>

<p>Then test the local context:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl <span class="nt">--context</span> <span class="nb">local </span>search <span class="nt">--name</span> <span class="s2">"*"</span>
</code></pre></div></div>

<h3 id="the-prod-context-says-you-are-not-authenticated">The prod context says you are not authenticated</h3>

<p>Log in again:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dirctl context <span class="nb">set </span>prod
dirctl auth login
dirctl auth status
</code></pre></div></div>

<p>If login succeeds but API calls still fail, confirm that your user or organization is allowed by the hosted environment’s policy.</p>

<h3 id="oidc-and-mtls-endpoints-are-easy-to-mix-up">OIDC and mTLS endpoints are easy to mix up</h3>

<p>If your context uses <code class="language-plaintext highlighter-rouge">auth_mode: oidc</code>, use the OIDC/JWT gateway hostname. If your context uses <code class="language-plaintext highlighter-rouge">auth_mode: x509</code> or <code class="language-plaintext highlighter-rouge">auth_mode: tls</code>, use the mTLS gateway hostname.</p>

<h2 id="wrap-up">Wrap-up</h2>

<p><code class="language-plaintext highlighter-rouge">dirctl context</code> is a small feature with a big impact on day-to-day Directory usage.</p>

<p>You can keep a local daemon for fast iteration, use the hosted testbed with OIDC when you need a shared Directory, and make the active target visible in your shell prompt. The result is less flag juggling, fewer accidental commands against the wrong environment, and a smoother path from local development to authenticated Directory access.</p>

<p>For deeper reference material, continue with the <a href="https://docs.agntcy.org/dir/directory-cli/">Directory CLI guide</a>, the <a href="https://docs.agntcy.org/dir/dir-deployment-local/">Local Deployment guide</a>, and <a href="https://docs.agntcy.org/dir/directory-oidc-authentication/">OIDC Authentication for Directory</a>.</p>]]></content><author><name>Tibor Kircsi</name></author><category term="technical" /><category term="directory" /><category term="dirctl" /><category term="directory" /><category term="oidc" /><category term="oidc-gateway" /><category term="developer-experience" /><category term="zsh" /><summary type="html"><![CDATA[When you work with Agent Directory, you often move between two worlds. On your laptop, you want a fast local Directory server where you can test records, validate metadata, and iterate without needing a cluster. When you are ready to search, publish, or interact with a shared environment, you want the hosted Directory testbed with real authentication at the edge. dirctl context makes that switch explicit. Instead of remembering a different --server-addr, --auth-mode, OIDC issuer, or TLS setting for every command, you can name each Directory target once and then move between them safely.]]></summary></entry></feed>