<?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: Hassan Mehmood</title>
    <description>The latest articles on DEV Community by Hassan Mehmood (@hasanmehmood).</description>
    <link>https://dev.to/hasanmehmood</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%2F362614%2F9fe89516-ec6f-429d-be45-37564ca4f0db.jpeg</url>
      <title>DEV Community: Hassan Mehmood</title>
      <link>https://dev.to/hasanmehmood</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hasanmehmood"/>
    <language>en</language>
    <item>
      <title>Your AI agent has sudo. I built a tool to take it away.</title>
      <dc:creator>Hassan Mehmood</dc:creator>
      <pubDate>Sun, 21 Jun 2026 12:49:08 +0000</pubDate>
      <link>https://dev.to/hasanmehmood/your-ai-agent-has-sudo-i-built-a-tool-to-take-it-away-46mk</link>
      <guid>https://dev.to/hasanmehmood/your-ai-agent-has-sudo-i-built-a-tool-to-take-it-away-46mk</guid>
      <description>&lt;p&gt;A few weeks ago I gave an AI agent access to my machine through MCP. It read files, opened PRs, queried a database. It was great — until I looked at &lt;em&gt;what it could have done&lt;/em&gt; if a tool description had been poisoned, or a prompt injection had slipped through.&lt;/p&gt;

&lt;p&gt;The answer was: anything. &lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;. &lt;code&gt;DROP TABLE users&lt;/code&gt;. &lt;code&gt;rm -rf /&lt;/code&gt;. The agent had sudo, and nobody had voted for that.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://github.com/hasanmehmood/agentperms" rel="noopener noreferrer"&gt;AgentPerms&lt;/a&gt;&lt;/strong&gt; — a CLI that gives MCP agents least-privilege permissions the same way you'd lock down any other process: figure out the minimum it actually needs, pin it, prove it, and enforce it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentperms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The gap nobody was filling
&lt;/h2&gt;

&lt;p&gt;MCP (the Model Context Protocol) is quietly becoming the USB-C of AI tooling. Claude Desktop, Cursor, VS Code, Windsurf, Gemini CLI — they all speak it. Which is wonderful, and also means your agent is one config file away from your filesystem, your repos, your inbox, and prod.&lt;/p&gt;

&lt;p&gt;The existing tools each do &lt;em&gt;part&lt;/em&gt; of the job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scanners&lt;/strong&gt; tell you something &lt;em&gt;looks&lt;/em&gt; risky. Then they leave. You still have a risky thing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firewalls / allowlists&lt;/strong&gt; make you hand-write YAML up front — before you have any idea what the agent will actually use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither closes the loop. What I wanted was the boring, proven security workflow we already use for everything else: &lt;strong&gt;observe real behavior → derive least privilege → enforce it → keep it honest in CI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the whole thesis of AgentPerms, as a pipeline:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;record → infer → lock → replay → enforce&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  See it in 30 seconds (no setup, no network)
&lt;/h2&gt;

&lt;p&gt;AgentPerms ships with a deliberately over-privileged demo MCP server, so you can watch a real policy decision without wiring anything up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Flag risky config: a ~/.ssh mount and an unpinned npx server&lt;/span&gt;
agentperms scan &lt;span class="nt"&gt;--path&lt;/span&gt; examples/vulnerable-mcp-demo

&lt;span class="c"&gt;# Replay a pack of canned attacks against an example policy&lt;/span&gt;
agentperms replay &lt;span class="nt"&gt;--policy&lt;/span&gt; examples/policies/example.mcp.policy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8/8 attacks blocked.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSH-key exfiltration, &lt;code&gt;.env&lt;/code&gt; reads, &lt;code&gt;rm -rf /&lt;/code&gt;, unapproved email, force-push, repo deletion, destructive SQL — every one denied or routed to human approval &lt;em&gt;before it would ever reach a server&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick: be the proxy
&lt;/h2&gt;

&lt;p&gt;Here's the part I'm proud of. AgentPerms doesn't ask your agent to cooperate, and it doesn't patch the client. It rewrites the MCP client's config so every server launches &lt;strong&gt;through a transparent stdio proxy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent  →  AgentPerms proxy  →  MCP server
              │
              ├─ record:  log every tools/call, then forward
              └─ enforce: allow / deny / require-approval before forwarding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proxy spawns the real server as a subprocess and pumps newline-delimited JSON-RPC both ways. It intercepts &lt;code&gt;tools/call&lt;/code&gt; requests and captures &lt;code&gt;tools/list&lt;/code&gt; responses. That's it. The agent has no idea it's there.&lt;/p&gt;

&lt;p&gt;A server entry goes from this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"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;"python3"&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;"server.py"&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;to this (original command preserved after &lt;code&gt;--&lt;/code&gt;, with a &lt;code&gt;.agentperms.bak&lt;/code&gt; so you can roll back):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"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;"/usr/bin/python3"&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;"-m"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agentperms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="s2"&gt;"--mode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enforce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="s2"&gt;"--policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/abs/path/mcp.policy.yaml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="s2"&gt;"--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.py"&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;In &lt;strong&gt;record&lt;/strong&gt; mode it logs and forwards. In &lt;strong&gt;enforce&lt;/strong&gt; mode it evaluates &lt;em&gt;first&lt;/em&gt; and, on a DENY, returns a synthetic JSON-RPC error to the client &lt;strong&gt;without forwarding&lt;/strong&gt;. Denied calls never touch the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record what's real, infer the minimum
&lt;/h2&gt;

&lt;p&gt;You don't write the policy. You run your agent normally for a while with recording on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentperms record &lt;span class="nt"&gt;--client&lt;/span&gt; cursor
&lt;span class="c"&gt;#   ... use your agent ...&lt;/span&gt;
agentperms infer        &lt;span class="c"&gt;# traces -&amp;gt; mcp.policy.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;infer&lt;/code&gt; is the killer command. It reads the traces and emits the &lt;em&gt;minimum&lt;/em&gt; policy that still lets the agent do what it actually did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the tools it called become &lt;code&gt;allowed_tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the directories it touched collapse into the smallest covering set of &lt;code&gt;allowed_paths&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;known-dangerous categories (shell, repo deletion, email send, DB writes) get seeded straight into &lt;code&gt;denied_tools&lt;/code&gt; / human-approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result reads like a security review wrote it for you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Your agent only used read-only GitHub calls and local &lt;code&gt;./src&lt;/code&gt; access. It does not need shell, home directory, secrets, Gmail send, or database write access.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  One decision authority
&lt;/h2&gt;

&lt;p&gt;Whatever you do, there must be exactly &lt;strong&gt;one&lt;/strong&gt; place that says allow/deny/approve — otherwise your offline tests and your live enforcement drift apart and you're testing a lie.&lt;/p&gt;

&lt;p&gt;In AgentPerms that's a single &lt;code&gt;evaluate(policy, server, tool, args)&lt;/code&gt; function, called by &lt;em&gt;both&lt;/em&gt; the live proxy and offline &lt;code&gt;replay&lt;/code&gt;. First-match-wins:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the human-approval list → &lt;strong&gt;require approval&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;denied_tools&lt;/code&gt; → &lt;strong&gt;deny&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A path argument hits &lt;code&gt;denied_paths&lt;/code&gt; / &lt;code&gt;denied_patterns&lt;/code&gt; → &lt;strong&gt;deny&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowed_tools&lt;/code&gt; set and tool not in it → &lt;strong&gt;deny&lt;/strong&gt; (default-deny)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowed_paths&lt;/code&gt; set and a path falls outside it → &lt;strong&gt;deny&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Otherwise → &lt;strong&gt;allow&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An empty policy allows everything. The moment &lt;em&gt;any&lt;/em&gt; server is constrained, unknown servers default-deny. What you test in &lt;code&gt;replay&lt;/code&gt; is byte-for-byte what runs in production, because it's the same code path.&lt;/p&gt;

&lt;p&gt;The policy itself stays small and reviewable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;allowed_tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;list_repos&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;read_file&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;create_issue&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;denied_tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;delete_repo&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;write_secret&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;force_push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;filesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;allowed_paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;./src&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;./docs&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;denied_paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;~/.ssh&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;~/.env&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;/etc&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;denied_patterns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.pem"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.key"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;approvals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;require_human_approval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gmail.send_email&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;github.merge_pr&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;shell.exec&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;redaction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;emails&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;api_keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tool poisoning: pin the identity
&lt;/h2&gt;

&lt;p&gt;There's a sneaky MCP attack class where a server silently changes a tool's &lt;em&gt;description&lt;/em&gt; or &lt;em&gt;schema&lt;/em&gt; after you've trusted it — the model re-reads it and gets quietly re-instructed. So AgentPerms also locks tool identity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentperms lock          &lt;span class="c"&gt;# hash every tool's name/description/schema&lt;/span&gt;
agentperms lock &lt;span class="nt"&gt;--check&lt;/span&gt;  &lt;span class="c"&gt;# fail if any of them changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop &lt;code&gt;lock --check&lt;/code&gt; in CI and a poisoned tool fails the build instead of your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make it a part of the codebase
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentperms init   &lt;span class="c"&gt;# scaffolds .github/workflows/agentperms.yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On every push/PR it runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentperms scan &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;     &lt;span class="c"&gt;# surface risky configs&lt;/span&gt;
agentperms lock &lt;span class="nt"&gt;--check&lt;/span&gt;      &lt;span class="c"&gt;# fail on tool poisoning&lt;/span&gt;
agentperms replay            &lt;span class="c"&gt;# fail if the policy stops blocking attacks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit &lt;code&gt;mcp.policy.yaml&lt;/code&gt; and &lt;code&gt;mcp.lock&lt;/code&gt;, and your agent's permissions become a reviewable, version-controlled, enforceable artifact — like any other part of your security posture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do (yet)
&lt;/h2&gt;

&lt;p&gt;I'd rather be honest than oversell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transport:&lt;/strong&gt; local &lt;strong&gt;stdio&lt;/strong&gt; MCP servers today. HTTP/SSE is on the roadmap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approvals&lt;/strong&gt; prompt on the terminal — fine for dev, not yet a fleet-grade workflow.&lt;/li&gt;
&lt;li&gt;A live dashboard and a Node wrapper are next.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agentperms
agentperms scan &lt;span class="nt"&gt;--path&lt;/span&gt; examples/vulnerable-mcp-demo
agentperms replay &lt;span class="nt"&gt;--policy&lt;/span&gt; examples/policies/example.mcp.policy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PyPI:&lt;/strong&gt; &lt;a href="https://pypi.org/project/agentperms/" rel="noopener noreferrer"&gt;https://pypi.org/project/agentperms/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/hasanmehmood/agentperms" rel="noopener noreferrer"&gt;https://github.com/hasanmehmood/agentperms&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're running agents with real access to real systems, I'd genuinely love your feedback — especially on the policy model and what attack shapes you'd want in the replay pack. Issues and PRs welcome.&lt;/p&gt;

&lt;p&gt;Your agent doesn't need sudo. Let's take it away.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>mcp</category>
      <category>python</category>
    </item>
    <item>
      <title>Knowledge Graph Index with NebulaGraph and OpenAI LLM</title>
      <dc:creator>Hassan Mehmood</dc:creator>
      <pubDate>Wed, 06 Dec 2023 04:49:01 +0000</pubDate>
      <link>https://dev.to/hasanmehmood/knowledge-graph-index-with-nebulagraph-and-openai-llm-k35</link>
      <guid>https://dev.to/hasanmehmood/knowledge-graph-index-with-nebulagraph-and-openai-llm-k35</guid>
      <description>&lt;p&gt;This tutorial contains code to set up a Knowledge Graph Index using NebulaGraph as the storage backend and OpenAI's Language Model (LLM) for query processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Load Environment Variables&lt;/strong&gt;: Ensure you have a &lt;code&gt;.env&lt;/code&gt; file set up with required environment variables. Use &lt;code&gt;dotenv&lt;/code&gt; to load them in your Python environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;OPENAI_API_KEY=ak**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```python
import os
from dotenv import load_dotenv

load_dotenv()
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Logging Configuration&lt;/strong&gt;: Configure the logging settings.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logging.DEBUG for more verbose output
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Import Dependencies&lt;/strong&gt;: Import necessary libraries and modules.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Import necessary modules and libraries
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;KnowledgeGraphIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LLMPredictor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ServiceContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.storage.storage_context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.graph_stores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NebulaGraphStore&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.llms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.display&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  NebulaGraph Setup
&lt;/h3&gt;

&lt;p&gt;Ensure NebulaGraph (version 3.5.0 or newer) is set up with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cluster Creation&lt;/strong&gt;: Create a NebulaGraph cluster using one of the following options:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Docker Installation (Machines with Docker Installed)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option 0: Run the command: &lt;code&gt;curl -fsSL nebula-up.siwei.io/install.sh | bash&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Desktop Installation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option 1: Install NebulaGraph Docker Extension from &lt;a href="https://hub.docker.com/extensions/weygu/nebulagraph-dd-ext" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Setup via NebulaGraph Console&lt;/strong&gt;: If the above options are not applicable, manually create the NebulaGraph space, tags, edges, and indexes using the NebulaGraph console. Refer to the provided commands in the code comments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Environment Configuration&lt;/strong&gt;: Set NebulaGraph environment variables.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBULA_USER&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBULA_PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nebula&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# default is "nebula"
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBULA_ADDRESS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:9669&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# assumed NebulaGraph installed locally
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Knowledge Graph Indexing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Graph Structure&lt;/strong&gt;: Define the graph structure (space, tags, edges).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;space_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llamaindex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;edge_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rel_prop_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relationship&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relationship&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;entity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize NebulaGraph Store and Storage Context&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;graph_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NebulaGraphStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;space_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;space_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;edge_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;edge_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rel_prop_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rel_prop_names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;storage_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;graph_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Load Data&lt;/strong&gt;: Load documents/data to be indexed.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create Knowledge Graph Index&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;kg_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KnowledgeGraphIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_triplets_per_chunk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;service_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;service_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;space_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;space_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;edge_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;edge_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rel_prop_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rel_prop_names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;include_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Querying the Knowledge Graph
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize Query Engine&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.query_engine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;KnowledgeGraphQueryEngine&lt;/span&gt;

&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;KnowledgeGraphQueryEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;service_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;service_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Querying&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your question on the data?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Further Customization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Adjust parameters and configurations in the code based on specific requirements or environment setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GITHUB REPO
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hasanmehmood/llamaindex-knowledge-graph" rel="noopener noreferrer"&gt;https://github.com/hasanmehmood/llamaindex-knowledge-graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Github is now free for teams!!</title>
      <dc:creator>Hassan Mehmood</dc:creator>
      <pubDate>Tue, 14 Apr 2020 19:03:44 +0000</pubDate>
      <link>https://dev.to/hasanmehmood/github-is-now-free-for-teams-p09</link>
      <guid>https://dev.to/hasanmehmood/github-is-now-free-for-teams-p09</guid>
      <description>&lt;p&gt;Visit the below link to get full details, Thanks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.blog/2020-04-14-github-is-now-free-for-teams/" rel="noopener noreferrer"&gt;https://github.blog/2020-04-14-github-is-now-free-for-teams/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>news</category>
    </item>
    <item>
      <title>Docker Cheat Sheet</title>
      <dc:creator>Hassan Mehmood</dc:creator>
      <pubDate>Sun, 12 Apr 2020 16:00:22 +0000</pubDate>
      <link>https://dev.to/hasanmehmood/docker-cheat-sheet-57b8</link>
      <guid>https://dev.to/hasanmehmood/docker-cheat-sheet-57b8</guid>
      <description>&lt;h3&gt;
  
  
  CONTAINERS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start a running container from an image&lt;br&gt;
&lt;code&gt;docker run -ti ubuntu bash&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List running containers&lt;br&gt;
&lt;code&gt;docker ps&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List all containers (running + stopped)&lt;br&gt;
&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List last container &lt;br&gt;
&lt;code&gt;docker -l&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete a container after it finishes&lt;br&gt;
&lt;code&gt;docker run -ti --rm ubuntu bash&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit a container and create a new image from it. First find the container id or its name then run the following command. Lets say 1234 is container id and my_container is the name&lt;br&gt;
&lt;code&gt;docker commit 1234 new_image_name&lt;/code&gt;&lt;br&gt;
OR&lt;br&gt;
&lt;code&gt;docker commit my_container new_image_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach an existing running container&lt;br&gt;
&lt;code&gt;docker attach name_of_container&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now leaving container wihtout exiting it&lt;br&gt;
&lt;code&gt;press and hold ctrl + p, ctrl + q&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker exec creates a new process in the existing container. Although it will die automatically if you close the original process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker logs will print the logs of the container&lt;br&gt;
&lt;code&gt;docker logs container_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker kill will kill the running container&lt;br&gt;
&lt;code&gt;docker kill container_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removing containers&lt;br&gt;
&lt;code&gt;docker rm container_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the outside ports are not assigned then it will choose any available port. To see which port it choose, run the following command&lt;br&gt;
&lt;code&gt;docker port container_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  NETWORKS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For displaying list of already existing networks.&lt;br&gt;
&lt;code&gt;docker network ls&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For creating a new network&lt;br&gt;
&lt;code&gt;docker network create new_network_name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for starting a container within a network&lt;br&gt;
&lt;code&gt;docker run -ti --net my_network_name --name my_container_name ubuntu bash&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  VOLUMES
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;2 main varieties of volumes&lt;br&gt;
&lt;strong&gt;Persistent&lt;/strong&gt; --&amp;gt; they will still exist when the contaner is stopped &lt;br&gt;
&lt;strong&gt;Ephemeral&lt;/strong&gt; --&amp;gt; they will be gone when no one (container) is using them&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sharing a volume with the host (Persistant)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -ti -v /full/path/to/folder:/shared_folder ubuntu bash&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sharing a volume b/w containers using volume-from (Ephemeral)&lt;br&gt;
&lt;code&gt;docker run -ti -v /shared-data ubuntu bash&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In above command Im creating a shared volume on the container that is not shared with the host&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now create another container and shared the above volume with the new continer&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -ti --volume-from above_container_name ubuntu bash&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now important note: The above volume will be available as long as atleast one container is still using it. when no container is active that volume will disappear&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git Repo: &lt;a href="https://github.com/hasanmehmood/docker-cheat-sheet" rel="noopener noreferrer"&gt;https://github.com/hasanmehmood/docker-cheat-sheet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
